基于注解的方式整合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更多的学习及使用方法,将在以后持续记录。

相关推荐