编程语言
首页 > 编程语言> > Java配置日志切面

Java配置日志切面

作者:互联网

日志切面配置

什么是切面

面向切面编程(Aspect-oriented Programming 简称AOPAOP) ,是相对面向对象编程(Object-oriented Programming 简称OOP)的框架,作为OOP的一种功能补充. OOP主要的模块单元是类(class)。而AOP则是切面(aspect)。切面会将诸如事务管理这样跨越多个类型和对象的关注点模块化(在AOP的语义中,这类关注点被称为横切关注点(crosscutting))

切面能干什么

事务管理、权限控制、缓存控制、日志打印

使用切面的好处

切面的使用(基于注解)

配置日志切面

1.指定切点

      /**
     *.AOP切入点表达式
     *
     *execution  * com.bonc.service..*.*(..)
     * execution 为切点修饰符
     *      第一个位 为访问修饰符可以不写
     *      第二个 *  方法返回值
     *      第三位为 报名 *代表所有 ..代表所欲子包
     *      第四位为 方法名
     *      第五位  (..)代表任意参数
     *      日志的入口一般为controller层所以切点为所有的controller
     *
     * */
    @Pointcut("execution(* com.bonc..controller..*(..))")
    public void logPointCut() {
    }

2.构建访问日志实体

@Data
public class RequestInfo {

    private String ip;
    private String url;
    private String httpMethod;
    private String classMethod;
    private Object requestParams;
    private Object result;
    private Long timeCost;
    private RuntimeException exception;

}

3.用@Around注解 并且拼装参数

@Around("logPointCut()")
    public Object doAround(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        long start = System.currentTimeMillis();
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();
        RequestInfo requestInfo = new RequestInfo();
        requestInfo.setIp(request.getRemoteAddr());
        requestInfo.setUrl(request.getRequestURL().toString());
        requestInfo.setHttpMethod(request.getMethod());
        requestInfo.setClassMethod(String.format("%s.%s", proceedingJoinPoint.getSignature().getDeclaringTypeName(),
                proceedingJoinPoint.getSignature().getName()));
        requestInfo.setRequestParams(getRequestParamsByProceedingJoinPoint(proceedingJoinPoint));

        Object result =null;
        try {
           result = proceedingJoinPoint.proceed();

        }catch ( RuntimeException e){
            requestInfo.setException(e);
        }
        requestInfo.setResult(result);
        requestInfo.setTimeCost(System.currentTimeMillis() - start);
        LOGGER.info("Request Info      : {}", JSON.toJSONString(requestInfo));
        return  result;
    }



    /**
     * 获取入参
     * @param proceedingJoinPoint
     *
     * @return
     * */
    private Map<String, Object> getRequestParamsByProceedingJoinPoint(ProceedingJoinPoint proceedingJoinPoint) {
        //参数名
        String[] paramNames = ((MethodSignature)proceedingJoinPoint.getSignature()).getParameterNames();
        //参数值
        Object[] paramValues = proceedingJoinPoint.getArgs();

        return buildRequestParam(paramNames, paramValues);
    }


    private Map<String, Object> buildRequestParam(String[] paramNames, Object[] paramValues) {
        Map<String, Object> requestParams = new HashMap<>();
        for (int i = 0; i < paramNames.length; i++) {
            Object value = paramValues[i];
            if (! (value instanceof Serializable)) {
                continue;
            }
            //如果是文件对象
            if (value instanceof MultipartFile) {
                MultipartFile file = (MultipartFile) value;
                value = file.getOriginalFilename();  //获取文件名
            }

            requestParams.put(paramNames[i], value);
        }

        return requestParams;
    }

## 4. 将该类声明为界面 并且将放置到spring容器中

