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
@EnableCaching注解是spring framework中的注解驅動的緩存管理功能。自spring版本3.1起加入了該注解。
如果你使用了這個注解,那么你就不需要在XML文件中配置cache manager了。
當你在配置類(@Configuration)上使用@EnableCaching注解時,會觸發一個post processor,這會掃描每一個spring bean,
查看是否已經存在注解對應的緩存。如果找到了,就會自動創建一個代理攔截方法調用,使用緩存的bean執行處理。
@Bean
1、@Bean可理解為用spring的時候xml里面的<bean>標簽。
2、 @Bean注解在返回實例的方法上,如果未通過@Bean指定bean的名稱,則默認與標注的方法名相同;
3、@Bean注解默認作用域為單例singleton作用域,可通過@Scope(“prototype”)設置為原型作用域;
redis相關pom依賴:
<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.43.232 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.lingerqi.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; /** * @author xyls * @blog name & blog address 027@0030 * @create 2019-11-28 22:38 */ /** * 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"/>
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.javaxl.ssm2.util.RedisCacheTransfer"> <property name="redisTemplate" ref="redisTemplate"/> </bean>
前面redis鏈接工廠的創建,已經交於springboot中的application.yml文件來完成。所以,springboot整合redis我們只需要關注下面這部分配置。
@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; } }
SpringBoot整合redis及其注解式開發
@Cacheable:作用是主要針對方法配置,能夠根據方法的請求參數對其結果進行緩存 主要參數說明: 1) value : 緩存的名稱,在 spring 配置文件中定義,必須指定至少一個, 例如:@Cacheable(value=”mycache”) 或者 @Cacheable(value={”cache1”,”cache2”}。 2) key :緩存的 key,可以為空, 如果指定要按照 SpEL 表達式編寫,如果不指定,則缺省按照方法的所有參數進行組合, 例如:@Cacheable(value=”testcache”,key=”#userName”)。 3) condition :緩存的條件,可以為空,
@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(11); System.out.println(book); System.out.println("---------------------------------------------"); Book book2 = bookService.selectByPrimaryKey(11); System.out.println(book2); }
當bid分別為8和11的時候,bid=8是不觸發緩存的,bid=18的時候才會緩存查詢結果
@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緩存槽中的所有對象...."); }
注:需要測試的話,先往緩存中緩存2個對象。
beforeInvocation :
是否在方法執行前就清空,缺省為 false,
如果指定為 true,則在方法還沒有執行的時候就清空緩存,
缺省情況下,如果方法執行拋出異常,則不會清空緩存,
例如@CachEvict(value=”testcache”,beforeInvocation=true)。