目标:
1、SpringBoot配置類
2、SpringBoot整合redis及其注解式開發
SpringBoot配置類
注解标簽
@Configuration
@Configuration底層是含有@Component ,是以@Configuration 具有和 @Component 的作用。
@Configuration可了解為用spring的時候xml裡面的<beans>标簽。
注:
1) 配置類必須以類的形式提供(不能是工廠方法傳回的執行個體),允許通過生成子類在運作時增強(cglib 動态代理)。
2) 配置類不能是 final 類(沒法動态代理)。
3) 配置注解通常為了通過 @Bean 注解生成 Spring 容器管理的類。
4) 配置類必須是非本地的(即不能在方法中聲明,不能是 private)。
5) 任何嵌套配置類都必須聲明為static。
6) @Bean方法不能建立進一步的配置類(也就是傳回的bean如果帶有@Configuration,也不會被特殊處理,隻會作為普通的 bean)。
@EnableCaching
1) @EnableCaching注解是spring framework中的注解驅動的緩存管理功能。自spring版本3.1起加入了該注解。
2) 如果你使用了這個注解,那麼你就不需要在XML檔案中配置cache manager了。
3) 當你在配置類(@Configuration)上使用@EnableCaching注解時,會觸發一個post processor,這會掃描每一個spring bean,檢視是否已經存在注解對應的緩存。如果找到了,就會自動建立一個代理攔截方法調用,使用緩存的bean執行處理。
@Bean
@Bean可了解為用spring的時候xml裡面的<bean>标簽。
注:
1) @Bean注解在傳回執行個體的方法上,如果未通過@Bean指定bean的名稱,則預設與标注的方法名相同;
2) @Bean注解預設作用域為單例singleton作用域,可通過@Scope(“prototype”)設定為原型作用域;
3) 既然@Bean的作用是注冊bean對象,那麼完全可以使用@Component、@Controller、@Service、@Repository等注解注冊bean(在需要注冊的類上加注解),當然需要配置@ComponentScan注解進行自動掃描。
導入redis的依賴
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
</dependency>
配置application.yml
spring:
redis:
database: 0
host: 192.168.231.128
port: 6379
password: 123456
jedis:
pool:
max-active: 100
max-idle: 3
max-wait: -1
min-idle: 0
timeout: 1000
建立RedisConfig
RedisConfig類用于Redis資料緩存。
//繼承CachingConfigurerSupport,為了自定義生成KEY的政策。可以不繼承。
package com.cgl.springboot02.config;
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
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.RedisCacheConfiguration;
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 org.springframework.data.redis.serializer.StringRedisSerializer;
import java.lang.reflect.Method;
import java.time.Duration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
/**
* redis配置類
**/
@Configuration
@EnableCaching//開啟注解式緩存
//繼承CachingConfigurerSupport,為了自定義生成KEY的政策。可以不繼承。
public class RedisConfig extends CachingConfigurerSupport {
/**
* 生成key的政策 根據類名+方法名+所有參數的值生成唯一的一個key
*
* @return
*/
@Bean
@Override
public KeyGenerator keyGenerator() {
return new KeyGenerator() {
@Override
public Object generate(Object target, Method method, Object... params) {
StringBuilder sb = new StringBuilder();
sb.append(target.getClass().getName());
sb.append(method.getName());
for (Object obj : params) {
sb.append(obj.toString());
}
return sb.toString();
}
};
}
/**
* 管理緩存
*
* @param redisConnectionFactory
* @return
*/
@Bean
public CacheManager cacheManager(RedisConnectionFactory redisConnectionFactory) {
//通過Spring提供的RedisCacheConfiguration類,構造一個自己的redis配置類,從該配置類中可以設定一些初始化的緩存命名空間
// 及對應的預設過期時間等屬性,再利用RedisCacheManager中的builder.build()的方式生成cacheManager:
RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig(); // 生成一個預設配置,通過config對象即可對緩存進行自定義配置
config = config.entryTtl(Duration.ofMinutes(1)) // 設定緩存的預設過期時間,也是使用Duration設定
.disableCachingNullValues(); // 不緩存空值
// 設定一個初始化的緩存空間set集合
Set<String> cacheNames = new HashSet<>();
cacheNames.add("my-redis-cache1");
cacheNames.add("my-redis-cache2");
// 對每個緩存空間應用不同的配置
Map<String, RedisCacheConfiguration> configMap = new HashMap<>();
configMap.put("my-redis-cache1", config);
configMap.put("my-redis-cache2", config.entryTtl(Duration.ofSeconds(120)));
RedisCacheManager cacheManager = RedisCacheManager.builder(redisConnectionFactory) // 使用自定義的緩存配置初始化一個cacheManager
.initialCacheNames(cacheNames) // 注意這兩句的調用順序,一定要先調用該方法設定初始化的緩存名,再初始化相關的配置
.withInitialCacheConfigurations(configMap)
.build();
return cacheManager;
}
@Bean
public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory connectionFactory) {
RedisTemplate<Object, Object> template = new RedisTemplate<>();
template.setConnectionFactory(connectionFactory);
//使用Jackson2JsonRedisSerializer來序列化和反序列化redis的value值(預設使用JDK的序列化方式)
Jackson2JsonRedisSerializer serializer = new Jackson2JsonRedisSerializer(Object.class);
ObjectMapper mapper = new ObjectMapper();
mapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
mapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
serializer.setObjectMapper(mapper);
template.setValueSerializer(serializer);
//使用StringRedisSerializer來序列化和反序列化redis的key值
template.setKeySerializer(new StringRedisSerializer());
template.afterPropertiesSet();
return template;
}
@Bean
public StringRedisTemplate stringRedisTemplate(RedisConnectionFactory factory) {
StringRedisTemplate stringRedisTemplate = new StringRedisTemplate();
stringRedisTemplate.setConnectionFactory(factory);
return stringRedisTemplate;
}
}
詳細針對下面這段代碼進行講解

