35. Spring Boot整合Redis實現快取機制【從零開始學Spring Boot】
【視訊&交流平臺】
http://study.163.com/course/introduction.htm?courseId=1004329008&utm_campaign=commission&utm_source=400000000155061&utm_medium=share
http://study.163.com/course/introduction.htm?courseId=1004638001&utm_campaign=commission&utm_source=400000000155061&utm_medium=share
https://gitee.com/happyangellxq520/spring-boot
http://412887952-qq-com.iteye.com/blog/2321532
【本文章是否對你有用以及是否有好的建議,請留言】
本文章牽涉到的技術點比較多:Spring Data JPA、Redis、Spring MVC,Spirng Cache,所以在看這篇文章的時候,需要對以上這些技術點有一定的瞭解或者也可以先看看這篇文章,針對文章中實際的技術點在進一步瞭解(注意,您需要自己下載Redis Server到您的本地,所以確保您本地的Redis可用,這裡還使用了MySql資料庫,當然你也可以記憶體資料庫進行測試)。這篇文章會提供對應的Eclipse程式碼示例,具體大體的分如下幾個步驟:
(1)新建Java MavenProject;
(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 mavenproject;
(2)在pom.xml中新增相應的依賴包;
在Maven中新增相應的依賴包,主要有:springboot 父節點依賴;spring boot web支援;快取服務spring-context-support;新增redis支援;JPA操作資料庫;mysql 資料庫驅動,具體pom.xml檔案如下:
<projectxmlns="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.0http://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>
<!-- springboot 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啟動類;
*
* @authorAngel(QQ:412887952)
* @version v.0.1
*/
@SpringBootApplication
public class App {
/**
*-javaagent:.\lib\springloaded-1.2.4.RELEASE.jar -noverify
* @param args
*/
public static voidmain(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:portpairs
#spring.redis.sentinel.nodes=
########################################################
### Java Persistence Api自動進行建表
########################################################
# Specify the DBMS
spring.jpa.database= MYSQL
# Show or not log for each sqlquery
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 tothe 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;
importorg.springframework.cache.CacheManager;
importorg.springframework.cache.annotation.CachingConfigurerSupport;
importorg.springframework.cache.annotation.EnableCaching;
importorg.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
importorg.springframework.data.redis.cache.RedisCacheManager;
importorg.springframework.data.redis.connection.RedisConnectionFactory;
importorg.springframework.data.redis.core.RedisTemplate;
/**
*redis快取配置;
*
*注意:RedisCacheConfig這裡也可以不用繼承 :CachingConfigurerSupport,也就是直接一個普通的Class就好了;
*
*這裡主要我們之後要重新實現 key的生成策略,只要這裡修改KeyGenerator,其它位置不用修改就生效了。
*
*普通使用普通類的方式的話,那麼在使用@Cacheable的時候還需要指定KeyGenerator的名稱;這樣編碼的時候比較麻煩。
*
*@author Angel(QQ:412887952)
*@version v.0.1
*/
@Configuration
@EnableCaching//啟用快取,這個註解很重要;
publicclass RedisCacheConfigextendsCachingConfigurerSupport {
/**
*快取管理器.
*@param redisTemplate
*@return
*/
@Bean
public CacheManagercacheManager(RedisTemplate<?,?>redisTemplate) {
CacheManagercacheManager =newRedisCacheManager(redisTemplate);
returncacheManager;
}
/**
*redis模板操作類,類似於jdbcTemplate的一個類;
*
*雖然CacheManager也能獲取到Cache物件,但是操作起來沒有那麼靈活;
*
*這裡在擴充套件下:RedisTemplate這個類不見得很好操作,我們可以在進行擴充套件一個我們
*
*自己的快取類,比如:RedisStorage類;
*
*@param factory :通過Spring進行注入,引數在application.properties進行配置;
*@return
*/
@Bean
publicRedisTemplate<String, String> redisTemplate(RedisConnectionFactoryfactory) {
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{
privatestaticfinallong serialVersionUID = 1L;
@Id @GeneratedValue
privatelongid;
private Stringname;
private Stringpwd;
publiclong getId() {
returnid;
}
publicvoid setId(longid) {
this.id =id;
}
public StringgetName() {
returnname;
}
publicvoid setName(Stringname) {
this.name =name;
}
public String getPwd(){
returnpwd;
}
publicvoid setPwd(Stringpwd) {
this.pwd =pwd;
}
@Override
public StringtoString() {
return"DemoInfo [id=" +id + ",name=" +name + ", pwd=" +pwd + "]";
}
}
(7)編寫DemoInfoRepository持久化類;
DemoInfoRepository使用Spirng DataJPA實現:
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
*/
publicinterfaceDemoInfoRepositoryextends 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 DemoInfofindById(longid);
publicvoiddeleteFromCache(longid);
void test();
}
com.kfit.service.impl.DemoInfoServiceImpl:
package com.kfit.service.impl;
import javax.annotation.Resource;
importorg.springframework.cache.annotation.CacheEvict;
importorg.springframework.cache.annotation.Cacheable;
importorg.springframework.data.redis.core.RedisTemplate;
importorg.springframework.data.redis.core.ValueOperations;
importorg.springframework.stereotype.Service;
import com.kfit.bean.DemoInfo;
importcom.kfit.repository.DemoInfoRepository;
import com.kfit.service.DemoInfoService;
/**
*
*DemoInfo資料處理類
*
*@author Angel(QQ:412887952)
*@version v.0.1
*/
@Service
publicclass DemoInfoServiceImplimplements DemoInfoService{
@Resource
privateDemoInfoRepositorydemoInfoRepository;
@Resource
privateRedisTemplate<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 DemoInfofindById(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;
importorg.springframework.beans.factory.annotation.Autowired;
importorg.springframework.stereotype.Controller;
importorg.springframework.web.bind.annotation.RequestMapping;
importorg.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(){