spring-cache与redis的结合使用

一、导入依赖

<!--spring-cache Redis start -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-cache</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

考虑到需要连接数据库,还需要有以下依赖

<!--  springboot mybatis 整合包   -->
<dependency>
    <groupId>org.mybatis.spring.boot</groupId>
    <artifactId>mybatis-spring-boot-starter</artifactId>
    <version>2.1.3</version>
</dependency>

<!--MySQL依赖 -->
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
</dependency>

二、Redis的配置类

1、申明缓存管理器,会创建一个切面(aspect)并触发Spring缓存注解的切点(pointcut)根据类或者方法所使用的注解以及缓存的状态,这个切面会从缓存中获取数据,将数据添加到缓存之中或者从缓存中移除某个值,

2、创建模板类,做序列化处理

方式一:

import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;

@EnableCaching
@Configuration
public class RedisConfig {

    /**
     * 申明缓存管理器,会创建一个切面(aspect)并触发Spring缓存注解的切点(pointcut)
     * 根据类或者方法所使用的注解以及缓存的状态,这个切面会从缓存中获取数据,将数据添加到缓存之中或者从缓存中移除某个值
     * @return
     */
    @Bean
    public RedisCacheManager cacheManager(RedisConnectionFactory redisConnectionFactory) {
        return RedisCacheManager.create(redisConnectionFactory);
    }

    /**
     * 创建数据存储模板类,做数据序列化处理
     * @param factory
     * @return
     */

    @Bean
    public RedisTemplate redisTemplate(RedisConnectionFactory factory) {
        // 创建一个模板类
        RedisTemplate<String, Object> template = new RedisTemplate<String, Object>();
        // 将刚才的redis连接工厂设置到模板类中
        template.setConnectionFactory(factory);
        // 设置key的序列化器
        template.setKeySerializer(new StringRedisSerializer());
        // 设置value的序列化器
        //使用Jackson 2,将对象序列化为JSON
        Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
        //json转对象类,不设置默认的会将json转成hashmap
        ObjectMapper om = new ObjectMapper();
        om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        jackson2JsonRedisSerializer.setObjectMapper(om);
        template.setValueSerializer(jackson2JsonRedisSerializer);
        return template;
    }
}

方式二:

import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.cache.RedisCacheWriter;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializationContext;

import java.time.Duration;
import java.util.HashMap;
import java.util.Map;

@EnableCaching
@Configuration
public class RedisConfig {

    @Bean
    public CacheManager cacheManager(RedisConnectionFactory redisConnectionFactory) {
        RedisCacheManager redisCacheManager = new RedisCacheManager(
                RedisCacheWriter.nonLockingRedisCacheWriter(redisConnectionFactory),
                // 设置缓存的有效时间,单位秒
                this.getRedisCacheConfigurationWithTtl(600),
                // 指定 key 策略
                this.getRedisCacheConfigurationMap()
        );
        redisCacheManager.setTransactionAware(true);
        return redisCacheManager;
    }

    private Map<String, RedisCacheConfiguration> getRedisCacheConfigurationMap() {
        Map<String, RedisCacheConfiguration> redisCacheConfigurationMap = new HashMap<>(16);
        return redisCacheConfigurationMap;
    }

    private RedisCacheConfiguration getRedisCacheConfigurationWithTtl(Integer seconds) {
        // 指定使用GenericJackson2JsonRedisSerializer序列化方式
        GenericJackson2JsonRedisSerializer genericJackson2JsonRedisSerializer = new GenericJackson2JsonRedisSerializer();

        RedisCacheConfiguration redisCacheConfiguration = RedisCacheConfiguration.defaultCacheConfig();
        redisCacheConfiguration = redisCacheConfiguration.serializeValuesWith(
                RedisSerializationContext
                        .SerializationPair
                        .fromSerializer(genericJackson2JsonRedisSerializer)
        ).entryTtl(Duration.ofSeconds(seconds));
        return redisCacheConfiguration;
    }
}

三、application.properties配置文件内容

server.port=8082

# redis相关配置
spring.redis.database=0
spring.redis.host=127.0.0.1
spring.redis.port=6379
spring.redis.password=123456

