IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> SpringBoot-AOP环绕通知记录日志/鉴权 -> 正文阅读

[Java知识库]SpringBoot-AOP环绕通知记录日志/鉴权

1、问题描述

微信公号h5开发,前后端分离,因为是在微信公号里面操作页面,还有涉及到不同手机操作也不一样,导致联调比较麻烦,定位问题也麻烦,以前写过通过aop记录所有前端http请求,就又拿出来梳理了下,记录日志,记录下,希望可以帮到有需要的朋友。

2、解决方案

项目是springboot项目,通过springboot-aop,配置环绕通知,记录调用地址、入参、返回参数、ip,同时记录执行时间等,以便定位问题。具体的入库就是弄个表,保存下获取到的值,这里就不多做介绍了。

2.1 AOP简要说明

(1)什么是AOP?

AOP为Aspect Oriented Programming的缩写,是面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。

(2)AOP的五种通知方式

前置通知(Before):在目标方法或者说连接点被调用前执行的通知;
后置通知(After):指在某个连接点完成后执行的通知;
返回通知(After-returning):指在某个连接点成功执行之后执行的通知;
异常通知(After-throwing):指在方法抛出异常后执行的通知;
环绕通知(Around):指包围一个连接点通知,在被通知的方法调用之前和之后执行自定义的方法。

(3)说明

软件老王用的比较多的是前置通知和环绕通知;

前置通知用于权限控制的比较多一些,简单说就是再http请求调用方法前,进行鉴权校验等,鉴权通过再放行;

后置通知也简单用过,记录返回值的,用的不是很多;

然后就是用的最多的环绕通知,环绕通知=前置通知+后置通知,记录日志非常方便;

2.2 pom文件配置

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-aop</artifactId>
        </dependency>

springboot项目下,gav配置后,代码中直接使用标签就可以配置aop通知了,非常方便。

2.3 代码分解介绍

import com.alibaba.fastjson.JSON;
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.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;

@Aspect
@Component
public class WebLogAspect {
    @Pointcut("execution(public * com.spring.wx.oauth.conntroller.*.*(..))")
    public void webLog(){

    }
    @Around("webLog()")
    public Object saveSysLog(ProceedingJoinPoint proceedingJoinPoint) {

        System.out.println("环绕通知开始。。。。。");

        MethodSignature signature = (MethodSignature) proceedingJoinPoint.getSignature();
        Method method = signature.getMethod();

        String className = proceedingJoinPoint.getTarget().getClass().getName();
        String methodName = method.getName();

        System.out.println(className);
        System.out.println(methodName);
        System.out.println(className + "." + methodName);

        //请求的参数
        Object[] args = proceedingJoinPoint.getArgs();
        String params = JSON.toJSONString(args);
        System.out.println(params);

        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();

        // 记录下请求内容
        System.out.println("URL : " + request.getRequestURL().toString());
        System.out.println("HTTP_METHOD : " + request.getMethod());
        System.out.println("IP : " + request.getRemoteAddr());


        //记录时间
        long start = System.currentTimeMillis();
     Object result =null;
        try {
            result = proceedingJoinPoint.proceed();
            System.out.println(result.toString());
        } catch (Throwable throwable) {
            throwable.printStackTrace();
            System.out.println(throwable.getMessage());
        }

        Long time = System.currentTimeMillis() - start;
        System.out.println(time);
        System.out.println("环绕通知结束。。。。。");
        return result;
    }
}

说明:

(1)两个标签,@Component和@Aspect,@Component标签,将类加入到spring容器,@Aspec,aop通知标签,只有pom中配置了gav才会有;

(2) @Pointcut,定义切入点,软件老王这里配置的conntroller包下的所有类;

    @Pointcut("execution(public * com.spring.wx.oauth.conntroller.*.*(..))")
    public void webLog(){

    }

(3) @Around(“webLog()”),环绕通知,value为上面配置的切入点;

    @Around("webLog()")
    public void saveSysLog(ProceedingJoinPoint proceedingJoinPoint) 

(4)接着就是使用取值入库或打印

 //打印请求的类和方法
 System.out.println(className + "." + methodName);
 //打印入参
 System.out.println(params);
 
 // 记录下请求内容
 System.out.println("URL : " + request.getRequestURL().toString());
 System.out.println("HTTP_METHOD : " + request.getMethod());
 System.out.println("IP : " + request.getRemoteAddr());
 //记录执行时间
 System.out.println(time);
 

2.4 执行验证

2.4.1 controller类

简单的两个测试方法,一个是返回有异常;一个是正常执行,分别是laowang和shuaige

    @ResponseBody
    @GetMapping("/laowang")
    public String laowang(String test) {

        userService.laowang();
        return "SUCCESS";
    }

    @ResponseBody
    @GetMapping("/shuaige")
    public UserEntity shuaige(String test) {
        UserEntity userEntity = userService.shuaige();
        return userEntity;
    }

2.4.2 service类

    public void laowang() {
        UserEntity userEntity = new UserEntity();
        userEntity.setType(0);
        userEntity.setOpenid("1111");
        insert(userEntity);

        int i = 1/0;
//        System.out.println(i);
    }
    public UserEntity shuaige() {
        UserEntity userEntity = new UserEntity();
        userEntity.setType(0);
        userEntity.setOpenid("1111");

        return userEntity;
    }

2.4.3 运行过程及说明

(1)浏览器地址:http://localhost/laowang?test=333,首先不会进入执行方法,而是进入aop通知;

(2) 执行过程

(3)进入执行方法体,laowang方法是抛异常的方法体(1/0),报错前;

(4)try-catch捕获异常,并打印出来,记录执行时间

(5)shauige方法,无异常方法

浏览器地址:http://localhost/shuaige?test=333,执行过程;

(6)shuaige方法执行完毕,打印返回参数和时间。

3、总结

我们的业务主要需求是:记录入参、出参、执行时间,方便定位问题,AOP的环绕通知已经能满足了;

入参:params;

出参:result.toString(),同时假如方法执行有异常,会将异常记录下来;

执行时间:time;

—20210813–
修改两行代码,增加了通知的返回,通知不返回的话,会把后端方法的返回给“吃掉”,导致前端无法获取后端返回数据(异常)。

 @Around("webLog()")
    public Object saveSysLog(ProceedingJoinPoint proceedingJoinPoint) {
    			return result;
    }

更多信息请关注公众号:「软件老王」,关注不迷路,软件老王和他的IT朋友们,分享一些他们的技术见解和生活故事。

  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2021-08-19 11:55:18  更:2021-08-19 11:55:35 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 8:54:00-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码