当前位置: 首页 > 工具软件 > Angel Redis > 使用案例 >

Spring Boot集成Redis实现缓存机制

蒯慈
2023-12-01
版权声明:本人原创内容,希望大佬在转载时注明出处,感激不尽。 https://412887952-qq-com.iteye.com/blog/2294942

   

      本文章牵涉到的技术点比较多:Spring Data JPA、Redis、Spring MVC,Spirng Cache,所以在看这篇文章的时候,需要对以上这些技术点有一定的了解或者也可以先看看这篇文章,针对文章中实际的技术点在进一步了解(注意,您需要自己下载Redis Server到您的本地,所以确保您本地的Redis可用,这里还使用了MySql数据库,当然你也可以内存数据库进行测试)。这篇文章会提供对应的Eclipse代码示例,具体大体的分如下几个步骤:
(1)新建Java Maven Project;

    这个步骤就不细说,新建一个spring-boot-redis Java maven project;

(2)在pom.xml中添加相应的依赖包;

    在Maven中添加相应的依赖包,主要有:spring boot 父节点依赖;spring boot web支持;缓存服务spring-context-support;添加redis支持;JPA操作数据库;mysql 数据库驱动,具体pom.xml文件如下:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">  
  <modelVersion>4.0.0</modelVersion>  
   
  <groupId>com.kfit</groupId>  
  <artifactId>spring-boot-redis</artifactId>  
  <version>0.0.1-SNAPSHOT</version>  
  <packaging>jar</packaging>  
   
  <name>spring-boot-redis</name>  
  <url>http://maven.apache.org</url>  
   
  <properties>  
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>  
    <!-- 配置JDK编译版本. -->  
    <java.version>1.8</java.version>  
  </properties>  
   
  <!-- spring boot 父节点依赖,  
       引入这个之后相关的引入就不需要添加version配置,  
        spring boot会自动选择最合适的版本进行添加。  
    -->  
    <parent>  
       <groupId>org.springframework.boot</groupId>  
       <artifactId>spring-boot-starter-parent</artifactId>  
       <version>1.3.3.RELEASE</version>  
    </parent>  
   
   
  <dependencies>  
         
        <dependency>  
           <groupId>junit</groupId>  
           <artifactId>junit</artifactId>  
           <scope>test</scope>  
       </dependency>  
   
       <!-- spring boot web支持:mvc,aop... -->  
       <dependency>  
           <groupId>org.springframework.boot</groupId>  
           <artifactId>spring-boot-starter-web</artifactId>  
       </dependency>  
        
       <!--  
           包含支持UI模版(Velocity,FreeMarker,JasperReports),  
           邮件服务,  
           脚本服务(JRuby),  
           缓存Cache(EHCache),  
           任务计划Scheduling(uartz)。  
        -->  
       <dependency>  
          <groupId>org.springframework</groupId>  
          <artifactId>spring-context-support</artifactId>  
        </dependency>  
   
       <!-- 添加redis支持-->  
       <dependency>  
            <groupId>org.springframework.boot</groupId>  
            <artifactId>spring-boot-starter-redis</artifactId>  
        </dependency>  
        
       <!-- JPA操作数据库. -->  
       <dependency>  
          <groupId>org.springframework.boot</groupId>  
          <artifactId>spring-boot-starter-data-jpa</artifactId>  
        </dependency>  
        
       <!-- mysql 数据库驱动. -->  
       <dependency>  
          <groupId>mysql</groupId>  
          <artifactId>mysql-connector-java</artifactId>  
        </dependency>  
         
        <!-- 单元测试. -->  
       <dependency>  
            <groupId>org.springframework.boot</groupId>  
            <artifactId>spring-boot-starter-test</artifactId>  
            <scope>test</scope>  
        </dependency>  
        
  </dependencies>  
</project>  

上面是完整的pom.xml文件,每个里面都进行了简单的注释。

(3)编写Spring Boot启动类(com.kfit.App);

Java代码

