1. 程式人生 > >35. Spring Boot整合Redis實現快取機制【從零開始學Spring Boot】

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),

任務計劃Schedulinguartz)。

               -->

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