一.redis基础配置
本项目采用基础ssm配置来实现,首先我们使用redis来做缓存,那么我们就需要先在spring中整合redis。

  1. 整合第一步,导入对应依赖。
    有关redis的配置
    <!--redis -->
    <dependency>
      <groupId>org.springframework.data</groupId>
      <artifactId>spring-data-redis</artifactId>
      <version>1.6.2.RELEASE</version>
    </dependency>


    <dependency>
      <groupId>redis.clients</groupId>
      <artifactId>jedis</artifactId>
      <version>2.9.0</version>
    </dependency>
  1. 第二步在spring配置文件中配置对应的redis配置
 <!--jedis配置-->
    <bean id="poolConfig" class="redis.clients.jedis.JedisPoolConfig">
        <property name="maxIdle" value="${maxIdle}"/>
        <property name="maxWaitMillis" value="${redis.maxWait}"/>
        <property name="testOnBorrow" value="${redis.testOnBorrow}"/>
    </bean>

    <bean id="connectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory">
        <property name="poolConfig" ref="poolConfig"/>
        <property name="port" value="${redis.port}"/>
        <property name="hostName" value="${redis.host}"/>
        <property name="password" value="${redis.password}"/>
        <property name="timeout" value="${redis.timeout}"/>
    </bean>

    <bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate">
        <property name="connectionFactory" ref="connectionFactory"/>
        //这里是键的序列化
        <property name="keySerializer">
            <bean class="org.springframework.data.redis.serializer.StringRedisSerializer"/>
        </property>
        //这里是值的序列化
        <property name="valueSerializer">
            <bean class="org.springframework.data.redis.serializer.JdkSerializationRedisSerializer"/>
        </property>
    </bean>

二.
做缓存的对象都是查询操作,从这一点我们可以想到使用spring的aop来对对应的查询操作进行拦截处理,步骤如下。

  1. 书写配置文件定义对应的切面类,切点。
//下面这行配置需要在spring的两个配置文件中都书写
	<aop:aspectj-autoproxy/>

    <bean id="redisUtil" class="com.by.util.RedisUtil">
        <property name="redisTemplate" ref="redisTemplate"/>
    </bean>

    <bean id="methodInterceptor" class="com.by.interceptor.CacheInterceptor">
        <property name="redisUtil" ref="redisUtil"/>
    </bean>


    <aop:config>
        <aop:pointcut id="controllerMethodPointcut" expression="execution(* com.by.service.*.query*(..))"/>
        <aop:advisor advice-ref="methodInterceptor" pointcut-ref="controllerMethodPointcut"/>
    </aop:config>
  1. 书写对应的redis工具类,这一步操作是为了方便我们书写切面类。
package com.by.util;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;

import java.io.Serializable;
import java.util.concurrent.TimeUnit;

/**
 * redis操作工具类
 */
public class RedisUtil {


    private RedisTemplate<Serializable, Object> redisTemplate;

    /**
     * 判断是否有key
     *
     * @param key
     * @return
     */
    public boolean exists(String key) {
        return redisTemplate.hasKey(key);
    }


    /**
     * 删除对应的value
     *
     * @param key
     */
    public void remove(String key) {
        if (exists(key)) {
            redisTemplate.delete(key);
        }
    }


    /**
     * 批量删除对应的value
     *
     * @param keys
     */
    public void remove(String... keys) {
        for (String key : keys) {
            remove(key);
        }
    }

    /**
     * 写入缓存
     *
     * @param key
     * @param value
     * @return
     */
    public boolean set(String key, Object value) {
        boolean result = false;
        try {
            ValueOperations<Serializable, Object> operations = redisTemplate.opsForValue();
            operations.set(key, value);
            result = true;
        } catch (Exception e) {
            e.printStackTrace();
        }

        return result;
    }

    /**
     * 写入缓存,并设置有效期
     *
     * @param key
     * @param value
     * @param expireTime
     * @return
     */
    public boolean set(String key, Object value, Long expireTime) {
        boolean result = false;
        try {
            redisTemplate.opsForValue().set(key, value);
            redisTemplate.expire(key, expireTime, TimeUnit.SECONDS);
            result = true;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }

    /**
     * 读取缓存
     *
     * @param key
     * @return
     */
    public Object get(String key) {
        Object result = null;
        ValueOperations<Serializable, Object> operations = redisTemplate.opsForValue();
        result = operations.get(key);
        return result;

    }

    public void setRedisTemplate(RedisTemplate<Serializable, Object> redisTemplate) {
        this.redisTemplate = redisTemplate;
    }
}

  1. 书写对应的拦截类(切面类),在这个类中我们拦截对应的
package com.by.interceptor;

import com.by.util.RedisUtil;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import java.util.Map;

public class CacheInterceptor implements MethodInterceptor {

    private RedisUtil redisUtil;

    private Long defaultCacheExpireTime;

    /**
     * 加载缓存有效时间
     */
    public CacheInterceptor() {
        defaultCacheExpireTime = 3600L;
    }

    @Override
    public Object invoke(MethodInvocation invocation) throws Throwable {
        Object value = null;

        //类名
        String targetName = invocation.getThis().getClass().getName();
        //方法名
        String methodName = invocation.getMethod().getName();
        //参数数组
        Object[] args = invocation.getArguments();
        Map<String, Object> maps = (Map<String, Object>) args[0];
        String pageSize = String.valueOf(maps.get("pageSize"));
        String pageNum = String.valueOf(maps.get("pageNum"));

        Object[] arguments = {pageNum + ":" + pageSize};
        String key = getCacheKey(targetName, methodName, arguments);

        //如果redis有数据,取出
        if (redisUtil.exists(key)) {
            return redisUtil.get(key);
        }
        //这里调用的方法是用来调用对应的代理实现方法,也就是分页查询方法
        value = invocation.proceed();
        //如果没有,写入
        if (value != null) {
            String tkey = key;
            Object tval = value;
            new Thread(new Runnable() {
                @Override
                public void run() {
                    redisUtil.set(tkey, tval, defaultCacheExpireTime);
                }
            }).start();
        }

        return value;
    }

    public String getCacheKey(String targetName, String methodName, Object[] args) {
        StringBuffer sbu = new StringBuffer();
        sbu.append(targetName).append("_").append(methodName);
        //如果有参数,一起拼接
        if ((args != null) && (args.length != 0)) {
            for (int i = 0; i < args.length; i++) {
                sbu.append("_").append(args[i]);
            }
        }
        return sbu.toString();

    }


    public void setRedisUtil(RedisUtil redisUtil) {
        this.redisUtil = redisUtil;
    }
}

到这里我们就实现了使用aop和redis来实现分页缓存

更多推荐