package com.kfit;  
import org.springframework.boot.SpringApplication;  
import org.springframework.boot.autoconfigure.SpringBootApplication;  
/** 
 * Spring Boot启动类; 
 * 
 * @author Angel(QQ:412887952) 
 * @version v.0.1 
 */  
   
@SpringBootApplication  
public class App {  
       /** 
        * -javaagent:.\lib\springloaded-1.2.4.RELEASE.jar -noverify 
        * @param args 
        */  
       public static void main(String[] args) {  
              SpringApplication.run(App.class, args);  
       }  
}  
(4)配置application.properties;

    这里主要是配置两个资源,第一就是数据库基本信息;第二就是redis配置;第三就是JPA的配置;


Src/main/resouces/application.properties:

########################################################

###datasource  配置MySQL数据源;

########################################################

spring.datasource.url = jdbc:mysql://localhost:3306/test

spring.datasource.username = root

spring.datasource.password = root

spring.datasource.driverClassName = com.mysql.jdbc.Driver

spring.datasource.max-active=20

spring.datasource.max-idle=8

spring.datasource.min-idle=8

spring.datasource.initial-size=10

 

 

 

########################################################

###REDIS (RedisProperties) redis基本配置;

########################################################

# database name

spring.redis.database=0

# server host1

spring.redis.host=127.0.0.1  

# server password

#spring.redis.password=

#connection port

spring.redis.port=6379

# pool settings ...

spring.redis.pool.max-idle=8
spring.redis.pool.min-idle=0
spring.redis.pool.max-active=8
spring.redis.pool.max-wait=-1

# name of Redis server

#spring.redis.sentinel.master=

# comma-separated list of host:port pairs

#spring.redis.sentinel.nodes=


########################################################
### Java Persistence Api 自动进行建表
########################################################
# Specify the DBMS
spring.jpa.database = MYSQL
# Show or not log for each sql query
spring.jpa.show-sql = true
# Hibernate ddl auto (create, create-drop, update)
spring.jpa.hibernate.ddl-auto = update
# Naming strategy
spring.jpa.hibernate.naming-strategy = org.hibernate.cfg.ImprovedNamingStrategy
# stripped before adding them to the entity manager)
spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.MySQL5Dialect

(5)编写RedisCacheConfig配置类;
    缓存主要有几个要实现的类:其一就是CacheManager缓存管理器;其二就是具体操作实现类;其三就是CacheManager工厂类(这个可以使用配置文件配置的进行注入,也可以通过编码的方式进行实现);其四就是缓存key生产策略(当然Spring自带生成策略,但是在Redis客户端进行查看的话是系列化的key,对于我们肉眼来说就是感觉是乱码了,这里我们先使用自带的缓存策略)。


    
com.kfit.config/RedisCacheConfig:

Java代码

package com.kfit.config;  
   
import org.springframework.cache.CacheManager;  
import org.springframework.cache.annotation.CachingConfigurerSupport;  
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;  
   
/** 
 * redis 缓存配置; 
 * 
 * 注意:RedisCacheConfig这里也可以不用继承:CachingConfigurerSupport,也就是直接一个普通的Class就好了; 
 * 
 * 这里主要我们之后要重新实现 key的生成策略,只要这里修改KeyGenerator,其它位置不用修改就生效了。 
 * 
 * 普通使用普通类的方式的话,那么在使用@Cacheable的时候还需要指定KeyGenerator的名称;这样编码的时候比较麻烦。 
 * 
 * @author Angel(QQ:412887952) 
 * @version v.0.1 
 */  
