spring整合redis

在SSH项目中整合redis

利用spring中的AOP 对redis进行统一的管理

1. 相关Jar文件

下载并导入以下3个Jar文件:

commons-pool2-2.4.2.jar、jedis-2.3.1.jar、spring-data-redis-1.3.4.RELEASE.jar。

三个文件分别对应的下载地址:http://www.java2s.com/Code/JarDownload/spring-data/ ,repo1.maven.org/maven2/redis/clients/jedis/,http://commons.apache.org/proper/commons-pool/download_pool.cgi 

2. Redis配置文件

在src文件夹下面新建一个redis.properties文件,设置连接Redis的一些属性。

<?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:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
>

<!-- 2.配置通知对象 -->
<bean name="redisAdvice" class="com.samton.common.redis.RedisAdvice" ></bean>
<!-- 3.开启使用注解完成织入 -->
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>

<bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig">
<property name="maxTotal" value="50" />
<property name="maxIdle" value="10" />
<property name="maxWaitMillis" value="1000" />
<property name="testOnBorrow" value="true" />
</bean>

<bean id="jedisPool" class="redis.clients.jedis.JedisPool">
<constructor-arg index="0" ref="jedisPoolConfig" />
<constructor-arg index="1" value="127.0.0.1" type="java.lang.String"/>
<constructor-arg index="2" value="6379" type="int" />
</bean>
</beans>

 

记住一定要在 spring创建jedisPool的时候,指定参数类型。否则会报错 jedis:Cannot open Redis connection due invalid URI

3. 自定义注解

在src文件夹下面新建一个注解文件;文件内容如下

@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface InterfaceCacheableDao {
    String key();
    String fieldKey();
    int expireTime() default 3600;
}

4. 建立AOP通知类

在src文件夹下面新建一个通知类,用于解析注解统一管理redis;

//通知类
@Aspect
public class RedisAdvice {
    /**
     * 获取注入对象
     */
    private RedisUtil redisUtil;
    
    public RedisRedisUtil  getRedisUtil () {
        return redisUtil;
    }
    
    public void setRedisUtil (RedisUtil redisUtil) {
        this.redisUtil= redisUtil;
    }

    @SuppressWarnings("unchecked")
    @Around("@annotation(com.samton.common.redis.dao.InterfaceCacheableDao)")
    public Object around(ProceedingJoinPoint pjp) throws Throwable {
        Object result =null;
        InterfaceCacheableDao cacheable=null;
        //获取注解上的完整方法
        Method proxyMethod = ((MethodSignature)pjp.getSignature()).getMethod();
        Method soruceMethod = pjp.getTarget().getClass().getMethod(proxyMethod.getName(), proxyMethod.getParameterTypes());
    
        cacheable=soruceMethod.getAnnotation(com.samton.common.redis.dao.InterfaceCacheableDao.class);
        
        if( null == cacheable ){
            cacheable = pjp.getTarget().getClass().getAnnotation(com.samton.common.redis.dao.InterfaceCacheableDao.class);
        }
        //解析注解
        String fieldKey =parseKey(cacheable.fieldKey(),soruceMethod,pjp.getArgs());
        
        //获取方法的返回类型,让缓存可以返回正确的类型
        Class returnType=((MethodSignature)pjp.getSignature()).getReturnType();
        
        //使用redis 的hash进行存取,易于管理
        result= redisUtil.hget(cacheable.key(), fieldKey,returnType);
        
        if( null == result ){
            try {
                result=pjp.proceed();
                Assert.notNull(fieldKey);
                redisUtil.hset(cacheable.key(),fieldKey, result,cacheable.expireTime());
            } catch (Throwable e) {
                e.printStackTrace();
            }
        }
        
        return result;
    }
    
    
     /**
     *    获取缓存的key 
     *    key 定义在注解上,支持SPEL表达式
     * @param pjp
     * @return
     */
    private String parseKey(String key,Method method,Object [] args){  
        if(!key.startsWith("#")){
            return key;
        }
        //获取被拦截方法参数名列表和参数 用于匹配spel 表达式的值
        LocalVariableTableParameterNameDiscoverer u =   
            new LocalVariableTableParameterNameDiscoverer();  
        String [] paraNameArr=u.getParameterNames(method);
        
        //使用SPEL进行key的解析
        ExpressionParser parser = new SpelExpressionParser(); 
        //SPEL上下文
        StandardEvaluationContext context = new StandardEvaluationContext();
        //把方法参数放入SPEL上下文中
        for(int i=0;i<paraNameArr.length;i++){
            context.setVariable(paraNameArr[i], args[i]);
        }
        
        return parser.parseExpression(key).getValue(context,String.class);
    }
    
}

4. 测试

在某个方法上面加上注解

@InterfaceCacheableDao(key="channeDao",fieldKey="#channelId",expireTime=20)
    public List test(int channelId) {
        ......
    }

大功告成

posted @ 2019-04-30 14:25  牧码人_hh  阅读(529)  评论(0编辑  收藏  举报