redis中的缓存介绍 与 spring中注解的使用

目录

1. 作用

2. 集成

2.1 导入需要的包

2.2 redis的属性配置文件

2.3 spring 与redis集成配置

2.3.1 xml方式

2.3.2 程序方式配置

3. 使用示例

3.1 @Cacheable

3.1.1 通过指定的key,将查询结果缓存到redis中

3.1.2 配置key的生成策略

3.1.3 condition

3.2 @CacheEvict

3.3 @CachePut

3.4 @Caching

3.5 @CacheConfig


1. 作用

  • 提升系统的运行效率

  • 简化缓存的使用

2. 集成

2.1 导入需要的包

   <dependency>
      <groupId>redis.clients</groupId>
      <artifactId>jedis</artifactId>
      <version>2.9.0</version>
    </dependency>
     <dependency>
      <groupId>org.springframework.data</groupId>
      <artifactId>spring-data-redis</artifactId>
      <version>1.7.11.RELEASE</version>
    </dependency>
    <dependency>
      <groupId>com.fasterxml.jackson.core</groupId>
      <artifactId>jackson-databind</artifactId>
      <version>2.13.3</version>
    </dependency>

2.2 redis的属性配置文件

redis属性配置文件放在resources目录下

#访问地址
redis.host=192.168.62.147
#访问端口
redis.port=6379
#注意,如果没有password,此处不设置值,但这一项要保留
#redis.password=
​
#最大空闲数,数据库连接的最大空闲时间。超过空闲时间,数据库连接将被标记为不可用,然后被释放。设为0表示无限制。
redis.maxIdle=300
#连接池的最大数据库连接数。设为0表示无限制
redis.maxTotal=600
#最大建立连接等待时间。如果超过此时间将接到异常。设为-1表示无限制。
redis.maxWaitMillis=1000
#在borrow一个jedis实例时,是否提前进行alidate操作;如果为true,则得到的jedis实例均是可用的;
redis.testOnBorrow=true

2.3 spring 与redis集成配置

2.3.1 xml方式

xml配置文件放在resources目录下,已applicationContext-redis.xml命名

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context"
       xmlns:cache="http://www.springframework.org/schema/cache"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd     http://www.springframework.org/schema/cache http://www.springframework.org/schema/cache/spring-cache.xsd">
​
    <!-- 连接池基本参数配置,类似数据库连接池  如果还导入的数据库配置文具 必须也需要加 ignore-unresolvable="true" 否为可能会出现覆盖   -->
    <context:property-placeholder location="classpath:redis.properties"
                                  ignore-unresolvable="true" />
​
    <!-- redis连接池 -->
    <bean id="poolConfig" class="redis.clients.jedis.JedisPoolConfig">
        <property name="maxTotal" value="${redis.maxTotal}" />
        <property name="maxIdle" value="${redis.maxIdle}" />
        <property name="testOnBorrow" value="${redis.testOnBorrow}" />
    </bean>
​
    <!-- 连接池配置,类似数据库连接池 -->
    <bean id="jedisConnectionFactory"
          class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory">
        <property name="hostName" value="${redis.host}"></property>
        <property name="port" value="${redis.port}"></property>
        <!-- <property name="password" value="${redis.pass}"></property> -->
        <property name="poolConfig" ref="poolConfig"></property>
    </bean>
​
    <!--redis操作模版,使用该对象可以操作redis  -->
    <bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate" >
        <property name="connectionFactory" ref="jedisConnectionFactory" />
        <!--如果不配置Serializer,那么存储的时候缺省使用String,如果用User类型存储,那么会提示错误User can't cast to String!!  -->
        <property name="keySerializer" >
            <bean class="org.springframework.data.redis.serializer.StringRedisSerializer" />
        </property>
        <property name="valueSerializer" >
            <bean class="org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer" />
        </property>
        <property name="hashKeySerializer">
            <bean class="org.springframework.data.redis.serializer.StringRedisSerializer"/>
        </property>
        <property name="hashValueSerializer">
            <bean class="org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer"/>
        </property>
        <!--开启事务  -->
        <property name="enableTransactionSupport" value="true"></property>
    </bean >