@Configuration  
@EnableCaching//启用缓存,这个注解很重要;  
public class RedisCacheConfig extends CachingConfigurerSupport {  
     
     
    /** 
     * 缓存管理器. 
     * @param redisTemplate 
     * @return 
     */  
    @Bean  
    public CacheManager cacheManager(RedisTemplate<?,?> redisTemplate) {  
       CacheManager cacheManager = new RedisCacheManager(redisTemplate);  
       return cacheManager;  
    }  
   
     
    /** 
     * redis模板操作类,类似于jdbcTemplate的一个类; 
     * 
     * 虽然CacheManager也能获取到Cache对象,但是操作起来没有那么灵活; 
     * 
     * 这里在扩展下:RedisTemplate这个类不见得很好操作,我们可以在进行扩展一个我们 
     * 
     * 自己的缓存类,比如:RedisStorage类; 
     * 
     * @param factory : 通过Spring进行注入,参数在application.properties进行配置; 
     * @return 
     */  
    @Bean  
    public RedisTemplate<String, String> redisTemplate(RedisConnectionFactory factory) {  
       RedisTemplate<String, String> redisTemplate = new RedisTemplate<String, String>();  
       redisTemplate.setConnectionFactory(factory);  
        
       //key序列化方式;(不然会出现乱码;),但是如果方法上有Long等非String类型的话,会报类型转换错误;  
       //所以在没有自己定义key生成策略的时候,以下这个代码建议不要这么写,可以不配置或者自己实现ObjectRedisSerializer  
       //或者JdkSerializationRedisSerializer序列化方式;  
//     RedisSerializer<String> redisSerializer = new StringRedisSerializer();//Long类型不可以会出现异常信息;  
//     redisTemplate.setKeySerializer(redisSerializer);  
//     redisTemplate.setHashKeySerializer(redisSerializer);  
        
       return redisTemplate;  
    }  
   
}  
 

在以上代码有很详细的注释,在这里还是在简单的提下:

   RedisCacheConfig这里也可以不用继承:CachingConfigurerSupport,也就是直接一个普通的Class就好了;这里主要我们之后要重新实现 key的生成策略,只要这里修改KeyGenerator,其它位置不用修改就生效了。普通使用普通类的方式的话,那么在使用@Cacheable的时候还需要指定KeyGenerator的名称;这样编码的时候比较麻烦。

(6)编写DemoInfo测试实体类;
   编写一个测试实体类:com.kfit.bean.DemoInfo:

Java代码

package com.kfit.bean;  
   
import java.io.Serializable;  
import javax.persistence.Entity;  
import javax.persistence.GeneratedValue;  
import javax.persistence.Id;  
/** 
 * 测试实体类,这个随便; 
 * @author Angel(QQ:412887952) 
 * @version v.0.1 
 */  
@Entity  
public class DemoInfo  implements Serializable{  
    private static final long serialVersionUID = 1L;  
    @Id @GeneratedValue  
    private long id;  
    private String name;  
    private String pwd;  
    public long getId() {  
       return id;  
    }  
    public void setId(longid) {  
       this.id = id;  
    }  
    public String getName() {  
        return name;  
    }  
    publicvoid setName(String name) {  
       this.name = name;  
    }  
    public String getPwd() {  
       return pwd;  
    }  
    publicvoid setPwd(String pwd) {  
       this.pwd = pwd;  
    }  
     
    @Override  
    public String toString() {  
       return "DemoInfo [id=" + id + ", name=" + name + ", pwd=" + pwd + "]";  
    }  
}  
 
(7)编写DemoInfoRepository持久化类;
   DemoInfoRepository使用Spirng Data JPA实现:

com.kfit.repository.DemoInfoRepository:

Java代码


package com.kfit.repository;  
   
import org.springframework.data.repository.CrudRepository;  
   
import com.kfit.bean.DemoInfo;  
   
/** 
 * DemoInfo持久化类 
 * @author Angel(QQ:412887952) 
 * @version v.0.1 
 */  
public interface DemoInfoRepository extends CrudRepository<DemoInfo,Long> {  
   
}  
(8)编写DemoInfoService类;

     编写DemoInfoService,这里有两个技术方面,第一就是使用Spring @Cacheable注解方式和RedisTemplate对象进行操作,具体代码如下:

com.kfit.service.DemoInfoService:

Java代码

package com.kfit.service;  
   
import com.kfit.bean.DemoInfo;  
   
/** 
 * demoInfo 服务接口 
 * @author Angel(QQ:412887952) 
 * @version v.0.1 
 */  
