【spring boot】在Java中操作缓存:


一、Jedis

在这里插入图片描述

<dependency>
  <groupId>junit</groupId>
  <artifactId>junit</artifactId>
  <version>4.12</version>
</dependency>
<dependency>
   <groupId>redis.clients</groupId>
   <artifactId>jedis</artifactId>
   <version>2.8.0</version>
</dependency>

在这里插入图片描述

二、Spring Data Redis(常用)

【1】pom.xml
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
【2】application.yml

在这里插入图片描述

spring:
  redis:    #redis配置
    host: localhost
    port: 6379
    #password:
    database: 0   #默认提供16个数据库,0:0号数据库
    jedis:
      pool:  #redis连接池配置
        max-active: 8   #最大连接数
        max-idle: 4     #最大空闲连接
        max-wait: 1ms   #最大阻塞等待时间
        min-idle: 0     #最小空闲连接

在这里插入图片描述

【3】RedisConfig
package com.example.ruijiwaimai.config;

import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.StringRedisSerializer;

@Configuration
public class RedisConfig extends CachingConfigurerSupport {
    
    
    @Bean
    public RedisTemplate<Object,Object> redisTemplate(RedisConnectionFactory connectionFactory){
    
    
        RedisTemplate<Object,Object> redisTemplate=new RedisTemplate<>();

        // 默认的key序列化器为:JdkSerializationRedisSerializer
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        redisTemplate.setHashKeySerializer(new StringRedisSerializer());
        redisTemplate.setConnectionFactory(connectionFactory);
        return redisTemplate;
    }
}
【4】RuiJiWaiMaiApplicationTests
package com.example.ruijiwaimai;

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.redis.connection.DataType;
import org.springframework.data.redis.core.*;

import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;

@SpringBootTest
class RuiJiWaiMaiApplicationTests {
    
    

    @Autowired
    private RedisTemplate redisTemplate;

    /*
     * 操作String类型数据=>ValueOperations:简单K-V操作
     * */
    @Test
    public void testString() {
    
    
        redisTemplate.opsForValue().set("city123", "shenzhen");    //  \xac\xed\x00\x05t\x00\x04city做了序列化,无法用get city获取=》config配置RedisConfig
        String value = (String) redisTemplate.opsForValue().get("city123");
        System.out.println(value);

        redisTemplate.opsForValue().set("key1", "value1", 10, TimeUnit.SECONDS);

        Boolean aBoolean = redisTemplate.opsForValue().setIfAbsent("city1234", "nanjing");
        System.out.println(aBoolean);
    }

    /*
     * 操作Hash类型数据=>HashOperations:针对map类型的数据操作
     * */
    @Test
    public void testHash() {
    
    
        HashOperations hashOperations = redisTemplate.opsForHash();
        hashOperations.put("002", "name", "xiaoming");
        hashOperations.put("002", "age", "20");

        String age = (String) hashOperations.get("002", "age");
        System.out.println(age);

        // 获取所有字段
        Set keys = hashOperations.keys("002");
        for (Object key : keys) {
    
    
            System.out.println(key);
        }
        // 获取所有值
        List values = hashOperations.values("002");
        for (Object value : values) {
    
    
            System.out.println(value);
        }
    }

    /*
     * 操作List类型数据=>ListOperations:针对list类型的数据操作
     * */
    @Test
    public void testList() {
    
    
        ListOperations listOperations = redisTemplate.opsForList();
        //存值
        listOperations.leftPush("mylist", "a");
        listOperations.leftPushAll("mylist", "b", "c", "d");
        //取值
        List<String> mylist = listOperations.range("mylist", 0, -1);
        for (String value : mylist) {
    
    
            System.out.println(value);
        }
        //获得列表长度
        Long size = listOperations.size("mylist");
        int lSize = size.intValue();
        for (int i = 0; i < lSize; i++) {
    
    
            //出队列
            Object element = listOperations.rightPop("mylist");
            System.out.println("出队列:" + element);
        }
    }

    /*
     * 操作Set(无序集合)类型数据=>SetOperations:set类型数据操作
     * */
    @Test
    public void testSet() {
    
    
        SetOperations setOperations = redisTemplate.opsForSet();
        //存值
        setOperations.add("myset", "a", "b", "c", "a");
        //取值
        Set<String> myset = setOperations.members("myset");
        for (String o : myset) {
    
    
            System.out.println(o);
        }
        //删除成员
        setOperations.remove("myset", "a", "b");

        myset = setOperations.members("myset");
        for (String o : myset) {
    
    
            System.out.println("删除后的数据:" + o);
        }
    }

    /*
     * 操作ZSet(有序集合)类型数据=>ZSetOperations:zset类型数据操作
     * */
    @Test
    public void testZSet() {
    
    
        ZSetOperations zSetOperations = redisTemplate.opsForZSet();
        //存值
        zSetOperations.add("myZset", "a", 10.0);
        zSetOperations.add("myZset", "b", 11.0);
        zSetOperations.add("myZset", "c", 12.0);
        zSetOperations.add("myZset", "a", 13.0);
        //取值
        Set<String> myZet = zSetOperations.range("myZset", 0, -1);
        for (String s : myZet) {
    
    
            System.out.println(s);
        }
        //修改分数
        zSetOperations.incrementScore("myZset", "b", 20.0);
        myZet = zSetOperations.range("myZset", 0, -1);
        for (String s : myZet) {
    
    
            System.out.println("修改分数: " + s);
        }
        //删除成员
        zSetOperations.remove("myZset", "a", "b");
        myZet = zSetOperations.range("myZset", 0, -1);
        for (String s : myZet) {
    
    
            System.out.println("删除后的成员: " + s);
        }
    }

