基于注解的方式整合Srpingmvc+Redis
项目中原本使用的是手动获取redis链接池的方式进行的与Spring的整合,现在需要修改为注解的形式。初次接触redis,做个记录。
1. 首先添加 jackson的jar包, 需要添加的 jar包共有三个,分别为:jackson-annoations-2.4.4.jar,jackson-core-2.4.4.jar,jackson-databind-2.4.4.jar,此项目中使用的是同一版本的jar。
2. 更新redis的配置文件,添加redis缓存管理器配置RedisCacheManager,添加redis缓存配置RedisCacheConfig,更新RedisTemplate,添加对key和value的序列化支持:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd "> <!-- 配置RedisTemplate --> <bean id="redisTemplate" class="org.springframework.data.redis.core.StringRedisTemplate"> <property name="connectionFactory" ref="jedisConnectionFactory" /> <br /> <!-- 设置key和value的序列化 --> <property name="keySerializer"> <bean class="org.springframework.data.redis.serializer.StringRedisSerializer" /> </property> <property name="valueSerializer"> <bean class="org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer" /> </property> </bean> <!-- 配置JedisConnectionFactory --> <bean id="jedisConnectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory" p:host-name="${redis.host}" p:port="${redis.port}" p:password="${redis.pass}" p:pool-config-ref="poolConfig" /> <!-- 配置JedisPoolConfig实例 --> <bean id="poolConfig" class="redis.clients.jedis.JedisPoolConfig"> <property name="maxIdle" value="${redis.maxIdle}" /> <property name="testOnBorrow" value="${redis.testOnBorrow}" /> </bean> <!-- 配置RedisCacheConfig --> <bean id="redisCacheConfig" class="com.fh.dao.redis.RedisCacheConfig"> <constructor-arg ref="jedisConnectionFactory" /> <constructor-arg ref="redisTemplate" /> <constructor-arg ref="redisCacheManager" /> </bean> <!-- 配置RedisCacheManager --> <bean id="redisCacheManager" class="org.springframework.data.redis.cache.RedisCacheManager"> <constructor-arg name="redisOperations" ref="redisTemplate" /> <property name="defaultExpiration" value="${redis.expiration}"/> <!-- 此处可以设置项目中用到的缓存名称,即@Cache* 标签中的value --> <constructor-arg name="cacheNames"> <set> <value>caiya_a</value> <value>caiya_test</value> <value>sampleCache1</value> <value>memoryCache</value> <value>scanCache</value> <value>padIndexCache</value> <value>sampleCache1</value> <value>sampleCache1</value> </set> </constructor-arg> <!--默认缓存名字--> <property name="defaultCacheName" value="caiya_a"/> <!--是否在容器启动时初始化--> <property name="loadRemoteCachesOnStartup" value="true"/> <!--是否使用前缀--> <property name="usePrefix" value="true"/> <!--前缀命名,仅当usePrefix为true时才生效--> <property name="cachePrefix"> <bean class="org.springframework.data.redis.cache.DefaultRedisCachePrefix"> <constructor-arg name="delimiter" value=":"/> </bean> </property> <!--缓存名字和有效期的分隔符--> <property name="separator" value="#"/> <!--默认有效期1h--> <!-- 多个缓存有效期,一般的单个工程可以省略此项 --> <!-- <property name="expires"> <map> <entry key="caiya_a" value="1800"/> </map> </property> --> </bean> </beans>
3.创建RedisCacheConfig缓存配置类:
package com.at.dao.redis; import java.lang.reflect.Method; 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.RedisCacheManager; import org.springframework.data.redis.connection.RedisConnectionFactory; import org.springframework.data.redis.connection.jedis.JedisConnectionFactory; import org.springframework.data.redis.core.RedisTemplate; /** * 以Spring与配置文件来管理的redis缓存配置类 * * 必须添加EnableCaching注解,才能正常启用缓存功能 * * @author at * 2018-3-15 */ @Configuration @EnableCaching public class RedisCacheConfig extends CachingConfigurerSupport { private volatile JedisConnectionFactory mJedisConnectionFactory; private volatile RedisTemplate<String, String> mRedisTemplate; private volatile RedisCacheManager mRedisCacheManager; public RedisCacheConfig() { super(); } public RedisCacheConfig(JedisConnectionFactory mJedisConnectionFactory, RedisTemplate<String, String> mRedisTemplate, RedisCacheManager mRedisCacheManager) { super(); this.mJedisConnectionFactory = mJedisConnectionFactory; this.mRedisTemplate = mRedisTemplate; this.mRedisCacheManager = mRedisCacheManager; } public JedisConnectionFactory redisConnectionFactory() { return mJedisConnectionFactory; } public RedisTemplate<String, String> redisTemplate(RedisConnectionFactory cf) { return mRedisTemplate; } public CacheManager cacheManager(RedisTemplate<?, ?> redisTemplate) { return mRedisCacheManager; } @Bean public KeyGenerator customKeyGenerator() { return new KeyGenerator() { @Override public Object generate(Object o, Method method, Object... objects) { StringBuilder sb = new StringBuilder(); sb.append(o.getClass().getName()); sb.append(method.getName()); for (Object obj : objects) { sb.append(obj.toString()); } return sb.toString(); } }; } }
4. 更新实体类使其实现序列化,其中:@JsonNaming是jackson 2.1+版本的注解,作用于类或方法,注意这个注解是在jackson-databind包中而不是在jackson-annotations包里,它可以让你定制属性命名策略。@JsonSerialize 用来实现实体类的序列化。
5. 添加对应的dao接口,因此项目使用的是SqlSessionTemplate操作的dao层,此处不再展示代码。
6. 添加 service和serviceimpl。在接口方法的实现上和dao层都可以添加@Cache*注解,此项目中主要添加在service的方法实现上。
// 此注解是将该方法的返回值放入value的缓存下的key的值中,首次请求该方法时会处理缓存。再次请求该方法时,将先查找缓存中是否有对应的key,如果有则跳过方法执行。 @Cacheable(value="value",key="'key'") public List<PageData> getModel(PageData pd) throws Exception { System.out.println("调用了方法"); return (List<PageData>) dao.getModel(pd); } // 此注解跟上面的注解功能相同,但不同的是,该注解将不会使方法跳过执行,而是每次执行后都将新的返回结果更新到value下的key中 @CachePut(value="value", key="'key'") public String updateEndTime(String arg1) { return arg1; } // 此注解将会使缓存中的key清除. @CacheEvict(value="figure", key="'figureList'",beforeInvocation=true) public int updateFigure(PageData pd) throws Exception{ System.out.println("调用了方法"); return (int) dao.update("CarouseFigureMapper.updateFigure", pd); }
注意:这些注解中都有的相同的参数为:value,key, condition。value表示使用哪个缓存,是必须指定的参数。key属性是用来指定Spring缓存方法的返回结果时对应的key的。该属性支持SpringEL表达式。当我们没有指定该属性时,Spring将使用默认策略生成key。condition属性可以设置是否使用缓存:condition属性默认为空,表示将缓存所有的调用情形。其值是通过SpringEL表达式来指定的,当为true时表示进行缓存处理;当为false时表示不进行缓存处理,即每次调用该方法时该方法都会执行一次。在@CacheEvict注解中,有两个新的参数,allEntries和beforeInvocation。其中allEntries是boolean类型,表示是否需要清除缓存中的所有元素。默认为false,表示不需要。当指定了allEntries为true时,Spring Cache将忽略指定的key。beforeInvocation可以设置缓存清除的触发时机,清除操作默认是在对应方法成功执行之后触发的,即方法如果因为抛出异常而未能成功返回时也不会触发清除操作。当我们指定该属性值为true时,Spring会在调用该方法之前清除缓存中的指定元素。
7. 注意事项:注解需要使用在public方法上。带有@Cache* 注解的方法不能被定义在调用该方法的类里,例如controller调用方法A,方法A使用注解,则A不能定义在该controller中。
8. 此处不再记录详细的接口实现等。关于redis更多的学习及使用方法,将在以后持续记录。