public interface DemoInfoService {  
     
    public DemoInfo findById(long id);  
     
    public void deleteFromCache(long id);  
   
    void test();  
}  
 

com.kfit.service.impl.DemoInfoServiceImpl:

Java代码


package com.kfit.service.impl;  
   
import javax.annotation.Resource;  
   
import org.springframework.cache.annotation.CacheEvict;  
import org.springframework.cache.annotation.Cacheable;  
import org.springframework.data.redis.core.RedisTemplate;  
import org.springframework.data.redis.core.ValueOperations;  
import org.springframework.stereotype.Service;  
   
import com.kfit.bean.DemoInfo;  
import com.kfit.repository.DemoInfoRepository;  
import com.kfit.service.DemoInfoService;  
   
/** 
 * 
 *DemoInfo数据处理类 
 * 
 * @author Angel(QQ:412887952) 
 * @version v.0.1 
 */  
@Service  
public class DemoInfoServiceImpl implements DemoInfoService {  
     
    @Resource  
    private DemoInfoRepository demoInfoRepository;  
     
    @Resource  
    private RedisTemplate<String,String> redisTemplate;  
     
    @Override  
    public void test(){  
       ValueOperations<String,String> valueOperations = redisTemplate.opsForValue();  
       valueOperations.set("mykey4", "random1="+Math.random());  
       System.out.println(valueOperations.get("mykey4"));  
    }  
     
    //keyGenerator="myKeyGenerator"  
    @Cacheable(value="demoInfo") //缓存,这里没有指定key.  
    @Override  
    public DemoInfo findById(longid) {  
       System.err.println("DemoInfoServiceImpl.findById()=========从数据库中进行获取的....id="+id);  
       return demoInfoRepository.findOne(id);  
    }  
     
    @CacheEvict(value="demoInfo")  
    @Override  
    public void deleteFromCache(longid) {  
       System.out.println("DemoInfoServiceImpl.delete().从缓存中删除.");  
    }  
     
}  
 
(9)编写DemoInfoController类;

Java代码


package com.kfit.controller;  
   
import org.springframework.beans.factory.annotation.Autowired;  
import org.springframework.stereotype.Controller;  
import org.springframework.web.bind.annotation.RequestMapping;  
import org.springframework.web.bind.annotation.ResponseBody;  
   
import com.kfit.bean.DemoInfo;  
import com.kfit.service.DemoInfoService;  
   
/** 
 * 测试类. 
 * @author Angel(QQ:412887952) 
 * @version v.0.1 
 */  
@Controller  
public class DemoInfoController {  
     
    @Autowired  
     DemoInfoService demoInfoService;  
       
     
    @RequestMapping("/test")  
    public @ResponseBody String test(){  
        DemoInfo loaded = demoInfoService.findById(1);  
System.out.println("loaded="+loaded);  
DemoInfo cached = demoInfoService.findById(1);  
        System.out.println("cached="+cached);  
        loaded = demoInfoService.findById(2);  
        System.out.println("loaded2="+loaded);  
        return "ok";  
    }  
     
     
    @RequestMapping("/delete")  
    public @ResponseBody String delete(longid){  
        demoInfoService.deleteFromCache(id);  
        return"ok";  
    }  
     
    @RequestMapping("/test1")  
    public @ResponseBody String test1(){  
        demoInfoService.test();  
        System.out.println("DemoInfoController.test1()");  
        return "ok";  
    }  
     
}  
(10)测试代码是否正常运行了

启动应用程序,访问地址:http://127.0.0.1:8080/test

查看控制台可以查看:

DemoInfoServiceImpl.findById()=========从数据库中进行获取的…id=1

loaded=DemoInfo [id=1, name=张三, pwd=123456]

cached=DemoInfo [id=1, name=张三, pwd=123456]

DemoInfoServiceImpl.findById()=========从数据库中进行获取的…id=2

loaded2=DemoInfo [id=2, name=张三, pwd=123456]

如果你看到以上的打印信息的话,那么说明缓存成功了。

