redis通用缓存 (注解版) 新

redis通用缓存(注解版)旧

一、引入相关依赖

<!--springData操作redis-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!--aop-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-aop</artifactId>
</dependency>

二、配置redis

spring:
  redis:
    host: 123.456.789.123   #ip地址
    port: 8888   #端口号
    database: 8   #操作的库
    password: 123456

三、创建一个切面类

package com.zsq.cache;

import com.alibaba.fastjson.JSON;
import com.micro.product.annotation.AddCache;
import com.micro.product.annotation.DelCache;
import org.apache.commons.lang.ArrayUtils;
import org.apache.commons.lang.StringUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.core.HashOperations;
import org.springframework.data.redis.core.RedisTemplate;

import javax.annotation.Resource;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;


@Configuration  //声明这个类是配置类
@Aspect //定义这是切面类
public class RedisCache {

    @Resource
    private RedisTemplate<String, Object> redisTemplate;


    /**
     *  添加缓存方法
     *  @Around注解是:  定义是环绕方法
     *  @annotation(com.zsq.annotcation.AddCache)
     *  @AddCache是自定义注解,把注解放在要添加缓存的方法上
     */
    @Around("@annotation(com.zsq.annotcation.AddCache)")
    public Object around(ProceedingJoinPoint proceedingJoinPoint){
    //获取方法签名
    MethodSignature signature = (MethodSignature) proceedingJoinPoint.getSignature();
        //获取被拦截的方法
        Method method = signature.getMethod();
        //获取方法上的注解信息
        AddCache addCache = method.getAnnotation(AddCache.class);
        //校验是否配置缓存key
        String key = addCache.key();
        if (StringUtils.isEmpty(key)) {
            //获取类的全路径名称
            key = proceedingJoinPoint.getTarget().getClass().getName();
        }
        //判断key前缀是否存在
        if (!StringUtils.isEmpty(addCache.keyPrefix())) {
            key = addCache.keyPrefix() + ":" + key;
        }
        //获取所有hashKey
        String hashKey = addCache.hashKey();
        if (StringUtils.isEmpty(hashKey)) {
            //获取类的全路径名称
            hashKey = proceedingJoinPoint.getSignature().getName();
        }
        //判断hashKey前缀是否存在
        if (!StringUtils.isEmpty(addCache.keyHashPrefix())) {
            hashKey = addCache.keyHashPrefix() + ":" + hashKey;
        }

        //创建存储方法中参数的数组
        Object[] args = null;

        //校验是否要携带参数信息
        if (addCache.carryArgs()) {
            //获取所有参数
            args = proceedingJoinPoint.getArgs();
            //判断是否有移除的参数
            int[] removeArgsIndex = addCache.removeArgsIndex();
            //判断方法参数不为空,并且需要移除无用参数
            if (ArrayUtils.isNotEmpty(args) && ArrayUtils.isNotEmpty(removeArgsIndex)) {
            	//创建存储
                ArrayList<Object> argList = new ArrayList<>();
                //将数组转集合
                List<Integer> removeArgsIndexList = Arrays.asList(ArrayUtils.toObject(removeArgsIndex));
                for (int i = 0; i < args.length; i++) {
                	//存储不移除的参数信息
                    if (!removeArgsIndexList.contains(i)) {
                        argList.add(args[i]);
                    }
                }
                args = argList.toArray();
            }
        }
        //判断参数信息是否为空,不为空则拼接到hashKey中
        if (ArrayUtils.isNotEmpty(args)) {
            hashKey = hashKey + ":" + JSON.toJSONString(args);
        }
        HashOperations<String, String, Object> opsForHash = redisTemplate.opsForHash();
        //判断缓存中是否有数据
        Boolean hasKey = opsForHash.hasKey(key, hashKey);
        Object result = null;
        if (hasKey) {
            //如果有返回数据
            result = opsForHash.get(key, hashKey);
        } else {
            //把数据存到redis中
            try {
                //获取切入方法的返回值
                result = proceedingJoinPoint.proceed();
                //存储到redis中
                opsForHash.put(key, hashKey, result);
                //获取是否设置超时时间
                long timeout = addCache.timeout();
                if (timeout != -1) {
                    //设置可以超时时间
                    redisTemplate.expire(key, timeout, addCache.unit());
                }
            } catch (Throwable throwable) {
                throwable.printStackTrace();
            }
        }
        return result;
    }