```java
@Component
@Aspect

5.检查是否开启了自动注解

<aop:aspectj-autoproxy/>

6. 启动项目,本地测试一下

正常结果如下

{
	"classMethod": "*******",
	"httpMethod": "GET",
	"ip": "127.0.0.1",
	"requestParams": {
		"pageSize": 10,
		"pageNum": 1
	},
	"result": {
		"code": 200,
		"msg": "成功"
	},
	"timeCost": 84,
	"url": "http://127.0.0.1:8090/*****"
}

异常结果

{
	"classMethod": "**",
	"exception": {
		"@type": "java.lang.ArithmeticException",
		"localizedMessage": "/ by zero",
		"message": "/ by zero",
		"stackTrace": [
			{
				"className": "com.bonc.huanghai.api.controller.oa.AnnouncementController",
				"fileName": "AnnouncementController.java",
				"lineNumber": 70,
				"methodName": "getAnnouncementList",
				"nativeMethod": false
			}
		]
	},
	"httpMethod": "GET",
	"ip": "127.0.0.1",
	"requestParams": {
		"pageSize": 10,
		"pageNum": 1
	},
	"timeCost": 96,
	"url": "http://127.0.0.1:8090/**"
}

代码

最后贴上所有的代码

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.AfterThrowing;
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.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;

/**
 * @author sz
 * @version V1.0
 * @Description: 请求切面(用一句话描述该文件做什么)
 * @date 2021/2/6
 */
@Component
@Aspect
public class RequestLogAspect {

    private final static Logger LOGGER = LoggerFactory.getLogger(RequestLogAspect.class);



    /**
     *.AOP切入点表达式
     *
     *execution  * com.bonc.service..*.*(..)
     * execution 为切点修饰符
     *      第一个位 为访问修饰符可以不写
     *      第二个 *  方法返回值
     *      第三位为 报名 *代表所有 ..代表所欲子包
     *      第四位为 方法名
     *      第五位  (..)代表任意参数
     *      日志的入口一般为controller层所以切点为所有的controller
     *
     * */
    @Pointcut("execution(* com.bonc..controller..*(..))")
    public void logPointCut() {
    }

    @Around("logPointCut()")
    public Object doAround(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        long start = System.currentTimeMillis();
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();
        RequestInfo requestInfo = new RequestInfo();
        requestInfo.setIp(request.getRemoteAddr());
        requestInfo.setUrl(request.getRequestURL().toString());
        requestInfo.setHttpMethod(request.getMethod());
        requestInfo.setClassMethod(String.format("%s.%s", proceedingJoinPoint.getSignature().getDeclaringTypeName(),
                proceedingJoinPoint.getSignature().getName()));
        requestInfo.setRequestParams(getRequestParamsByProceedingJoinPoint(proceedingJoinPoint));

        Object result =null;
        try {
           result = proceedingJoinPoint.proceed();

        }catch ( RuntimeException e){
            requestInfo.setException(e);
        }
        requestInfo.setResult(result);
        requestInfo.setTimeCost(System.currentTimeMillis() - start);
        LOGGER.info("Request Info      : {}", JSON.toJSONString(requestInfo));
        return  result;
    }



    /**
     * 获取入参
     * @param proceedingJoinPoint
     *
     * @return
     * */
    private Map<String, Object> getRequestParamsByProceedingJoinPoint(ProceedingJoinPoint proceedingJoinPoint) {
        //参数名
        String[] paramNames = ((MethodSignature)proceedingJoinPoint.getSignature()).getParameterNames();
        //参数值
        Object[] paramValues = proceedingJoinPoint.getArgs();

        return buildRequestParam(paramNames, paramValues);
    }


    private Map<String, Object> buildRequestParam(String[] paramNames, Object[] paramValues) {
        Map<String, Object> requestParams = new HashMap<>();
        for (int i = 0; i < paramNames.length; i++) {
            Object value = paramValues[i];
            if (! (value instanceof Serializable)) {
                continue;
            }
            //如果是文件对象
            if (value instanceof MultipartFile) {
                MultipartFile file = (MultipartFile) value;
                value = file.getOriginalFilename();  //获取文件名
            }

            requestParams.put(paramNames[i], value);
        }

        return requestParams;
    }

}

@Data
public class RequestInfo {

    private String ip;
    private String url;
    private String httpMethod;
    private String classMethod;
    private Object requestParams;
    private Object result;
    private Long timeCost;
    private RuntimeException exception;

}

标签:Object,Java,requestInfo,proceedingJoinPoint,private,切面,import,日志
来源: https://blog.csdn.net/qq_39684784/article/details/113725944