​
    <!-- 启用缓存 -->
    <cache:annotation-driven cache-manager="cacheManager"/>
​
    <!-- 声明reids缓存管理器 -->
    <bean id="cacheManager" class="org.springframework.data.redis.cache.RedisCacheManager">
        <constructor-arg index="0" ref="redisTemplate"></constructor-arg>
        <!-- 用于指明过期时间 -->
        <!--<property name="expires">
            <map>
                <entry key="students" value="#{60*2}"/>
            </map>
        </property>-->
​
    </bean>
    
    <bean id="customKeyGenerator" 
class="com.zking.mybatisdemo.config.CustomKeyGenerator"/>
​
</beans>

2.3.2 程序方式配置

在源码中,可以新建一个config的包,用于放置配置相关的java文件。

@Configuration
@EnableCaching
public class CacheConfig {
​
​
    private static final Logger log = LoggerFactory.getLogger(CacheConfig.class);
​
​
    @Bean
    public JedisConnectionFactory redisConnectionFactory() throws IOException {
​
        ClassPathResource resource = new ClassPathResource("/redis.properties");
        InputStream in = resource.getInputStream();
        Properties prop = new Properties();
        prop.load(in);
​
        String host = prop.getProperty("redis.host");
        Integer port = Integer.valueOf(prop.getProperty("redis.port"));
        Integer maxIdle = Integer.valueOf(prop.getProperty("redis.maxIdle"));
        Integer maxTotal = Integer.valueOf(prop.getProperty("redis.maxTotal"));
        Integer maxWaitMillis = Integer.valueOf(prop.getProperty("redis.maxWaitMillis"));
        boolean testOnBorrow =  Boolean.valueOf(prop.getProperty("redis.testOnBorrow"));
​
        JedisPoolConfig poolConfig = new JedisPoolConfig();
        poolConfig.setMaxIdle(maxIdle);
        poolConfig.setMaxTotal(maxTotal);
        poolConfig.setMaxWaitMillis(maxWaitMillis);
        poolConfig.setTestOnBorrow(testOnBorrow);
​
        JedisConnectionFactory redisConnectionFactory = new JedisConnectionFactory();
        redisConnectionFactory.setHostName(host);
        redisConnectionFactory.setPort(port);
        redisConnectionFactory.setPoolConfig(poolConfig);
​
        return redisConnectionFactory;
    }
​
​
    @Bean
    public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory cf) {
        RedisTemplate<Object, Object> redisTemplate = new RedisTemplate<>();
        redisTemplate.setConnectionFactory(cf);
​
        GenericJackson2JsonRedisSerializer genericJackson2JsonRedisSerializer = new GenericJackson2JsonRedisSerializer();
​
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        redisTemplate.setValueSerializer(genericJackson2JsonRedisSerializer);
​
        redisTemplate.setHashKeySerializer(new StringRedisSerializer());
        redisTemplate.setHashValueSerializer(genericJackson2JsonRedisSerializer);
        return redisTemplate;
    }
​
​
    @Bean
    public StringRedisTemplate stringRedisTemplate(RedisConnectionFactory factory) {
        StringRedisTemplate stringRedisTemplate = new StringRedisTemplate();
        stringRedisTemplate.setConnectionFactory(factory);
        return stringRedisTemplate;
    }
​
​
    @Bean
    public CacheManager cacheManager(RedisTemplate redisTemplate) {
        RedisCacheManager cacheManager = new RedisCacheManager(redisTemplate);
        //这里可以设置一个默认的过期时间
        cacheManager.setDefaultExpiration(300);
        return cacheManager;
    }