    /**
     *  清空缓存
     *	@After:后置通知
     *  @annotation(com.zsq.annotcation.DelCache)
     *  @DelCache是自定义注解,把注解放在要清空缓存的方法上
     */
    @After("@annotation(com.zsq.annotcation.DelCache)")
    public void after(JoinPoint joinPoint){
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        //获取被拦截的方法
        Method method = signature.getMethod();
        DelCache delCache = method.getAnnotation(DelCache.class);
        //获取要清除的key
        String[] keys = delCache.key();
        //判断清除key是否为空,如果为空默认为方法名
        if (ArrayUtils.isEmpty(keys)) {
            keys = new String[]{joinPoint.getTarget().getClass().getName()};
        }
        //获取所有的hashKey
        String[] hashKeys = delCache.hashKey();
        try {
            //校验hashKey是否为空,如果不为为空则直接删除key
            if (ArrayUtils.isEmpty(hashKeys)) {
                //校验hashKey是否配置前缀
                String keyPrefix = delCache.keyPrefix();
                //删除hashKey
                for (String key : keys) {
                    redisTemplate.delete(StringUtils.isEmpty(keyPrefix) ? key : keyPrefix + ":" + key);
                }
            } else {
                HashOperations<String, String, Object> operations = redisTemplate.opsForHash();
                String keyHashPrefix = delCache.keyHashPrefix();
                //删除每个key的hashKey
                for (String key : keys) {
                    for (String hashKey : hashKeys) {
                        operations.delete(key, StringUtils.isEmpty(keyHashPrefix) ? hashKey : keyHashPrefix + ":" + hashKey);
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}

四、创建自定义注解

放在你要切的方法上

package com.zsq.annotcation;

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

/**
 * 添加缓存注解
 */
@Target(ElementType.METHOD)//只能在方法上生命声明
@Retention(RetentionPolicy.RUNTIME)//运行时生效
public @interface AddCache {

    /**
     * key前缀
     *
     * @return
     */
    String keyPrefix() default "";

    /**
     * redis存储key
     * 默认是当前使用注解方法的全路径类名
     *
     * @return
     */
    String key() default "";

    /**
     * hashKey前缀
     *
     * @return
     */
    String keyHashPrefix() default "";

    /**
     * redis存储hashKey
     * 默认是当前使用注解方法的  方法名:参数
     *
     * @return
     */
    String hashKey() default "";

    /**
     * hashKey是否携带参数
     *
     * @return
     */
    boolean carryArgs() default true;

    /**
     * 要移除携带参数的下标,从0开始
     *
     * @return
     */
    int[] removeArgsIndex() default {};

    /**
     * 设置key超时时间
     * @return
     */
    long timeout() default -1;

    /**
     * 设置超时时间单位,默认为秒
     * @return
     */
    TimeUnit unit() default TimeUnit.SECONDS;

}

package com.zsq.annotcation;


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

/**
 * 清空缓存注解
 */
@Target(ElementType.METHOD)//只能在方法上使用
@Retention(RetentionPolicy.RUNTIME)//运行时生效
public @interface DelCache {

    /**
     * key前缀
     *
     * @return
     */
    String keyPrefix() default "";

    /**
     * redis存储key
     * 默认是当前使用注解方法的全路径类名
     *
     * @return
     */
    String[] key() default {};


    /**
     * hashKey前缀
     *
     * @return
     */
    String keyHashPrefix() default "";

    /**
     * redis存储hashKey
     * 默认删除当前key下的所有hash信息
     *
     * @return
     */
    String[] hashKey() default {};

}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值