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 */ @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: 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 */ @entity publicclass 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 */ @service publicclass 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 */ @controller publicclass 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)测试代码是否正常运行了
启动应用程序,访问地址:
查看控制台可以查看:
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]
如果你看到以上的打印信息的话,那么说明缓存成功了。
访问地址:
random1=0.9985031320746356
demoinfocontroller.test1()
二次访问:
loaded=demoinfo [id=1, name=张三, pwd=123456]
cached=demoinfo [id=1, name=张三, pwd=123456]
loaded2=demoinfo [id=2, name=张三, pwd=123456]
这时候所有的数据都是执行缓存的。
这时候执行删除动作:
然后在访问:
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(); } }; } }
这时候在访问地址:
这时候看到的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),希望对大家有所帮助
上一篇: java计算百分比值的方法
推荐阅读
-
Spring Boot集成Redis实现缓存机制(从零开始学Spring Boot)
-
Spring Boot集成Redis实现缓存机制(从零开始学Spring Boot)
-
详解Spring Boot使用redis实现数据缓存
-
详解Spring Boot使用redis实现数据缓存
-
Spring Boot项目利用Redis实现集中式缓存实例
-
Spring Boot项目利用Redis实现集中式缓存实例
-
spring-boot整合ehcache实现缓存机制的方法
-
spring-boot整合ehcache实现缓存机制的方法
-
Spring Boot2(二):使用Spring Boot2集成Mybatis缓存机制
-
spring-boot-2.0.3之redis缓存实现,不是你想的那样哦!