访问地址:http://127.0.0.1:8080/test1

random1=0.9985031320746356

DemoInfoController.test1()

二次访问:http://127.0.0.1:8080/test

loaded=DemoInfo [id=1, name=张三, pwd=123456]

cached=DemoInfo [id=1, name=张三, pwd=123456]

loaded2=DemoInfo [id=2, name=张三, pwd=123456]

这时候所有的数据都是执行缓存的。

这时候执行删除动作:http://127.0.0.1:8080/delete?id=1

然后在访问:http://127.0.0.1:8080/test

DemoInfoServiceImpl.findById()=========从数据库中进行获取的....id=1

loaded=DemoInfo [id=1, name=张三, pwd=123456]

cached=DemoInfo [id=1, name=张三, pwd=123456]

loaded2=DemoInfo [id=2, name=张三, pwd=123456]

(11)自定义缓存key;

在com.kfit.config.RedisCacheConfig类中重写CachingConfigurerSupport中的keyGenerator ,具体实现代码如下:

Java代码

/** 
     * 自定义key. 
     * 此方法将会根据类名+方法名+所有参数的值生成唯一的一个key,即使@Cacheable中的value属性一样,key也会不一样。 
     */  
    @Override  
    public KeyGenerator keyGenerator() {  
       System.out.println("RedisCacheConfig.keyGenerator()");  
       return new KeyGenerator() {  
           @Override  
           public Object generate(Object o, Method method, Object... objects) {  
              // This will generate a unique key of the class name, the method name  
              //and all method parameters appended.  
              StringBuilder sb = new StringBuilder();  
              sb.append(o.getClass().getName());  
              sb.append(method.getName());  
              for (Object obj : objects) {  
                  sb.append(obj.toString());  
              }  
              System.out.println("keyGenerator=" + sb.toString());  
              return sb.toString();  
           }  
       };  
    }  
 

这时候在redis的客户端查看key的话还是序列化的肉眼看到就是乱码了,那么我改变key的序列方式,这个很简单,redis底层已经有具体的实现类了,我们只需要配置下:

Java代码

//key序列化方式;(不然会出现乱码;),但是如果方法上有Long等非String类型的话,会报类型转换错误;  
//所以在没有自己定义key生成策略的时候,以下这个代码建议不要这么写,可以不配置或者自己实现ObjectRedisSerializer  
//或者JdkSerializationRedisSerializer序列化方式;  
       RedisSerializer<String> redisSerializer = new StringRedisSerializer();//Long类型不可以会出现异常信息;  
       redisTemplate.setKeySerializer(redisSerializer);  
       redisTemplate.setHashKeySerializer(redisSerializer);  
 

综上以上分析:RedisCacheConfig类的方法调整为:

Java代码

package com.kfit.config;  
   
import java.lang.reflect.Method;  
   
import org.springframework.cache.CacheManager;  
import org.springframework.cache.annotation.CachingConfigurerSupport;  
import org.springframework.cache.annotation.EnableCaching;  
import org.springframework.cache.interceptor.KeyGenerator;  
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.RedisSerializer;  
import org.springframework.data.redis.serializer.StringRedisSerializer;  
   
/** 
 * redis 缓存配置; 
 * 
 * 注意:RedisCacheConfig这里也可以不用继承:CachingConfigurerSupport,也就是直接一个普通的Class就好了; 
 * 
 * 这里主要我们之后要重新实现 key的生成策略,只要这里修改KeyGenerator,其它位置不用修改就生效了。 
 * 
 * 普通使用普通类的方式的话,那么在使用@Cacheable的时候还需要指定KeyGenerator的名称;这样编码的时候比较麻烦。 
 * 
 * @author Angel(QQ:412887952) 
 * @version v.0.1 
 */  
@Configuration  
@EnableCaching//启用缓存,这个注解很重要;  
public class RedisCacheConfig extends CachingConfigurerSupport {  
     
