spring boot自定义注解打印日志
在实际项目中可能需要监控每个接口的请求时间以及请求参数等相关信息,那么此时我们想到的就是两种实现方式,一种是通过拦截器实现,另一种则通过AOP自定义注解实现。
本文介绍自定义注解实现方式
自定义注解,四个元注解这次就不解释了。
@Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) public @interface WebLog { /** * 日志信息描述 */ String description() default ""; }
AOP实现:
1.@Order注解用来定义切面的执行顺序,数值越小优先级越高。
2.@Around环绕通知,我们可以自定义在什么时候执行@Before以及@After。
3.ThreadLocal针对每个线程都单独的记录。
@Aspect @Component public class WebLogAspect { private static ThreadLocal<ProceedingJoinPoint> td = new ThreadLocal<>(); @Pointcut("@annotation(com.example.demo.annotation.WebLog)") @Order(1) public void webLog(){} @Before("webLog()") public void doBefor(JoinPoint point){ System.out.println("***********method before执行************"); ServletRequestAttributes attributes = (ServletRequestAttributes)RequestContextHolder.getRequestAttributes(); HttpServletRequest request = attributes.getRequest(); System.out.println("请求URL:"+request.getRequestURL()); System.out.println("请求参数:"+ Arrays.toString(point.getArgs())); System.out.println("***********method before结束************"); } @Around("webLog()") public Object doAround(ProceedingJoinPoint point) throws Throwable { System.out.println("***********执行环绕方法开始************"); td.set(point); long startTime = System.currentTimeMillis(); ProceedingJoinPoint joinPoint = td.get(); Object proceed = joinPoint.proceed(); System.out.println("执行耗时毫秒:"+ (System.currentTimeMillis()-startTime)); System.out.println("***********执行环绕方法结束************"); return proceed; } }
Controller
@RestController public class LoginController { @PostMapping("/user/login") @WebLog(description = "用户登录接口") public UserForm login(@RequestBody UserForm user){ return user; } }
测试结果
通过自定义注解获取日志
1.定义一个注解
package com.hisense.demo02; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** * @author : sunkepeng E-mail : sunkepengouc@163.com * @date : 2020/8/8 20:09 */ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) public @interface Check { }
2.写一个测试用类,并使用注解
package com.hisense.demo02; /** * @author : sunkepeng E-mail : sunkepengouc@163.com * @date : 2020/8/8 20:04 */ public class Calculator { @Check public void add(){ System.out.println("1+0=" + (1+0)); } @Check public void sub(){ System.out.println("1-0=" + (1-0)); } @Check public void mul(){ System.out.println("1*0=" + (1*0)); } @Check public void div(){ System.out.println("1/0=" + (1/0)); } public void show(){ System.out.println("永无bug"); } }
3.使用注解,在测试类中输出log
package com.hisense.demo02; import java.io.BufferedWriter; import java.io.FileWriter; import java.io.IOException; import java.lang.reflect.Method; /** * @author : sunkepeng E-mail : sunkepengouc@163.com * @date : 2020/8/8 21:39 */ public class TestCheck { public static void main(String[] args) throws IOException { Calculator calculator = new Calculator(); Class calculatorClass = calculator.getClass(); Method[] methods = calculatorClass.getMethods(); int number =0; BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter("bug.txt")); for (Method method : methods) { if (method.isAnnotationPresent(Check.class)){ try { method.invoke(calculator); } catch (Exception e) { number++; bufferedWriter.write(method.getName()+"出现异常"); bufferedWriter.newLine(); bufferedWriter.write("异常的名称:"+e.getCause().getClass().getSimpleName()); bufferedWriter.newLine(); bufferedWriter.write("异常的原因"+e.getCause().getMessage()); bufferedWriter.newLine(); bufferedWriter.write("-----------------"); bufferedWriter.newLine(); } } } bufferedWriter.write("本次共出现:"+number+"次异常"); bufferedWriter.flush(); bufferedWriter.close(); } }
以上为个人经验,希望能给大家一个参考,也希望大家多多支持。