# 连接池最大连接数(使用负值表示没有限制)
srping.redis.jedis.pool.max-active =8
# 连接池最大阻塞等待时间(使用负值表示没有限制)
srping.redis.jedis.pool.max-wait=-1ms
# 连接池中的最大空闲连接
srping.redis.jedis.pool.max-idle=8
# 连接池中的最小空闲连接
srping.redis.jedis.pool.min-idle=0
# 连接超时时间(毫秒)默认是2000ms
srping.redis.jedis.pool.timeout=2000ms

## Entry expiration in milliseconds. By default the entries never expire.
spring.cache.type=redis
spring.cache.cache-names=user
spring.cache.redis.time-to-live= 1d
#写入redis时是否使用键前缀。
spring.cache.redis.use-key-prefix= true

#数据库
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/cache?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai
spring.datasource.username=root
spring.datasource.password=123456

 四、业务逻辑增加注解

 @CacheConfig:主要用于配置该类中会用到的一些共用的缓存配置
@Cacheable:主要方法返回值加入缓存。同时在查间时,会先从缓存中取,若不存在再次发起对数据库的访问。

@CachePut:配置于函数上,能够根据参数定义条件进行缓存,与@Cacheable不同的是,每次会真实的调用函数,所以主要用于数据新增和修改操作上。
@CacheEvict:配置于函数上,通常用在删除方法上,用来从缓存中移除对应的数据
@Cachina:置于函数上,组合多个Cache注解使用

特殊说明:以下这两种配置等价

@Cacheable(value = "user")

//@Cacheable(cacheNames = "user")

Person getUserName(Integer id);

五:例子 

//实体类需要进行序列化
@ApiModel("用户实体类")
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User implements Serializable {
    @ApiModelProperty("ID")
    @Min(value = 1,message = "id应该在1-100之间")
    @Max(value = 100000,message = "id应该在1-100之间")
    private Integer id;
    @ApiModelProperty("用户名")
    @Size(min = 1,max = 5,message = "姓名长度应该在1-5之间")
    public String username;
    @ApiModelProperty("密码")
    @Size(min = 1,max = 5,message = "密码长度应该在1-5之间")
    public String password;

}

//业务实现类进行缓存处理

@Service
@CacheConfig(cacheNames = "user")
public class UserRedisServiceImpl implements UserRedisService {

    @Cacheable(value = "user", key = "'user_list_202205091505'")
    @Override
    public List<User> list() {
        System.out.println("=========list");
        User user1 = new User();
        user1.setId(1);
        user1.setName("老大");
        User user2 = new User();
        user2.setId(2);
        user2.setName("老二");
        List<User> users = new ArrayList<>();
        users.add(user1);
        users.add(user2);
        return users;
    }
}

//controller中通过swagger可以进行测试

@ApiOperation("写在controller的方法上的,测试swagger,同时也测试java bean validation,也测试Redis与springcache结合")
@RestController
public class UserController {
    @Autowired
    private UserRedisServiceImpl redisServiceImpl;

    @RequestMapping(value = "/getlist", method = RequestMethod.POST)
    public void getlist() {
        List<User> list = redisServiceImpl.list();
        System.out.println(list);
    }

    @RequestMapping(value = "/getlist1", method = RequestMethod.POST)
    public List<User> getlist1() {
        List<User> list1 = redisServiceImpl.list1();
        System.out.println("<===list1===>" + list1);
        return list1;
    }
}

查看缓存效果

补充知识点:

RedisTemplate和StringRedisTemplate的区别

  1. StringRedisTemplate继承了RedisTemplate。
  2. 两者的数据是不共通的;即:StringRedisTemplate只可以管理StringRedisTemplate里面的数据,RedisTemplate只可以管理RedisTemplate中的数据。
  3. SDR默认采用的序列化策略有两种:String的序列化策略、JDK的序列化策略

【StringRedisTemplate】默认采用String的序列化策略,保存的key和value都是采用此策略序列化进行保存。

【RedisTemplate】默认采用JDK的序列化策略,保存的key和value都是采用此策略序列化进行保存。

RedisTemplate使用的序列类在操作数据的时候,比如说存入数据会将数据先序列化成字节数组然后在存入Redis数据库,这个时候打开Redis查看的时候,你会看到你的数据不是以可读的形式展现的,而是以字节数组显示。当然从Redis获取数据的时候也会默认将数据当做字节数组转化。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值