    /** 
     * 缓存管理器. 
     * @param redisTemplate 
     * @return 
     */  
    @Bean  
    public CacheManager cacheManager(RedisTemplate<?,?> redisTemplate) {  
       CacheManager cacheManager = new RedisCacheManager(redisTemplate);  
       return cacheManager;  
    }  
   
     
    /** 
     * RedisTemplate缓存操作类,类似于jdbcTemplate的一个类; 
     * 
     * 虽然CacheManager也能获取到Cache对象,但是操作起来没有那么灵活; 
     * 
     * 这里在扩展下:RedisTemplate这个类不见得很好操作,我们可以在进行扩展一个我们 
     * 
     * 自己的缓存类,比如:RedisStorage类; 
     * 
     * @param factory : 通过Spring进行注入,参数在application.properties进行配置; 
     * @return 
     */  
    @Bean  
    public RedisTemplate<String, String> redisTemplate(RedisConnectionFactory factory) {  
       RedisTemplate<String, String> redisTemplate = new RedisTemplate<String, String>();  
       redisTemplate.setConnectionFactory(factory);  
        
       //key序列化方式;(不然会出现乱码;),但是如果方法上有Long等非String类型的话,会报类型转换错误;  
       //所以在没有自己定义key生成策略的时候,以下这个代码建议不要这么写,可以不配置或者自己实现ObjectRedisSerializer  
       //或者JdkSerializationRedisSerializer序列化方式;  
       RedisSerializer<String> redisSerializer = new StringRedisSerializer();//Long类型不可以会出现异常信息;  
       redisTemplate.setKeySerializer(redisSerializer);  
       redisTemplate.setHashKeySerializer(redisSerializer);  
        
       return redisTemplate;  
    }  
     
    /** 
     * 自定义key. 
     * 此方法将会根据类名+方法名+所有参数的值生成唯一的一个key,即使@Cacheable中的value属性一样,key也会不一样。 
     */  
    @Override  
    public KeyGenerator keyGenerator() {  
       System.out.println("RedisCacheConfig.keyGenerator()");  
       return new KeyGenerator() {  
           @Override  
           public Object generate(Object o, Method method, Object... objects) {  
              // This will generate a unique key of the class name, the method name  
              //and all method parameters appended.  
              StringBuilder sb = new StringBuilder();  
              sb.append(o.getClass().getName());  
              sb.append(method.getName());  
              for (Object obj : objects) {  
                  sb.append(obj.toString());  
              }  
              System.out.println("keyGenerator=" + sb.toString());  
              return sb.toString();  
           }  
       };  
    }  
   
}  

这时候在访问地址:http://127.0.0.1:8080/test

这时候看到的Key就是:com.kfit.service.impl.DemoInfoServiceImplfindById1

在控制台打印信息是:


(1)keyGenerator=com.kfit.service.impl.DemoInfoServiceImplfindById1

(2)DemoInfoServiceImpl.findById()=========从数据库中进行获取的....id=1

(3)keyGenerator=com.kfit.service.impl.DemoInfoServiceImplfindById1

(4)loaded=DemoInfo [id=1, name=张三, pwd=123456]

(5)keyGenerator=com.kfit.service.impl.DemoInfoServiceImplfindById1

(6)cached=DemoInfo [id=1, name=张三, pwd=123456]

(7)keyGenerator=com.kfit.service.impl.DemoInfoServiceImplfindById2

(8)keyGenerator=com.kfit.service.impl.DemoInfoServiceImplfindById2

(10)DemoInfoServiceImpl.findById()=========从数据库中进行获取的....id=2

(11)loaded2=DemoInfo [id=2, name=张三, pwd=123456]

@Cacheable,@CacheEvict简单的介绍
Spring Boot Cache理论篇

在上一篇中我们介绍了Spring Boot集成Redis的实战例子,里面使用到了Spring Cache,那么什么是Spring Cache呢,本章将会做一个理论介绍,至于实战的话,可以在上一章节进行实战测试。