​
    @Bean
    public KeyGenerator customKeyGenerator() {
        return new KeyGenerator() {
            @Override
            public Object generate(Object o, Method method, Object... params) {
                StringBuilder sb = new StringBuilder();
                sb.append(o.getClass().getName());
                sb.append(method.getName());
                for (Object obj : params) {
                    sb.append(obj.toString());
                }
                return sb.toString();
            }
        };
    }
​
}

3. 使用示例

常用注解:

  • @Cacheable 主要针对方法配置,能够根据方法的请求参数对其结果进行缓存

  • @CacheEvict 主要针对方法配置,能够根据一定的条件对缓存进行清空

  • @CachePut 更新缓存(不会影响到方法的运行),这个注释可以确保方法被执行,同时方法的返回值也被记录到缓存中,实现缓存与数据库的同步更新。

  • @Caching 重新组合要应用于方法的多个缓存操作

  • @CacheConfig 设置类级别上共享的一些常见缓存设置

3.1 @Cacheable

3.1.1 通过指定的key,将查询结果缓存到redis中

@Service
public class StudentService implements IStudentService {
​
    @Resource
    private StudentMapper studentMapper;
​
    @Cacheable(value = "students",key = "#student.toString()")
    @Override
    public List<Student> list(Student student) {
        return studentMapper.list(student);
    }
​
}

​​​​​​​

属性 描述 示例
methodName 当前方法名 #root.methodName
method 当前方法 #root.method.name
target 当前被调用的对象 #root.target
targetClass 当前被调用的对象的class #root.targetClass
args 当前方法参数组成的数组 #root.args[0]
caches 当前被调用的方法使用的Cache #root.caches[0].name

3.1.2 配置key的生成策略

1) xml配置文件方式

编写自定义key生成器

public class CustomKeyGenerator implements KeyGenerator {
​
    @Override
    public Object generate(Object target, Method method, Object... params) {
        StringBuilder sb = new StringBuilder();
        sb.append(target.getClass().getName());
        sb.append(method.getName());
        for (Object obj : params) {
            sb.append(obj.toString());
        }
        return sb.toString();
    }
}
    <!-- 启用注解式缓存 -->
    <cache:annotation-driven cache-manager="cacheManager" key-generator="customKeyGenerator"/>
    
    <!--自定义key生成器-->
    <bean id="customKeyGenerator" class="com.zking.mybatisdemo.config.CustomKeyGenerator"/>

2) java配置方式

@Configuration
@EnableCaching
public class CacheConfig extends CachingConfigurerSupport {
​
    private static final Logger log = LoggerFactory.getLogger(CacheConfig.class);
​
    ......
​
    @Bean
    public CacheManager cacheManager(RedisTemplate redisTemplate) {
        RedisCacheManager cacheManager = new RedisCacheManager(redisTemplate);
        //这里可以设置一个默认的过期时间
        cacheManager.setDefaultExpiration(300);
        return cacheManager;
    }
​
    @Bean(name="customKeyGenerator")
    public KeyGenerator customKeyGenerator() {
        return new CustomKeyGenerator();
    }
​
    //配置自定义key生成器
    @Override
    public KeyGenerator keyGenerator() {
        return new CustomKeyGenerator();
    }
​
}

注意: 该类必须继承CachingConfigurerSupport类,并重写其中的keyGenerator方法。

配置默认的生成策略后,如果没有指定key,则使用默认的生成策略, 如:

    @Cacheable(value = "students")
    @Override
    public List<Student> list(Student student) {
        return studentMapper.list(student);
    }

3) 除默认key生成策略外,还可以指定key,或指定生成策略,如果一下示例:

    @Cacheable(value = "students", key = "'sname:' + #student.sname")
    @Override
    public List<Student> list(Student student) {
        return studentMapper.list(student);
    }
