redisCacheManager(redis緩存管理器使用):配置+註解java
@Cacheable、@CachePut、@CacheEvict 註解介紹:redis
(1)@Cacheablespring
做用:主要針對方法配置,可以根據方法的請求參數對其結果進行緩存數據庫
@Cacheable 主要的參數:緩存
1)value:緩存的名稱,在 spring 配置文件中定義,必須指定至少一個mvc
例如:@Cacheable(value="mycache") 或者 @Cacheable(value={"cache1","cache2"})ui
2)key:緩存的 key,能夠爲空,若是指定要按照 SpEL 表達式編寫,若是不指定,則缺省按照方法的全部參數進行組合spa
例如:@Cacheable(value="testcache",key="#userName")code
3)condition:緩存的條件,能夠爲空,使用 SpEL 編寫,返回 true 或者 false,只有爲 true 才進行緩存component
例如:@Cacheable(value="testcache",condition="#userName.length()>2")
(2)@CachePut
做用:主要針對方法配置,可以根據方法的請求參數對其結果進行緩存,
和@Cacheable不一樣的是,它每次都會觸發真實方法的調用
@CachePut 主要的參數:同@Cacheable
(3)@CacheEvict
做用:主要針對方法配置,可以根據必定的條件對緩存進行清空
@CacheEvict 主要的參數:
1)value:緩存的名稱,在 spring 配置文件中定義,必須指定至少一個
例如:@CachEvict(value="mycache") 或者 @CachEvict(value={"cache1","cache2"})
2)key:緩存的 key,能夠爲空,若是指定要按照 SpEL 表達式編寫,若是不指定,則缺省按照方法的全部參數進行組合
例如:@CachEvict(value="testcache",key="#userName")
3)condition:緩存的條件,能夠爲空,使用 SpEL 編寫,返回 true 或者 false,只有爲 true 才清空緩存
例如:@CachEvict(value="testcache",condition="#userName.length()>2")
4)allEntries:是否清空全部緩存內容,缺省爲 false,若是指定爲 true,則方法調用後將當即清空全部緩存
例如:@CachEvict(value="testcache",allEntries=true)
5)beforeInvocation:是否在方法執行前就清空,缺省爲 false,
若是指定爲 true,則在方法尚未執行的時候就清空緩存,
缺省狀況下,若是方法執行拋出異常,則不會清空緩存
例如:@CachEvict(value="testcache」,beforeInvocation=true)
配置+註解的具體使用:
一、pom.xml依賴注入:
<dependency> <groupId>org.springframework.data</groupId> <artifactId>spring-data-redis</artifactId> <version>1.7.6.RELEASE</version> </dependency> <dependency> <groupId>redis.clients</groupId> <artifactId>jedis</artifactId> <version>2.9.0</version> </dependency>
二、redis.properties(redis緩存配置文件)
master.name=mymaster master.password=123456 sentinel.host=127.0.0.1 sentinel1.port=26379 sentinel2.port=26380 #緩存數據庫選擇 redis.default.db=3 pool.timeout=100000 pool.maxTotal=100 pool.maxActive=100 pool.maxIdle=10 pool.maxWaitMillis=1000 #是否在borrow一個jedis以前就validate pool.testOnBorrow=true #緩存數據的最大生命週期,單位:s,-1永久 redis.expiration=-1 #是否禁用緩存,true禁用 cacheManagers.fallbackToNoOpCache=false
三、在spring.xml(servlet-context.xml)中配置jedis以及cacheManager
<!-- 掃描package方便註解依賴注入--> <context:component-scan base-package="com.shop" /> <!--載入 redis 配置文件--> <context:property-placeholder location="classpath:redis.properties" ignore-unresolvable="true"/> <mvc:annotation-driven/> <!-- 開啓緩存註解驅動 --> <cache:annotation-driven/><!--缺省了cache-manager="cacheManager"--> <!--哨兵配置--> <bean id="redisSentinelConfiguration" class="org.springframework.data.redis.connection.RedisSentinelConfiguration"> <property name="master"> <bean class="org.springframework.data.redis.connection.RedisNode" p:name="${master.name}"/><!--要跟哨兵配置文件監控主機名稱一致--> </property> <property name="sentinels"> <set> <bean class="org.springframework.data.redis.connection.RedisNode" c:host="${sentinel.host}" c:port="${sentinel1.port}"/> <bean class="org.springframework.data.redis.connection.RedisNode" c:host="${sentinel.host}" c:port="${sentinel2.port}"/> </set> </property> </bean> <!-- jedis pool配置 --> <bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig" p:maxTotal="${pool.maxTotal}" p:maxIdle="${pool.maxIdle}" p:maxWaitMillis="${pool.maxWaitMillis}" p:testOnBorrow="${pool.testOnBorrow}"/> <!-- spring data redis --> <bean id="jedisConnectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory" p:pool-config-ref="jedisPoolConfig" c:sentinelConfig-ref="redisSentinelConfiguration" p:password="${master.password}" p:database="${redis.default.db}"/> <bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate" p:connectionFactory-ref="jedisConnectionFactory"> <!--序列化配置--> <property name="keySerializer"> <bean class="org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer"/> </property> <property name="valueSerializer"> <bean class="org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer"/> </property> <property name="hashKeySerializer"> <bean class="org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer"/> </property> <property name="hashValueSerializer"> <bean class="org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer"/> </property> </bean> <!-- 配置cacheManager --> <!--使用spring cache--> <!-- simple cache manager --> <!--<bean id="cacheManager" class="org.springframework.cache.support.SimpleCacheManager"> <property name="caches"> <set> <bean class="org.springframework.cache.concurrent.ConcurrentMapCacheFactoryBean" p:name="default" /> <bean class="org.springframework.cache.concurrent.ConcurrentMapCacheFactoryBean" p:name="userCache" /> </set> </property> </bean>--> <!--redisCacheManager--> <bean id="redisCacheManager" class="org.springframework.data.redis.cache.RedisCacheManager" c:redisOperations-ref="redisTemplate" p:usePrefix="true" p:transactionAware="true" p:defaultExpiration="${redis.expiration}"> <!--啓用前綴和事務支持、失效時間--> </bean> <!-- dummy cacheManager --> <!--在沒有cache容器的狀況下使用緩存機制,系統會拋出異常, 因此在不想使用緩存機制時,能夠設置fallbackToNoOpCache爲true來禁用緩存--> <bean id="cacheManager" class="org.springframework.cache.support.CompositeCacheManager" p:cacheManagers-ref="redisCacheManager" p:fallbackToNoOpCache="${cacheManagers.fallbackToNoOpCache}"/> <!--<property name="cacheManagers"> <list> <ref bean="redisCacheManager" /> </list> </property>-->
四、使用註解(建議在Service層使用)
public class UserService { /** * @Cacheable:主要針對方法配置,可以根據方法的請求參數對其結果進行緩存 * #:SpEL表達式 * 至少指定一個緩存的名稱(value),多個:(value={"cache1","cache2"}) * 若緩存的key爲空則缺省按照方法的全部參數進行組合,多個key組合:key="#userName.concat(#password)" * condition:緩存條件,可爲空 condition="#userName.length()>4" */ @Cacheable(value = "user",key = "#id") public User findUserById(Integer id) { log.info("findUserFromDB================================================================"); return userDao.findUserById(id); } //@CachePut:每次都執行方法體並對返回結果進行緩存操做 @CachePut(value = "userLoginIdentity",key = "#user.getId()",condition="#user.getUserName().length()>4") public UserLoginIdentity buildUserLoginIdentity(User user){ UserLoginIdentity userLoginIdentity = new UserLoginIdentity(); userLoginIdentity.setUserIdString(UserIDBase64.encoderUserID(user.getId())); userLoginIdentity.setUserName(user.getUserName()); userLoginIdentity.setRealName(user.getTrueName()); return userLoginIdentity; } /** * @CacheEvict:清除緩存 * allEntries:是否清空全部緩存內容,缺省爲 false,若是指定爲 true,則方法調用後將當即清空全部緩存 * beforeInvocation:是否在方法執行前就清空,缺省爲 false,若是指定爲 true,則在方法尚未執行的時候就清空緩存, * 缺省狀況下,若是方法執行拋出異常,則不會清空緩存 */ @CacheEvict(value = {"user","userLoginIdentity"},allEntries = true,beforeInvocation = true) public UserLoginIdentity login(String userName, String password) { //非空驗證 AssertUtil.isNotEmpty(userName, "用戶名不能爲空!"); AssertUtil.isNotEmpty(password, "密碼不能爲空!"); User user=userDao.findUserByUserName(userName.trim()); AssertUtil.notNull(user); if (!MD5Util.md5Method(password).equals(user.getPassword())) { throw new ParamException(103,"用戶密碼錯誤!請從新輸入!"); } return buildUserLoginIdentity(user); } }
關於序列化:keySerializer:這個是對key的默認序列化器。
默認值是StringSerializer。
valueSerializer:這個是對value的默認序列化器,
默認值是取自DefaultSerializer的JdkSerializationRedisSerializer。
hashKeySerializer:對hash結構數據的hashkey序列化器,
默認值是取自DefaultSerializer的JdkSerializationRedisSerializer。
hashValueSerializer:對hash結構數據的hashvalue序列化器,
默認值是取自DefaultSerializer的JdkSerializationRedisSerializer。
從執行時間上來看,JdkSerializationRedisSerializer是最高效的(畢竟是JDK原生的),可是序列化的結果字符串是最長的。
JSON因爲其數據格式的緊湊性,序列化的長度是最小的,時間比前者要多一些。
而OxmSerialiabler在時間上看是最長的(當時和使用具體的Marshaller有關)。
因此我的的選擇是傾向使用JacksonJsonRedisSerializer做爲POJO的序列器。