@Retention自定义注解,切面缓存

1.先创建一个自定义注解需要用到@Retention 注解

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 *@Description TODO 基于注解+Redis 实现方法级缓存
 *@Version 1.0
 */
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface MethodCache {


    /**
     * 指定缓存的过期时间, 默认60秒
     *
     * @return int
     */
    int expireSeconds() default 60;

    /**
     * 缓存的key, 如果不指定, 默认按照方法的签名作为key
     *
     * @return String
     */
    String key() default "";

    /**
     * 缓存开启标志 默认开启
     *
     * @return boolean
     */
    boolean limitQuery() default true;

    /**
     * 说明
     * @return
     */
    String explain() default "";


}

上述注解定义好我们可以在方法上使用

@MethodCache(expireSeconds = 1200,key = "cacheKey",explain = "列表信息")

 2.定义切面进入的标准利用上述建的MethodCache注解


import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.application.core.util.domain.Response;
import com.factory.annotation.MethodCache;
import com.factory.util.HashAlgorithms;
import com.factory.util.RedisUtil;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.lang.reflect.Method;
import java.net.HttpCookie;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * @ClassName MethodCacheAspect
 * @Description TODO 定义缓存切面
 * @Version 1.0
 */
@Aspect
@Order(value = 2)
@Component
public class MethodCacheAspect {

    @Resource
    private RedisUtil redisUtil;
    //定义MethodCacheKey唯一标识,方便对Key做统一的处理
    private final String METHOD_CACHE_KEY = "MethodCacheKey-";

    private static Logger log = LoggerFactory.getLogger(MethodCacheAspect.class);

    /**
     * 切面具体的操作
     *
     * @param proceedingJoinPoint 切面
     * @param methodCache         注解
     * @return Object
     * @throws Throwable 抛出异常
     */
    @Around("@annotation(methodCache)")
    public Object execute(ProceedingJoinPoint proceedingJoinPoint, MethodCache methodCache) throws Throwable {
            MethodSignature methodSignature = (MethodSignature) proceedingJoinPoint.getSignature();
        Method method = methodSignature.getMethod();

        if(StringUtils.isNotEmpty(methodCache.explain())){
            log.info("[MethodCache]加载方法{}",methodCache.explain());
        }else{
            log.info("[MethodCache]加载方法{}",method.getName());
        }
        // 解析请求参数
        List<Object> list = parseRequestParam(proceedingJoinPoint);
        // 根据方法获取相应的key
        String key = methodCache.key();
        if (StringUtils.isBlank(key)) {
            key = getSignature(method);
        }
        key =METHOD_CACHE_KEY + key + HashAlgorithms.mixHash(JSON.toJSONString(list));
        log.info("[MethodCacheKey]:{}",key);
        Object deserialize = tryGetFromCache(key);
        if (deserialize != null) {
            return deserialize;
        }
        Object proceed;
        if (methodCache.limitQuery()) {
            proceed = executeConcreteMethod(proceedingJoinPoint);
            redisUtil.set(key, JSON.toJSONString(proceed));
            redisUtil.expire(key, methodCache.expireSeconds(),TimeUnit.SECONDS);
        } else {
            // 允许查询
            proceed = executeConcreteMethod(proceedingJoinPoint);
        }
        return proceed;
    }

    /**
     * 执行具体的方法
     *
     * @param proceedingJoinPoint 切面
     * @return Object
     * @throws Throwable 异常
     */
    private Object executeConcreteMethod(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        return proceedingJoinPoint.proceed();
    }

    /**
     * 尝试从缓存中获取
     *
     * @param key key
     * @return Object
     */
    private Object tryGetFromCache(String key) {
        if(!redisUtil.hasKey(key)){
            return null;
        }
        String result = redisUtil.get(key);
//        log.info("[MethodCache]读取缓存中信息:{}",result);
        if(result != null){
            return JSONObject.parseObject(result,Response.class);
        }
        return null;
    }

    /**
     * 解析请求参数
     *
     * @param proceedingJoinPoint 切面
     * @return List<Object>
     */
    private List<Object> parseRequestParam(ProceedingJoinPoint proceedingJoinPoint) {
        // 方法参数解析
        int size = proceedingJoinPoint.getArgs().length;
        Object[] args = proceedingJoinPoint.getArgs();
        List<Object> argList = new ArrayList<>();
        for (int i = 0; i < size; i++) {
            if (args[i] instanceof HttpServletRequest) {
                HttpServletRequest request = (HttpServletRequest) args[i];
                argList.add(request.getParameterMap());
            } else if (args[i] instanceof HttpServletResponse || args[i] instanceof HttpSession
                    || args[i] instanceof HttpCookie) {
                continue;
            } else {
                argList.add(args[i]);
            }
        }
        return argList;
    }

    /**
     * 生成方法签名
     *
     * @param method 方法
     * @return String
     */
    private String getSignature(Method method) {
        StringBuilder sb = new StringBuilder();
        String methodName = method.getName();
        if (StringUtils.isNotBlank(methodName)) {
            sb.append(method).append("#");
        }
        return sb.toString();
    }



}

3.现在就可以使用注解了切面缓存查询了

//缓存查询
@MethodCache(expireSeconds = 1200,key = "cacheKey",explain = "列表") 
@GetMapping(value = "findCacheKey")
    public Response findCacheKey(@RequestParam(required = true) String channelCode,@RequestParam(required = true)String comCode) {
        //上面用到@MethodCache注解 会先切面查询缓存 缓存没有查询到再进入此方法查询
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值