​
    @Override
    @Cacheable(value="student",keyGenerator = "customKeyGenerator")
    public Student load(String sid) {
        return studentMapper.load(Integer.valueOf(sid));
    }

3.1.3 condition

只对学生名称以“李”字开发的的查询执行缓存,否则不进行缓存, 代码如下:

    @Cacheable(value = "students", key = "'sname:' + #student.sname", condition = "#student.sname.equals('李')")
    @Override
    public List<Student> list(Student student) {
        return studentMapper.list(student);
    }

可以使用unless参数否决向缓存添加值。

3.2 @CacheEvict

主要针对方法配置,能够根据一定的条件对缓存进行清空

示例:

   @Override
    @Cacheable(value="student", key="#sid.toString()")
    public Student load(Integer sid) {
        return studentMapper.load(sid);
    }
​
​
    @CacheEvict(value="student", key="T(Integer).toString(#student.sid)")
    //@CacheEvict(value="student", key="#student.sid + ''")
    @Override
    public void update(Student student) {
        studentMapper.update(student);
    }

测试代码:

    @Test
    public void load() {
        Student student = studentService.load(197);
        System.out.println(student);
    }
​
    @Test
    public void update() {
        Student student = new Student();
        student.setSid(197);
        student.setSname("曹雪学");
        student.setAge(56);
        student.setRemark("测试");
        studentService.update(student);
    }

先运行load测试, 会将sid为197的学生信息缓存,然后再运行update,会将sid为197的学习信息从缓存中删除。

使用allEntries属性从缓存中退出所有条目。如下示例:

   
 @CacheEvict(cacheNames="books", allEntries=true)
    @Override
    public void update(Student student) {
        studentMapper.update(student);
    }

清除操作默认是在对应方法成功执行之后触发的,即方法如果因为抛出异常而未能成功返回时也不会触发清除操作。使用beforeInvocation可以改变触发清除操作的时间,当我们指定该属性值为true时,Spring会在调用该方法之前清除缓存中的指定元素 示例:

@CacheEvict(value="users", beforeInvocation=true)

3.3 @CachePut

对于使用@Cacheable标注的方法,Spring在每次执行前都会检查Cache中是否存在相同key的缓存元素,如果存在就不再执行该方法,而是直接从缓存中获取结果进行返回,否则才会执行并将返回结果存入指定的缓存中。@CachePut也可以声明一个方法支持缓存功能。与@Cacheable不同的是使用@CachePut标注的方法在执行前不会去检查缓存中是否存在之前执行过的结果,而是每次都会执行该方法,并将执行结果以键值对的形式存入指定的缓存中。

示例:

    @Override
    //@Cacheable(value="student", key="#sid.toString()")
    @CachePut(value = "student", key="#sid.toString()")
    public Student load(Integer sid) {
        return studentMapper.load(sid);
    }

注意: @CachePut 与 @Cacheable 之间的差别,@CachePut不会去检查缓存中是否有值, 每次都会通过获取获取数据填充到缓存中去。

3.4 @Caching

有时,需要指定相同类型的多个注释(如@CacheEvict或@CachePut) 例如,因为不同缓存之间的条件或键表达式不同。@Caching允许在同一方法上使用多个嵌套的@Cacheable、@CachePut和@CacheEvict注释。

示例代码如下:

@Caching(evict = { @CacheEvict("primary"), @CacheEvict(cacheNames="secondary", key="#p0") }) public Book importBooks(String deposit, Date date) {
   .....
}

3.5 @CacheConfig

缓存提供了许多的注解选项,但是有一些公用的操作,我们可以使用@CacheConfig在类上进行全局设置。

@CacheConfig(keyGenerator = "customKeyGenerator")
public class StudentService implements IStudentService {
    
    @Cacheable(value = "students")
    @Override
    public List<Student> list(Student student) {
        return studentMapper.list(student);
    }
    ....
 }

猜你喜欢

转载自blog.csdn.net/qq_62898618/article/details/127832746