【Spring Boot學習總結】14.Spring Boot整合Redis-與傳統方式對比
前面我們講解了如何使用Spring Boot來控制事務,下面我們來講解一下如何使用Spring Boot來整合Redis
為了對比傳統工程與Spring Boot整合的不同,以及彰顯Spring Boot整合的優勢,我們會逐一剖析傳統整合方式與Spring Boot整合方式。
一、傳統方式整合Redis
在不使用Spring Boot的傳統工程中,我們使用XML配置檔案來整合Redis。首先在POM檔案中引入Redis的相關依賴:
<dependency> <groupId>org.springframework.data</groupId> <artifactId>spring-data-redis</artifactId> <version>1.6.0.RELEASE</version> </dependency> <dependency> <groupId>redis.clients</groupId> <artifactId>jedis</artifactId> <version>2.7.3</version> </dependency>
然後建立一個redis.properties檔案,用於配置redis的連線資訊:
# Redis伺服器地址 redis.host=127.0.0.1 # Redis伺服器連線埠 redis.port=6379 # Redis伺服器連線密碼(預設為空) redis.pass=password redis.dbIndex=0 # Redis中Key的過期時間 redis.expiration=3000 # 連線池中的最大空閒連線 redis.maxIdle=300 # 連線池最大連線數(使用負值表示沒有限制) redis.maxActive=600 # 連線池最大阻塞等待時間(使用負值表示沒有限制) redis.maxWait=1000 redis.testOnBorrow=true
然後在Spring的配置檔案中(含有資料來源、sessionFactory等Bean配置的檔案),新增Redis的配置:
<!-- redis config start --> <!-- 配置JedisPoolConfig例項 --> <bean id="poolConfig" class="redis.clients.jedis.JedisPoolConfig"> <property name="maxIdle" value="${redis.maxIdle}" /> <property name="maxTotal" value="${redis.maxActive}" /> <property name="maxWaitMillis" value="${redis.maxWait}" /> <property name="testOnBorrow" value="${redis.testOnBorrow}" /> </bean> <!-- 配置JedisConnectionFactory --> <bean id="jedisConnectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory"> <property name="hostName" value="${redis.host}" /> <property name="port" value="${redis.port}" /> <property name="password" value="${redis.pass}" /> <property name="database" value="${redis.dbIndex}" /> <property name="poolConfig" ref="poolConfig" /> </bean> <!-- 配置RedisTemplate --> <bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate"> <property name="connectionFactory" ref="jedisConnectionFactory" /> </bean> <!-- 配置RedisCacheManager --> <bean id="redisCacheManager" class="org.springframework.data.redis.cache.RedisCacheManager"> <constructor-arg name="redisOperations" ref="redisTemplate" /> <property name="defaultExpiration" value="${redis.expiration}" /> </bean> <!-- 配置RedisCacheConfig --> <bean id="redisCacheConfig" class="com.ssm.utils.RedisCacheConfig"> <constructor-arg ref="jedisConnectionFactory" /> <constructor-arg ref="redisTemplate" /> <constructor-arg ref="redisCacheManager" /> </bean> <!-- redis config end -->
其中分別配置了JedisPoolConfig、JedisConnectionFactory、RedisTemplate、RedisCacheManager、RedisCacheConfig,其中:
(1)JedisPoolConfig
JedisPoolConfig類中設定了redis連線池的配置資訊,用於通過配置資訊來控制redis資料庫連線池的一些連線操作。
(2)JedisConnectionFactory
JedisConnectionFactory類為redis資料庫的連線工廠類,類似引入了DataSource的SqlSessionFactory資料庫會話工廠。
該類通過配置的redis資料庫的連線資訊,來與redis資料庫進行連線操作,並返回相應的連線例項物件。
(3)RedisTemplate
RedisTemplate類是redis操作類,通過引入JedisConnectionFactory連線工廠獲取連線,對外提供redis的各種操作API,
在專案中可以直接使用RedisTemplate類來進行redis資料庫的操作。
(4)RedisCacheManager
RedisCacheManager為redis自定義的工具類,在構造方法中引入了RedisTemplate,旨在對redis資料庫中的key-value資料進行管理,例如設定了key的失效時間等。
(5)RedisCacheConfig
RedisCacheConfig類是需要開發者自定義的類,用於為redis做統一的排程和管理。該類需繼承CachingConfigurerSupport父類,分別注入了JedisConnectionFactory、RedisTemplate以及RedisCacheManager。
下面是一個自定義RedisCacheConfig:
package com.ssm.utils;
import java.lang.reflect.Method;
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.jedis.JedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
/**
* 通過spring管理redis快取配置
* @author Administrator
*/
@Configuration
@EnableCaching
public class RedisCacheConfig extends CachingConfigurerSupport {
private volatile JedisConnectionFactory jedisConnectionFactory;
private volatile RedisTemplate<String, String> redisTemplate;
private volatile RedisCacheManager redisCacheManager;
public RedisCacheConfig() {
super();
}
/**
* 帶引數的構造方法 初始化所有的成員變數
*
* @param jedisConnectionFactory
* @param redisTemplate
* @param redisCacheManager
*/
public RedisCacheConfig(JedisConnectionFactory jedisConnectionFactory, RedisTemplate<String, String> redisTemplate,
RedisCacheManager redisCacheManager) {
this.jedisConnectionFactory = jedisConnectionFactory;
this.redisTemplate = redisTemplate;
this.redisCacheManager = redisCacheManager;
}
public JedisConnectionFactory getJedisConnecionFactory() {
return jedisConnectionFactory;
}
public RedisTemplate<String, String> getRedisTemplate() {
return redisTemplate;
}
public RedisCacheManager getRedisCacheManager() {
return redisCacheManager;
}
@Bean
public KeyGenerator customKeyGenerator() {
return new KeyGenerator() {
@Override
public Object generate(Object target, Method method, Object... objects) {
StringBuilder sb = new StringBuilder();
sb.append(target.getClass().getName());
sb.append(method.getName());
for (Object obj : objects) {
sb.append(obj.toString());
}
return sb.toString();
}
};
}
}
該類繼承CachingConfigurerSupport,用於手動修改redis相關設定。這裡重寫customKeyGenerator方法,提供了key的預設生成方式(類名+方法名)。下面就是在我們的Service中使用快取,有兩種方式,第一種就是開發一個工具類xxxRedisUtils,將RedisTemplate類注入進該類,然後提供各種操作,如下類:
@Service
public class RedisCacheUtil<T>{
@Autowired @Qualifier("jedisTemplate")
public RedisTemplate redisTemplate;
/**
* 快取基本的物件,Integer、String、實體類等
* @param key 快取的鍵值
* @param value 快取的值
* @return 快取的物件
*/
public <T> ValueOperations<String,T> setCacheObject(String key,T value){
ValueOperations<String,T> operation = redisTemplate.opsForValue();
operation.set(key,value);
return operation;
}
//其它各種操作省略...
}
然後在Service中注入RedisCacheUtil類進行快取的操作即可:
@Autowired
private RedisCacheUtil<User> redisCache;
第二種就是在Service直接使用註解的方式來進行快取的操作,這種也是比較方便的方式:
有兩種常用註解,分別是@Cacheable和@CacheEvict,用於快取的設定和清理:
(1)@Cacheable("a")
該註解的意義就是把該方法的查詢結果放到redis中去,下一次再發起查詢就去redis中去取,存在redis中的資料的key就是a;
(2)@CacheEvict(value={"a","b"},allEntries=true)
該註解的意思就是執行該方法後要清除redis中key名稱為a,b的資料;使用樣例:
@Cacheable("getUserById")//標註該方法查詢的結果進入快取,再次訪問時直接讀取快取中的資料
@Override
public User getUserById(int userId) {
return this.iUserDao.selectByPrimaryKey(userId);
}
@CacheEvict(value= {"getAllUser","getUserById","findUsers"},allEntries=true)//清空快取,allEntries變量表示所有物件的快取都清除
@Override
public void insertUser(User user) {
this.iUserDao.insertUser(user);
}
以上就是使用傳統方式整合redis的操作方式。可以看出配置步驟還是比較繁瑣的。
二、使用Spring Boot整合Redis原理剖析
說白了,Spring Boot針對Redis的整合,有一部分依賴了Spring Boot的自動配置機制。
我們先來了解一下Spring Boot針對Spring Boot的自動化配置原理:
一般我們在使用Spring Boot的時候要編寫一個啟動類:
package cn.com.springboot;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
//Sprnig Boot專案的核心註解,主要目的是開啟自動配置
public class MainApplication {
//該main方法作為專案啟動的入口
public static void main(String[] args) {
SpringApplication.run(MainApplication.class, args);
}
}
因為Spring Boot可以開啟自動配置(@SpringBootApplication中的@EnableAutoConfiguration),SpringBootApplication物件例項化時會載入spring-boot的jar中的META-INF/spring.factories檔案,
在該檔案中設定了需要進行自動配置載入的實體類,其中就包含了redis的相關自動配置類:
org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration,\
org.springframework.boot.autoconfigure.data.redis.RedisRepositoriesAutoConfiguration,\
其中RedisAutoConfiguration類會讀取RedisProperties類中的引數作為配置項,而RedisProperties中的連線引數,是讀取使用者在properties中配置的,以“spring.redis”開頭的配置項,通過原始碼可以看到:
package org.springframework.boot.autoconfigure.data.redis;
import java.util.List;
import org.springframework.boot.context.properties.ConfigurationProperties;
@ConfigurationProperties(prefix = "spring.redis")
public class RedisProperties {
//內容原始碼省略...
}
RedisAutoConfiguration就是幫我們自動做了一些列的配置,我們在開發中只需要修改少量配置指向自己的redis服務地址即可。
那我們其實很清晰了,我們只需要在Spring Boot的properties檔案中,使用“spring.redis”字首進行redis連線資訊的配置,就可以使用redis了!是不是很方便!
下面就是Spring Boot連整合redis的方式。
三、使用Spring Boot整合Redis步驟
首先在POM檔案中引入redis的啟動依賴:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
然後在修改專案啟動類,增加註解@EnableCaching,開啟快取功能,如下:
package cn.com.springboot;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.scheduling.annotation.EnableScheduling;
@SpringBootApplication
//Sprnig Boot專案的核心註解,主要目的是開啟自動配置
@EnableScheduling
@EnableCaching
public class MainApplication {
//該main方法作為專案啟動的入口
public static void main(String[] args) {
SpringApplication.run(MainApplication.class, args);
}
}
然後在application.properties中配置Redis連線資訊,如下:
# Redis資料庫索引(預設為0)
spring.redis.database=0
# Redis伺服器地址
spring.redis.host=172.31.19.222
# Redis伺服器連線埠
spring.redis.port=6379
# Redis伺服器連線密碼(預設為空)
spring.redis.password=
# 連線池最大連線數(使用負值表示沒有限制)
spring.redis.pool.max-active=8
# 連線池最大阻塞等待時間(使用負值表示沒有限制)
spring.redis.pool.max-wait=-1
# 連線池中的最大空閒連線
spring.redis.pool.max-idle=8
# 連線池中的最小空閒連線
spring.redis.pool.min-idle=0
# 連線超時時間(毫秒)
spring.redis.timeout=0
然後編寫一個Redis快取配置類RedisConfig,用於定義快取key生成策略、快取管理器、RedisTemplate等。如下:
package springboot.config;
import org.springframework.beans.factory.annotation.Value;
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;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
/**
* Redis快取配置類
* @author szekinwin
*
*/
@Configuration
@EnableCaching
public class RedisConfig extends CachingConfigurerSupport{
@Value("${spring.redis.host}")
private String host;
@Value("${spring.redis.port}")
private int port;
@Value("${spring.redis.timeout}")
private int timeout;
//自定義快取key生成策略
@Bean
public KeyGenerator keyGenerator() {
return new KeyGenerator(){
@Override
public Object generate(Object target, java.lang.reflect.Method method, Object... params) {
StringBuffer sb = new StringBuffer();
sb.append(target.getClass().getName());
sb.append(method.getName());
for(Object obj:params){
sb.append(obj.toString());
}
return sb.toString();
}
};
}
//快取管理器
@Bean
public CacheManager cacheManager(@SuppressWarnings("rawtypes") RedisTemplate redisTemplate) {
RedisCacheManager cacheManager = new RedisCacheManager(redisTemplate);
//設定快取過期時間
cacheManager.setDefaultExpiration(10000);
return cacheManager;
}
@Bean
public RedisTemplate<String, String> redisTemplate(RedisConnectionFactory factory){
StringRedisTemplate template = new StringRedisTemplate(factory);
setSerializer(template);//設定序列化工具
template.afterPropertiesSet();
return template;
}
private void setSerializer(StringRedisTemplate template){
@SuppressWarnings({ "rawtypes", "unchecked" })
Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
ObjectMapper om = new ObjectMapper();
om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
jackson2JsonRedisSerializer.setObjectMapper(om);
template.setValueSerializer(jackson2JsonRedisSerializer);
}
}
然後在Service中使用redisTemplate或者直接使用@Cacheable和@CacheEvict來進行快取操作即可。
當然你也可以像第一小節講的那樣,使用傳統配置來進行redis的設定,不同的就是我們使用Java配置來代替XML配置,適合那些需要自己控制redis核心操作的專案。
使用Java方式配置,只需要新建一個類,然後使用@Configuration註解即可,然後使用配置的RedisTemplate類進行redis資料庫的操作。這裡不再贅述。
四、補充:redis叢集操作
上面講的都是針對redis單機版進行的操作,而目前我們的企業級專案都是搭建了redis叢集來進行redis管理的,這裡我們來補充一下傳統模式和Spring Boot模式對
redis叢集的操作。
(1)傳統方式操作redis叢集
修改redis.propertis,放置叢集配置:
redis.host1=192.168.1.235
redis.port1=7001
redis.host2=192.168.1.235
redis.port2=7002
redis.host3=192.168.1.235
redis.port3=7003
redis.host4=192.168.1.235
redis.port4=7004
redis.host5=192.168.1.235
redis.port5=7005
redis.host6=192.168.1.235
redis.port6=7006
redis.maxRedirects=3
redis.maxIdle=30
redis.maxTotal=100
redis.minIdle=5
redis.maxWaitMillis=30000
redis.testOnBorrow=true
redis.testOnReturn=true
redis.testWhileIdle=true
redis.timeout=3000
然後在spring配置檔案中,配置RedisClusterConfiguration類,將叢集資訊放置進去:
<bean id="redisClusterConfiguration" class="org.springframework.data.redis.connection.RedisClusterConfiguration">
<property name="maxRedirects" value="${redis.maxRedirects}"></property>
<property name="clusterNodes">
<set>
<bean class="org.springframework.data.redis.connection.RedisNode">
<constructor-arg name="host" value="${redis.host1}"></constructor-arg>
<constructor-arg name="port" value="${redis.port1}"></constructor-arg>
</bean>
<bean class="org.springframework.data.redis.connection.RedisNode">
<constructor-arg name="host" value="${redis.host2}"></constructor-arg>
<constructor-arg name="port" value="${redis.port2}"></constructor-arg>
</bean>
<bean class="org.springframework.data.redis.connection.RedisNode">
<constructor-arg name="host" value="${redis.host3}"></constructor-arg>
<constructor-arg name="port" value="${redis.port3}"></constructor-arg>
</bean>
<bean class="org.springframework.data.redis.connection.RedisNode">
<constructor-arg name="host" value="${redis.host4}"></constructor-arg>
<constructor-arg name="port" value="${redis.port4}"></constructor-arg>
</bean>
<bean class="org.springframework.data.redis.connection.RedisNode">
<constructor-arg name="host" value="${redis.host5}"></constructor-arg>
<constructor-arg name="port" value="${redis.port5}"></constructor-arg>
</bean>
<bean class="org.springframework.data.redis.connection.RedisNode">
<constructor-arg name="host" value="${redis.host6}"></constructor-arg>
<constructor-arg name="port" value="${redis.port6}"></constructor-arg>
</bean>
</set>
</property>
</bean>
然後將配置好的RedisClusterConfiguration作為引數,引入到之前配置好的jeidsConnectionFactory中即可:
<bean id="jeidsConnectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory" >
<property name="poolConfig" ref="jedisPoolConfig" />
<constructor-arg name="clusterConfig" ref="redisClusterConfiguration"/>
<constructor-arg name="poolConfig" ref="jedisPoolConfig"/>
</bean>
其它配置就無需修改(redisTemplate等配置),在後面使用redis的操作也類似之前。
如果redis配置了主從,操作如下:
配置檔案:
#sentinel1的IP和埠
sentinel1.host=192.168.1.233
sentinel1.port=26379
#sentinel2的IP和埠
sentinel2.host=192.168.1.233
sentinel2.port=26378
im.hs.server.redis.maxIdle=500
#最大連線數,超過此連線時操作redis會報錯
im.hs.server.redis.maxTotal=5000
im.hs.server.redis.maxWaitTime=1000
im.hs.server.redis.testOnBorrow=true
#最小閒置連線數,spring啟動的時候自動建立該數目的連線供應用程式使用,不夠的時候會申請。
im.hs.server.redis.minIdle=300
im.hs.server.redis.sentinel.masterName=mymaster
然後在XML配置檔案中配置redisSentinelConfiguration類,將redis主從資訊放入其中:
<bean id="redisSentinelConfiguration" class="org.springframework.data.redis.connection.RedisSentinelConfiguration">
<property name="master">
<bean class="org.springframework.data.redis.connection.RedisNode">
<property name="name" value="${im.hs.server.redis.sentinel.masterName}"/>
</bean>
</property>
<property name="sentinels">
<set>
<bean class="org.springframework.data.redis.connection.RedisNode">
<constructor-arg name="host" value="${sentinel1.host}"></constructor-arg>
<constructor-arg name="port" value="${sentinel1.port}"></constructor-arg>
</bean>
<bean class="org.springframework.data.redis.connection.RedisNode">
<constructor-arg name="host" value="${sentinel2.host}"></constructor-arg>
<constructor-arg name="port" value="${sentinel2.port}"></constructor-arg>
</bean>
</set>
</property>
</bean>
<bean id="jeidsConnectionFactory"
class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory">
<constructor-arg name="sentinelConfig" ref="redisSentinelConfiguration"></constructor-arg>
<constructor-arg name="poolConfig" ref="poolConfig"></constructor-arg>
</bean>
解釋:sentinel意思是哨兵,用於監視主從伺服器的執行狀況,如果主伺服器掛掉,會在從伺服器中選舉一個作為主伺服器。
其它配置就無需修改(redisTemplate等配置),在後面使用redis的操作也類似之前。
(2)Spring Boot操作redis叢集
Spring Boot的叢集配置就很簡單了,修改原來的配置如下:
spring.redis.cluster.nodes=127.0.0.1:26379,127.0.0.1:26479,127.0.0.1:26579
spring.redis.password=password
餘下的操作如之前。
主從配置:
# database name
spring.redis.database=0
# server host1 單機使用,對應伺服器ip
#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 哨兵監聽的Redis server的名稱
spring.redis.sentinel.master=mymaster
# comma-separated list of host:port pairs 哨兵的配置列表
spring.redis.sentinel.nodes=127.0.0.1:26379,127.0.0.1:26479,127.0.0.1:26579
以上就是Spring 以及Spring Boot針對redis的整合。
參考:
Spring整合redis:
https://www.cnblogs.com/hello-daocaoren/p/7891907.html
SpringBoot使用Redis快取:
https://www.cnblogs.com/gdpuzxs/p/7222309.html
spring整合redis(叢集、主從):
https://blog.csdn.net/sunqingzhong44/article/details/70976038?locationNum=6&fps=1
spring boot整合redis主從sentinel:
https://blog.csdn.net/liuchuanhong1/article/details/54601037
轉載請註明出處:https://blog.csdn.net/acmman/article/details/83035604