Spring AOP切面编程切入Controller打印日志

5 篇文章 0 订阅

当Controller层,收到页面请求,我们需要记录一下相关日志,一般我们都是在Controller里的每个方法上加上一段:

logger.info("收到请求");

这样不仅增加代码量,还增加重复代码;

如何进行优化呢?Spring AOP切面编程可以帮助我们实现!

一、我们先引入所需的jar包:

<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<dependency>
	<groupId>org.aspectj</groupId>
	<artifactId>aspectjrt</artifactId>
	<version>1.9.4</version>
</dependency>

二、创建class,使用@Aspect注解,表示这是一个切面,再加上@Component将class加入到Spring容器中;

三、通过@Pointcut注解,选择我们的切入点:

@Pointcut("execution(public * com.example.demo.controller..*.*(..))")
public void anyController() {}

execution(public * com.example.demo.controller..*.*(..))切入Controller层下的所有public方法;

四、通过@before注解,在方法执行前切入,也是打印日志的地方,下面贴出代码:

import com.alibaba.fastjson.JSON;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
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 javax.servlet.http.HttpServletRequest;

@Aspect
@Component
public class RequestLog {

    private final static Logger logger = LoggerFactory.getLogger(RequestLog.class);

    @Pointcut("execution(public * com.example.demo.controller..*.*(..))")
    public void anyController() {}

    /**
     * 方法用途:
     *      这里用JoinPoint切入点
     *      ProceedingJoinPoint切入点只能用在@Around注解<br/>
     * 操作步骤: TODO<br/>
     * ${tags}
     */
    @Before("anyController()")
    public void before(JoinPoint joinPoint) {
        // 请求URL
        requestURI();
        // 请求参数
        Object[] args = joinPoint.getArgs();
        MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
        // 类路径URL
        String methodPackage = methodSignature.getDeclaringTypeName();
        // 方法名
        String method = methodSignature.getMethod().getName();
        StringBuilder builder = new StringBuilder();
        builder.append(methodPackage)
                .append(".")
                .append(method)
                .append(",请求参数:")
                .append(JSON.toJSONString(args));
        logger.info(builder.toString());
    }

    /**
     * 打印请求URL
     */
    private void requestURI() {
        ServletRequestAttributes requestAttributes = (ServletRequestAttributes)RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = requestAttributes.getRequest();
        String requestURL = request.getRequestURI();
        logger.info(String.format("请求URL:%s", requestURL));
    }

}

这样我们就不需要在每个Controller的每个方法里去写打印日志的代码了,还没有结束,如果我们controller方法用了HttpServletRequest,我们的args在转换json就会报错,解决方式很简单,加上try catch捕获异常:

Object[] args = joinPoint.getArgs();
StringBuilder paramBuilder = new StringBuilder();
for (int i = 0; i < args.length; i++) {
    Object obj = args[i];
    try {
        String param = JSON.toJSONString(obj);
        paramBuilder.append(param);
    } catch (Exception e) {
        logger.error("args is HttpServletRequest", e);
    }
}

或者我们切入点改成service层或者自定义一个注解,只在没有用到HttpServletRequest的方法上加上自定义注解,我们的切面切入点改成自定义注解:

import com.example.demo.enums.EditTypeEnum;

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 LogByMethod {

    String remark();

    String editType() default "QUERY";
}

切入点:

@Pointcut(""@annotation(com.example.demo.annotation.LogByMethod)")
public void anyController() {}

在controller方法上加上自定义注解:

@LogByMethod(remark = "查询所有人", editType = "QUERY")
@PostMapping("/queryAll")
public int queryAll(@RequestBody Map<String, String> map) {
    threadService.queryAll();
    return 200;	
}

postman请求:

运行结果:

喜欢的朋友点赞、加关注!

  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值