在整合ehcache的時候,會有一個配置檔案spring-ehcache.xml如下
<!-- 使用ehcache緩存 -->
<bean id="cacheManagerFactory" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean">
<property name="configLocation" value="classpath:ehcache.xml"/>
<property name="shared" value="true"></property>
</bean>
<!-- 預設是cacheManager -->
<bean id="cacheManager" class="org.springframework.cache.ehcache.EhCacheCacheManager">
<property name="cacheManager" ref="cacheManagerFactory"/>
</bean>
ehcache.xml
<!--defaultCache:預設的管理政策-->
<!--eternal:設定緩存的elements是否永遠不過期。如果為true,則緩存的資料始終有效,如果為false那麼還要根據timeToIdleSeconds,timeToLiveSeconds判斷-->
<!--maxElementsInMemory:在記憶體中緩存的element的最大數目-->
<!--overflowToDisk:如果記憶體中資料超過記憶體限制,是否要緩存到磁盤上-->
<!--diskPersistent:是否在磁盤上持久化。指重新開機jvm後,資料是否有效。預設為false-->
<!--timeToIdleSeconds:對象空閑時間(機關:秒),指對象在多長時間沒有被通路就會失效。隻對eternal為false的有效。預設值0,表示一直可以通路-->
<!--timeToLiveSeconds:對象存活時間(機關:秒),指對象從建立到失效所需要的時間。隻對eternal為false的有效。預設值0,表示一直可以通路-->
<!--memoryStoreEvictionPolicy:緩存的3 種清空政策-->
<!--FIFO:first in first out (先進先出)-->
<!--LFU:Less Frequently Used (最少使用).意思是一直以來最少被使用的。緩存的元素有一個hit 屬性,hit 值最小的将會被清出緩存-->
<!--LRU:Least Recently Used(最近最少使用). (ehcache 預設值).緩存的元素有一個時間戳,當緩存容量滿了,而又需要騰出地方來緩存新的元素的時候,那麼現有緩存元素中時間戳離目前時間最遠的元素将被清出緩存-->
<defaultCache eternal="false" maxElementsInMemory="1000" overflowToDisk="false" diskPersistent="false"
timeToIdleSeconds="0" timeToLiveSeconds="600" memoryStoreEvictionPolicy="LRU"/>
是以截圖中代碼的意思是:從RedisCacheConfiguration擷取一個預設的緩存政策,針對這一政策做對應的調整,生成一個全新的政策。然後,初始化兩個緩存槽,賦予名字my-redis-cache1和my-redis-cache2,,賦予再基于之前的緩存政策,初始化兩個緩存政策,存儲與configMap,然後政策與緩存槽對應上,生成緩存管理器交個spring進行管理,替代掉SSM時代的配置檔案。
ssm架構中如果整合redis,那麼會有個spring-redis.xml配置檔案,裡面的配置内容如下
<!-- 1. 引入properties配置檔案 -->
<!--<context:property-placeholder location="classpath:redis.properties" />-->
<!-- 2. redis連接配接池配置-->
<bean id="poolConfig" class="redis.clients.jedis.JedisPoolConfig">
<!--最大空閑數-->
<property name="maxIdle" value="${redis.maxIdle}"/>
<!--連接配接池的最大資料庫連接配接數 -->
<property name="maxTotal" value="${redis.maxTotal}"/>
<!--最大建立連接配接等待時間-->
<property name="maxWaitMillis" value="${redis.maxWaitMillis}"/>
<!--逐出連接配接的最小空閑時間 預設1800000毫秒(30分鐘)-->
<property name="minEvictableIdleTimeMillis" value="${redis.minEvictableIdleTimeMillis}"/>
<!--每次逐出檢查時 逐出的最大數目 如果為負數就是 : 1/abs(n), 預設3-->
<property name="numTestsPerEvictionRun" value="${redis.numTestsPerEvictionRun}"/>
<!--逐出掃描的時間間隔(毫秒) 如果為負數,則不運作逐出線程, 預設-1-->
<property name="timeBetweenEvictionRunsMillis" value="${redis.timeBetweenEvictionRunsMillis}"/>
<!--是否在從池中取出連接配接前進行檢驗,如果檢驗失敗,則從池中去除連接配接并嘗試取出另一個-->
<property name="testOnBorrow" value="${redis.testOnBorrow}"/>
<!--在空閑時檢查有效性, 預設false -->
<property name="testWhileIdle" value="${redis.testWhileIdle}"/>
</bean>
<!-- 3. redis連接配接工廠 -->
<bean id="connectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory"
destroy-method="destroy">
<property name="poolConfig" ref="poolConfig"/>
<!--IP位址 -->
<property name="hostName" value="${redis.hostName}"/>
<!--端口号 -->
<property name="port" value="${redis.port}"/>
<!--如果Redis設定有密碼 -->
<property name="password" value="${redis.password}"/>
<!--用戶端逾時時間機關是毫秒 -->
<property name="timeout" value="${redis.timeout}"/>
</bean>
<!-- 4. redis操作模闆,使用該對象可以操作redis -->
<bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate">
<property name="connectionFactory" ref="connectionFactory"/>
<!--如果不配置Serializer,那麼存儲的時候預設使用String,如果用User類型存儲,那麼會提示錯誤User can't cast to String!! -->
<property name="keySerializer">
<bean class="org.springframework.data.redis.serializer.StringRedisSerializer"/>
</property>
<property name="valueSerializer">
<bean class="org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer"/>
</property>
<property name="hashKeySerializer">
<bean class="org.springframework.data.redis.serializer.StringRedisSerializer"/>
</property>
<property name="hashValueSerializer">
<bean class="org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer"/>
</property>
<!--開啟事務 -->
<property name="enableTransactionSupport" value="true"/>
</bean>
<!-- 5.使用中間類解決RedisCache.RedisTemplate的靜态注入,進而使MyBatis實作第三方緩存 -->
<bean id="redisCacheTransfer" class="com.cgl.ssm2.util.RedisCacheTransfer">
<property name="redisTemplate" ref="redisTemplate"/>
</bean>
其中前面redis連結工廠的建立,已經交于springboot中的application.yml檔案來完成。是以,springboot整合redis我們隻需要關注下面這部配置設定置。
SpringBoot整合
常用緩存注解
@Cacheable:作用是主要針對方法配置,能夠根據方法的請求參數對其結果進行緩存
主要參數說明:
1) value :
緩存的名稱,在 spring 配置檔案中定義,必須指定至少一個,
例如:@Cacheable(value=”mycache”) 或者 @Cacheable(value={”cache1”,”cache2”}。
2) key :緩存的 key,可以為空,
如果指定要按照 SpEL 表達式編寫,如果不指定,則預設按照方法的所有參數進行組合,
例如:@Cacheable(value=”testcache”,key=”#userName”)。
3) condition :緩存的條件,可以為空,
案例如下:
service層
//表示使用my-redis-cache1緩存空間,key的生成政策為book+bid,當bid>10的時候才會使用緩存
@Cacheable(value = "my-redis-cache1",key = "'book'+#bid",condition = "#bid>10")
public Book selectByPrimaryKey(Integer bid) {
return bookMapper.selectByPrimaryKey(bid);
}
測試代碼
@Test
public void selectByPrimaryKey() {
Book book = bookService.selectByPrimaryKey(18);
System.out.println(book);
System.out.println("---------------------------------------------");
Book book2 = bookService.selectByPrimaryKey(18);
System.out.println(book2);
}
@CachePut:作用是主要針對方法配置,能夠根據方法的請求參數對其結果進行緩存,和 @Cacheable 不同的是,它每次都會觸發真實查詢
方法的調用
主要參數說明:
參數配置和@Cacheable一樣。
@CacheEvict:作用是主要針對方法配置,能夠根據一定的條件對緩存進行清空
主要參數說明:
1)value , key 和 condition 參數配置和@Cacheable一樣。
2) allEntries :
是否清空所有緩存内容,預設為 false,
如果指定為 true,則方法調用後将立即清空所有緩存,
例如:@CachEvict(value=”testcache”,allEntries=true)。
service層代碼
@CacheEvict(value = "my-redis-cache2",allEntries = true)
public void clear() {
System.out.println("清空my-redis-cache2緩存槽中的所有對象....");
}
測試代碼如下
public void clear() {
bookService.clear();
}
需要測試的話,先往緩存中緩存2個對象。
3) beforeInvocation :
是否在方法執行前就清空,預設為 false,
如果指定為 true,則在方法還沒有執行的時候就清空緩存,
預設情況下,如果方法執行抛出異常,則不會清空緩存,
例如@CachEvict(value=”testcache”,beforeInvocation=true)。