虚位以待(AD)
虚位以待(AD)
首页 > 软件编程 > Java编程 > Spring Boot集成Redis实现缓存机制(从零开始学Spring Boot)

Spring Boot集成Redis实现缓存机制(从零开始学Spring Boot)
类别:Java编程   作者:码皇   来源:互联网   点击:

这篇文章主要介绍了Spring Boot集成Redis实现缓存机制(从零开始学Spring Boot),需要的朋友可以参考下

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

(1)新建Java Maven Project;
(2)在pom.xml中添加相应的依赖包;
(3)编写Spring Boot启动类;
(4)配置application.properties;
(5)编写RedisCacheConfig配置类;
(6)编写DemoInfo测试实体类;
(7)编写DemoInfoRepository持久化类;
(8)编写DemoInfoService类;
(9)编写DemoInfoController类;
(10)测试代码是否正常运行了
(11)自定义缓存key;

(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);

    package com.kfit;
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    /** * Spring Boot启动类;
    * * @author Angel(QQ:412887952) * @version v.0.1 */@SpringBootApplicationpublic class App {
    /** * -javaagent:.libspringloaded-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/testspring.datasource.username = rootspring.datasource.password = rootspring.datasource.driverClassName = com.mysql.jdbc.Driverspring.datasource.max-active=20spring.datasource.max-idle=8spring.datasource.min-idle=8spring.datasource.initial-size=10###########################################################REDIS (RedisProperties) redis基本配置;######################################################### database namespring.redis.database=0# server host1spring.redis.host=127.0.0.1 # server password#spring.redis.password=#connection portspring.redis.port=6379# pool settings ...spring.redis.pool.max-idle=8spring.redis.pool.min-idle=0spring.redis.pool.max-active=8spring.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 DBMSspring.jpa.database = MYSQL# Show or not log for each sql queryspring.jpa.show-sql = true# hibernate ddl auto (create, create-drop, update)spring.jpa.hibernate.ddl-auto = update# Naming strategyspring.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: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//启用缓存,这个注解很重要;publicclass RedisCacheConfig extends CachingConfigurerSupport {
    /** * 缓存管理器. * @param redisTemplate * @return */ @Bean public CacheManager cacheManager(RedisTemplate<?,?> redisTemplate) {
    CacheManager cacheManager = new RedisCacheManager(redisTemplate);
    returncacheManager;
    }
    /** * 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);
    returnredisTemplate;
    }
    }

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

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

(6)编写DemoInfo测试实体类;

       编写一个测试实体类:com.kfit.bean.DemoInfo:

    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 */@Entitypublicclass DemoInfo implements Serializable{
    privatestaticfinallongserialVersionUID = 1L;
    @Id@GeneratedValue privatelongid;
    private String name;
    private String pwd;
    publiclong getId() {
    returnid;
    }
    publicvoid setId(longid) {
    this.id = id;
    }
    public String getName() {
    returnname;
    }
    publicvoid setName(String name) {
    this.name = name;
    }
    public String getPwd() {
    returnpwd;
    }
    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:package com.kfit.repository;
    import org.springframework.data.repository.CrudRepository;
    import com.kfit.bean.DemoInfo;
    /** * DemoInfo持久化类 * @author Angel(QQ:412887952) * @version v.0.1 */publicinterface DemoInfoRepository extends CrudRepository<DemoInfo,Long> {
    }

(8)编写DemoInfoService类;

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

com.kfit.service.DemoInfoService:

    package com.kfit.service;
    import com.kfit.bean.DemoInfo;
    /** * demoInfo 服务接口 * @author Angel(QQ:412887952) * @version v.0.1 */publicinterface DemoInfoService {
    public DemoInfo findById(longid);
    publicvoid deleteFromCache(longid);
    void test();
    }
    com.kfit.service.impl.DemoInfoServiceImpl: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 */@Servicepublicclass DemoInfoServiceImpl implements DemoInfoService {
    @Resource private DemoInfoRepository demoInfoRepository;
    @Resource private RedisTemplate<String,String> redisTemplate;
    @Override publicvoid 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);
    returndemoInfoRepository.findOne(id);
    }
    @CacheEvict(value="demoInfo") @Override publicvoid deleteFromCache(longid) {
    System.out.println("DemoInfoServiceImpl.delete().从缓存中删除.");
    }
    }

(9)编写DemoInfoController类;

    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 */@Controllerpublicclass 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 ,具体实现代码如下:

    /** * 自定义key. * 此方法将会根据类名+方法名+所有参数的值生成唯一的一个key,即使@Cacheable中的value属性一样,key也会不一样。 */ @Override public KeyGenerator keyGenerator() {
    System.out.println("RedisCacheConfig.keyGenerator()");
    returnnew 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());
    returnsb.toString();
    }
    }
    ;
    }

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

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

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

    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//启用缓存,这个注解很重要;publicclass RedisCacheConfig extends CachingConfigurerSupport {
    /** * 缓存管理器. * @param redisTemplate * @return */ @Bean public CacheManager cacheManager(RedisTemplate<?,?> redisTemplate) {
    CacheManager cacheManager = new RedisCacheManager(redisTemplate);
    returncacheManager;
    }
    /** * 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);
    returnredisTemplate;
    }
    /** * 自定义key. * 此方法将会根据类名+方法名+所有参数的值生成唯一的一个key,即使@Cacheable中的value属性一样,key也会不一样。 */ @Override public KeyGenerator keyGenerator() {
    System.out.println("RedisCacheConfig.keyGenerator()");
    returnnew 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());
    returnsb.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集成Redis实现缓存机制(从零开始学Spring Boot),希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对脚本之家网站的支持!

相关热词搜索: springboot redis缓存 从零开始学springbo