Spring 3.1 引入了激动人心的基于注释(annotation)的缓存(cache)技术,它本质上不是一个具体的缓存实现方案(例如EHCache 或者 OSCache、Redis等),而是一个对缓存使用的抽象,通过在既有代码中添加少量它定义的各种 annotation,即能够达到缓存方法的返回对象的效果。

Spring 的缓存技术还具备相当的灵活性,不仅能够使用 SpEL(Spring Expression Language)来定义缓存的 key 和各种 condition,还提供开箱即用的缓存临时存储方案,也支持和主流的专业缓存例如 EHCache 集成。

其特点总结如下:

· 通过少量的配置 annotation 注释即可使得既有代码支持缓存

· 支持开箱即用 Out-Of-The-Box,即不用安装和部署额外第三方组件即可使用缓存

· 支持 Spring Express Language,能使用对象的任何属性或者方法来定义缓存的 key 和 condition

· 支持 AspectJ,并通过其实现任何方法的缓存支持

· 支持自定义 key 和自定义缓存管理者,具有相当的灵活性和扩展性

我们以前如何自己实现缓存的呢?

以前我们是在service层通过先判断缓存中是否存在缓存数据,如果存在直接返回数据,如果不存在从数据库中进行查询数据的方式,那么我们会发现这种方式的代码耦合型太高了。如果你之前的代码就是这么设计的,那么你可以考虑使用Spring Cache优化你的代码,你的代码将会变得优雅很多。

实现方式主要在方法上加上注解,可以注解的注解类有:

@Cacheable 支持如下几个参数:

value:缓存位置名称,不能为空,如果使用EHCache,就是ehcache.xml中声明的cache的name

key:缓存的key,默认为空,既表示使用方法的参数类型及参数值作为key,支持SpEL

condition:触发条件,只有满足条件的情况才会加入缓存,默认为空,既表示全部都加入缓存,支持SpEL

以下有一个例子:

 //将缓存保存进andCache,并使用参数中的userId加上一个字符串(这里使用方法名称)作为缓存的key   

 @Cacheable(value="andCache",key="#userId + 'findById'")  

 public SystemUser findById(String userId) {  

 SystemUser user = (SystemUser) dao.findById(SystemUser.class, userId);        

   return user ;         

  }  

  //将缓存保存进andCache,并当参数userId的长度小于32时才保存进缓存,默认使用参数值及类型作为缓存的key  

  @Cacheable(value="andCache",condition="#userId.length < 32")  

  public boolean isReserved(String userId) {  

    System.out.println("hello andCache"+userId);  

    return false;  

}  

@CacheEvict 支持如下几个参数:

value:缓存位置名称,不能为空,同上

key:缓存的key,默认为空,同上

condition:触发条件,只有满足条件的情况才会清除缓存,默认为空,支持SpEL

allEntries:true表示清除value中的全部缓存,默认为false

以下是一个小例子:

 //清除掉指定key的缓存  

  @CacheEvict(value="andCache",key="#user.userId + 'findById'")  

  public void modifyUserRole(SystemUser user) {  

           System.out.println("hello andCache delete"+user.getUserId());  

  }  

    

  //清除掉全部缓存  

  @CacheEvict(value="andCache",allEntries=true)  

  public void setReservedUsers() {  

    System.out.println("hello andCache deleteall");  

}  

一般来说,我们的更新操作只需要刷新缓存中某一个值,所以定义缓存的key值的方式就很重要,最好是能够唯一,因为这样可以准确的清除掉特定的缓存,而不会影响到其它缓存值,

比如我这里针对用户的操作,使用(userId+方法名称)的方式设定key值,当然,你也可以找到更适合自己的方式去设定。

@CachePut 注释,这个注释可以确保方法被执行,同时方法的返回值也被记录到缓存中,实现缓存与数据库的同步更新,理解为update语句。
两个例子:
代码: https://pan.baidu.com/s/1qkTkdGn-A6w7q4hcOlgZLA

例子: https://github.com/chenglijunnanduo/springbootRedis

更具体的可以参考:http://hanqunfeng.iteye.com/blog/1158824

 类似资料: