本文章牽涉到的技術點比較多: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文件如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
|
<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);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
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的配置;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
|
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,對于我們肉眼來說就是感覺是亂碼了,這里我們先使用自帶的緩存策略)。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
|
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:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
|
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實現:
1
2
3
4
5
6
7
8
9
10
11
|
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:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
|
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類;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
|
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)測試代碼是否正常運行了
啟動應用程序,訪問地址: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 ,具體實現代碼如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
/** * 自定義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底層已經有具體的實現類了,我們只需要配置下:
1
2
3
4
5
6
|
//key序列化方式;(不然會出現亂碼;),但是如果方法上有Long等非String類型的話,會報類型轉換錯誤; //所以在沒有自己定義key生成策略的時候,以下這個代碼建議不要這么寫,可以不配置或者自己實現ObjectRedisSerializer //或者JdkSerializationRedisSerializer序列化方式; RedisSerializer<String> redisSerializer = new StringRedisSerializer(); //Long類型不可以會出現異常信息; redisTemplate.setKeySerializer(redisSerializer); redisTemplate.setHashKeySerializer(redisSerializer); |
綜上以上分析:RedisCacheConfig類的方法調整為:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
|
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),希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回復大家的。在此也非常感謝大家對服務器之家網站的支持!
原文鏈接:http://blog.csdn.net/gebitan505/article/details/54963622