springCloud使用自定义注解实现redis缓存

springCloud使用自定义注解实现redis缓存

每次使用redis缓存的时候,都要去写redisTemplate相关的代码,第一步先去redis中读数据,有数据就解析并返回。 第二步,如果没有数据,再去调用本地方法读取数据。 第三步,将数据放到redis中。
这就是模板模式的套路,除了redis的key、缓存时间和数据类型不同外,其他的流程都是一样的。如果抽象成模板模式,会省事很多。 如果用自定义注解来实现,则用起来会很爽,每次在目标方法上加个注解,指定一下redis相关的参数就可以了

首先实现自定义注解:


```java
package com.annotation;

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 RedisCache {
    String redisKey() ;  
    String timeOut();  //超时时间, 单位TimeUnit.MILLISECONDS
    String resultObjClass();    //返回数据类型
    String isList() default "false";   //返回数据是否是List
}

定义切点和切面,实现缓存逻辑

```java
package com.annotation;

import com.google.gson.Gson;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonParser;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import java.lang.reflect.Method;
import java.util.*;
import java.util.concurrent.TimeUnit;

@Aspect
@Component
public class RedisCacheAspect {
    private static final Logger logger = LoggerFactory.getLogger(RedisCacheAspect.class);

    @Autowired
    private StringRedisTemplate stringRedisTemplate;  //注入redis模板

    @Pointcut("@annotation(com.annotation.RedisCache)") //定义切点
    public void redisCachePointCut() {
    }

    @Around("redisCachePointCut()")
    public Object around(ProceedingJoinPoint point) throws Throwable {
        MethodSignature signature = (MethodSignature) point.getSignature();
        Method method = signature.getMethod();
        RedisCache redisCache = method.getAnnotation(RedisCache.class);
        try {
            if (redisCache != null) {
                // 注解上的描述
                Gson gson = new Gson();
                String redisKey = redisCache.redisKey();
                Integer timeOut = Integer.parseInt(redisCache.timeOut());
                String resultObj = redisCache.resultObjClass();
                boolean isList = Boolean.parseBoolean(redisCache.isList());
                String realValue = stringRedisTemplate.opsForValue().get(redisKey); //获取redis数据
                if (!StringUtils.isEmpty(realValue)) {
                    logger.info("redisValue:{}", realValue);
                    Class resultObjClass = Class.forName(resultObj);
                    if (isList) {//如果是list类型的返回数据
                        JsonParser jsonParser = new JsonParser();
                        JsonArray jsonArray = jsonParser.parse(realValue).getAsJsonArray();
                        List resultList = new ArrayList();
                        if (jsonArray != null) {
                            for (JsonElement element : jsonArray) {
                                resultList.add(gson.fromJson(element, resultObjClass));
                            }
                        }
                        return resultList;
                    }
                    return gson.fromJson(realValue, resultObjClass);
                } else {
                    Object result = point.proceed();
                    realValue = new Gson().toJson(result);
                    stringRedisTemplate.opsForValue().set(redisKey, realValue, timeOut, TimeUnit.MILLISECONDS);
                    return result;
                }
            }
        }catch (Exception e){
            logger.error("redisCachePointCutError!", e);
            return point.proceed();  //异常直接执行方法
        }
        return null;
    }
}

测试代码,测试不同的数据类型,解析是否支持。

package com.controller;

import com.bo.TestObj;
import com.service.FirstService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;

@RestController
public class FirstController {
    @Autowired
    private FirstService firstService;

    @GetMapping("/hi")
    public String firstMethod(@RequestParam String param){
        return firstService.f(param);
    }
    @GetMapping("/hi2")
    public TestObj firstMethod2(@RequestParam String param){
        return firstService.g(param);
    }
    @GetMapping("/hi3")
    public Integer firstMethod3(@RequestParam Integer param){
        return firstService.i(param);
    }
    @GetMapping("/hi4")
    public List<String> firstMethod4(@RequestParam String param){
        return firstService.j(param);
    }
    @GetMapping("/hi5")
    public List<Integer> firstMethod4(@RequestParam Integer param){
        return firstService.k(param);
    }
    @GetMapping("/hi6")
    public List<TestObj> firstMethod5(@RequestParam Integer param){
        return firstService.l(param);
    }
}

service:

package com.service;

import com.annotation.RedisCache;
import com.bo.TestObj;
import org.springframework.stereotype.Service;

import java.util.Arrays;
import java.util.List;

@Service
public class FirstService {

    @RedisCache(timeOut = "5000", redisKey = "redis_prefix", resultObjClass = "java.lang.String")
    public String f(String param){
        return "hello ni hao :"+param;
    }
    @RedisCache(timeOut = "5000", redisKey = "redis_prefix2", resultObjClass = "com.bo.TestObj")
    public TestObj g(String param){
        TestObj testObj = new TestObj();
        testObj.setName("name:"+param);
        testObj.setDesc("desc:"+param);
        return testObj;
    }

    @RedisCache(timeOut = "5000", redisKey = "redis_prefix3", resultObjClass = "java.lang.Integer")
    public Integer i(Integer param){
        return 2*param;
    }

    @RedisCache(timeOut = "5000", redisKey = "redis_prefix4", resultObjClass = "java.lang.String", isList="true")
    public List<String> j(String param){
        return Arrays.asList("1,","2", param);
    }
    @RedisCache(timeOut = "5000", redisKey = "redis_prefix5", resultObjClass = "java.lang.Integer", isList="true")
    public List<Integer> k(Integer param){
        return Arrays.asList(1,2, param);
    }
    @RedisCache(timeOut = "5000", redisKey = "redis_prefix6", resultObjClass = "com.bo.TestObj", isList="true")
    public List<TestObj> l(Integer param){
        TestObj testObj1= new TestObj();
        TestObj testObj2= new TestObj();
        testObj1.setName("1name"+param);
        testObj2.setName("2name"+param);
        testObj1.setDesc("1desc"+param);
        testObj2.setDesc("2desc"+param);

        return Arrays.asList(testObj1, testObj2);
    }
}

appliation.yml:

spring:
 application:
  name: first_controller
 redis:
  database: 10
  host: 1*2.26.***.3
  port: 8001
  password: ******
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值