    /*
     * 通用操作
     * */
    @Test
    public void testCommon() {
    
    
        //获取redis中所有的key
        Set keys = redisTemplate.keys("*");
        for (Object key : keys) {
    
    
            System.out.println(key);
        }
        //判断某个key是否存在
        Boolean itcast = redisTemplate.hasKey("itcast");
        System.out.println("判断某个key是否存在:"+itcast);
        //删除指定key
        redisTemplate.delete("myZset");
        //获取指定key对应的value的数据类型
        DataType dataType = redisTemplate.type("001");
        System.out.println("获取指定key对应的value的数据类型:"+dataType.name());
    }
}

在这里插入图片描述

三、Spring Cache

【1】常用注解:
注解 说明
@EnableCaching 开启缓存注解功能
@Cacheable 判断是否有缓存数据,有=》返回缓存数据;没有=》放到缓存中
@CachePut 将方法的返回值放到缓存中
@CacheEvict 将一条或多条数据从缓存中删除
【2】使用案例
package com.itheima.controller;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.itheima.entity.User;
import com.itheima.service.UserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.web.bind.annotation.*;
import java.util.ArrayList;
import java.util.List;

@RestController
@RequestMapping("/user")
@Slf4j
public class UserController {
    
    

    @Autowired
    private CacheManager cacheManager;

    @Autowired
    private UserService userService;

    /**
     * CachePut:将方法返回值放入缓存
     * value:缓存的名称,每个缓存名称下面可以有多个key
     * key:缓存的key
     */
    @CachePut(value = "userCache",key = "#user.id")
    @PostMapping
    public User save(User user){
    
    
        userService.save(user);
        return user;
    }

    /**
     * CacheEvict:清理指定缓存
     * value:缓存的名称,每个缓存名称下面可以有多个key
     * key:缓存的key
     */
    @CacheEvict(value = "userCache",key = "#p0")
    //@CacheEvict(value = "userCache",key = "#root.args[0]")
    //@CacheEvict(value = "userCache",key = "#id")
    @DeleteMapping("/{id}")
    public void delete(@PathVariable Long id){
    
    
        userService.removeById(id);
    }

    //@CacheEvict(value = "userCache",key = "#p0.id")
    //@CacheEvict(value = "userCache",key = "#user.id")
    //@CacheEvict(value = "userCache",key = "#root.args[0].id")
    @CacheEvict(value = "userCache",key = "#result.id")
    @PutMapping
    public User update(User user){
    
    
        userService.updateById(user);
        return user;
    }

    /**
     * Cacheable:在方法执行前spring先查看缓存中是否有数据,如果有数据,则直接返回缓存数据;若没有数据,调用方法并将方法返回值放到缓存中
     * value:缓存的名称,每个缓存名称下面可以有多个key
     * key:缓存的key
     * condition:条件,满足条件时才缓存数据
     * unless:满足条件则不缓存
     */
    @Cacheable(value = "userCache",key = "#id",unless = "#result == null")
    @GetMapping("/{id}")
    public User getById(@PathVariable Long id){
    
    
        User user = userService.getById(id);
        return user;
    }

    @Cacheable(value = "userCache",key = "#user.id + '_' + #user.name")
    @GetMapping("/list")
    public List<User> list(User user){
    
    
        LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(user.getId() != null,User::getId,user.getId());
        queryWrapper.eq(user.getName() != null,User::getName,user.getName());
        List<User> list = userService.list(queryWrapper);
        return list;
    }
}
【3】底层不使用redis,重启服务,内存丢失=>解决:
pom.xml
<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-cache</artifactId>
</dependency>
application.yml

在这里插入图片描述

  redis:    #redis配置
    host: 192.168.139.128
    port: 6379
    #password:
    database: 0   #默认提供16个数据库,0;0号数据库
  cache:
    redis:
      time-to-live: 1800000 #设置缓存数据的过期时间
启动类:

在这里插入图片描述

Result:

在这里插入图片描述

注解使用:
    @PostMapping()
    @CacheEvict(value = "setmealCache",allEntries = true)
    public Result<String> save(@RequestBody SetmealDto setmealDto) {
    
    
        log.info("套餐信息:{}", setmealDto);
        setmealService.saveWithDish(setmealDto);
        return null;
    }
    
    //删除套餐
    @DeleteMapping()
    @CacheEvict(value = "setmealCache",allEntries = true)//清除setmealCache下的所有缓存
    public Result<String> delete(@RequestParam List<Long> ids){
    
    
        setmealService.removeWithDish(ids);
        return Result.success("套餐数据删除成功");
    }

    /**
     * 根据条件查询套餐数据
     * @param setmeal
     * @return
     */
    @GetMapping("/list")
    @Cacheable(value = "setmealCache",key = "#setmeal.categoryId + '_' + #setmeal.status")
    public Result<List<Setmeal>> list(Setmeal setmeal){
    
    
        LambdaQueryWrapper<Setmeal> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(setmeal.getCategoryId() != null,Setmeal::getCategoryId,setmeal.getCategoryId());
        queryWrapper.eq(setmeal.getStatus() != null,Setmeal::getStatus,setmeal.getStatus());
        queryWrapper.orderByDesc(Setmeal::getUpdateTime);

        List<Setmeal> list = setmealService.list(queryWrapper);

        return Result.success(list);
    }

猜你喜欢

转载自blog.csdn.net/weixin_53791978/article/details/129678469