zoukankan      html  css  js  c++  java
  • 【JavaWeb】利用SpringAOP和redis做缓存

    SpringAOP

    SpringAOP的切点

    面向切面,即在一个切点前后执行某些操作。

    切点定义格式:

    例如定义test包下Controller的test()方法为一个切点:

        @Pointcut("execution(* test.AppController.test(*))")
        public void pointCut(){}

    SpringAOP定义了5种通知:

    通知描述
    前置通知在一个方法执行之前,执行通知。
    后置通知在一个方法执行之后,不考虑其结果,执行通知。
    返回后通知在一个方法执行之后,只有在方法成功完成时,才能执行通知。
    抛出异常后通知在一个方法执行之后,只有在方法退出抛出异常时,才能执行通知。
    环绕通知在建议方法调用之前和之后,执行通知。

    对应格式(引用于https://www.w3cschool.cn/wkspring/k4q21mm8.html):

        @Before("pointCut()")
        public void doBeforeTask(){
         ...
        }
        @After("businessService()")
        public void doAfterTask(){
         ...
        }
        @AfterReturning(pointcut = "businessService()", returning="retVal")
        public void doAfterReturnningTask(Object retVal){
          // you can intercept retVal here.
          ...
        }
        @AfterThrowing(pointcut = "businessService()", throwing="ex")
        public void doAfterThrowingTask(Exception ex){
          // you can intercept thrown exception here.
          ...
        }
        @Around("pointcut()")
        public void doAroundTask(){
         ...
        }

    利用SpringAOP和redis做缓存(基于SpringBoot)

    缓存策略:

    利用环绕通知,在且点前查询redis,若存在,则直接返回查询结果,否则调用数据库查询,并将查询结果保存到redis。

    切面类:

        @Aspect
        @Component
        public class PointCutTest {
            @Autowired
            RedisTemplate<String,String> redisTemplate ;
            @Pointcut("execution(* test.AppController.test(*))")
            public void pointCut(){}
            @Around("pointCut()")
            public Object testBefore(ProceedingJoinPoint joinPoint){
                System.out.println("查询redis...");
                String id = joinPoint.getArgs()[0].toString();
                System.out.println("id="+id);
                Object object = null;
                object = redisTemplate.opsForValue().get(id);
                if (object!=null) {
                    System.out.println("redis获取到缓存,直接返回");
                    return JSONObject.fromObject(object).toString();
                }
    
                System.out.println("redis未找到缓存结果,调用数据库查询...");
                try {
                    object = joinPoint.proceed();
                } catch (Throwable throwable) {
                    throwable.printStackTrace();
                }
                if(object!=null){
                    System.out.println("数据库查询成功,保存到缓存中...");
                    redisTemplate.opsForValue().set(id, JSONObject.fromObject(object).toString());
                }
                System.out.println("查询完成");
                return object;
    
            }
        }

    被切类:(为了方便没有真的查数据库)

        @Controller
        public class AppController {
            @Autowired
            RedisTemplate<String,String> redisTemplate ;
            @ResponseBody
            @RequestMapping("/")
            public String test(int id){
                Stu stu = new Stu();
                System.out.println("模拟数据库查询...");
                stu.setId(id);
                stu.setName("00"+id);
                return JSONObject.fromObject(stu).toString();
            }
        }

    实体类:

        @Entity
        @Table(name = "tb_stu")
        public class Stu {
            @Id
            @GeneratedValue(strategy = GenerationType.IDENTITY)
            private int id;
            @Column
            private String name;
            public int getId() {
                return id;
            }
    
            public void setId(int id) {
                this.id = id;
            }
    
            public String getName() {
                return name;
            }
    
            public void setName(String name) {
                this.name = name;
            }
        }

    测试:

    第一次查询id为1的数据:

        查询redis...
        id=1
        未找到缓存结果,调用数据库查询...
        模拟数据库查询...
        数据库查询成功,保存到缓存中...
        查询完成

    第二次查询id为1的数据:

        查询redis...
        redis id=1
        获取到缓存,直接返回
    

    完成。

  • 相关阅读:
    linux 终端光标消失问题
    linux系统中条件测试语句
    linux shell if语句
    linux shell for循环
    linux 系统中read命令
    linux中while循环语句
    linux shell脚本中流程控制语句 if 、for、while、case
    pc端WINCE的安装包
    WinCE程序的几种开发方法
    Wince 下开发技巧(一)查看内存
  • 原文地址:https://www.cnblogs.com/cnsec/p/13286697.html
Copyright © 2011-2022 走看看