場景:當service的方法執行拋出異常時,事務會發生回滾,導致無法記錄錯誤日志
解決:切面
其他:1.日志需要記錄日志標題,保存入參
? ? ? ? ? ?2.失敗時會拋出異常;日志需要判斷執行是否成功,記錄狀態
? ? ? ? ? ?3.只是模擬操作,實際情況需要將日志保存到數據庫
引入依賴:
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-aop</artifactId></dependency>
代碼:
1. 日志記錄時需要加標題,每個方法的日志標題不一樣,解決辦法是切面+自定義注解
package com.test.Annotation;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 LogAnnotation {String logTitle() default "";//日志標題
}
?controller的方法上加注解:
@LogAnnotation(logTitle = "post測試")@PostMapping("/login")public String login(@RequestBody Department department) throws Exception{return "hello World";}
2. 配置切面
package com.test.aspect;import com.test.Annotation.LogAnnotation;
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.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.Arrays;@Aspect
@Component
public class LogAspect {@Autowiredprivate HttpServletRequest request;// @Pointcut("@annotation(com.test.aspect.LogAnnotation)") //單獨設置@Pointcut("execution(* com.test.controller.*.*(..)) && @annotation(com.test.Annotation.LogAnnotation)") //同時設置public void pt() {}@Around("pt()")public Object around(ProceedingJoinPoint joinPoint) throws Throwable {Object result = null;try{MethodSignature signature = (MethodSignature)joinPoint.getSignature();Method method = signature.getMethod();LogAnnotation logAnnotation =method.getAnnotation(LogAnnotation.class);System.out.println("@anno logtitle = " + logAnnotation.logTitle());//自定義注解-日志名稱System.out.println("method = " + method.getName());//方法名System.out.println("params = " + Arrays.toString(joinPoint.getArgs()));//參數,post和get都可以獲取;也可以轉為JSON格式result = joinPoint.proceed();//執行結果,即response返回的數據System.out.println("response = " + result);//todo:記錄狀態為true的日志,dao操作省略return result;}catch (Exception e) {//如果controller的方法執行時發生異常,會被捕獲異常,可以在這里記錄錯誤日志System.out.println("method has exception, e = " + e);//todo:記錄狀態為false的日志,dao操作省略}return result;}
}
3.測試
3.1 get測試:?發送請求:http://localhost:8081/hello?userId=abc
a. get測試-正常請求時
@LogAnnotation(logTitle = "get測試")@GetMapping("/hello")public String hello(@RequestParam(value="userId", required = false) String userId) throws Exception{return "hello World";}
打印:
@anno logtitle = get測試
method = hello
params = [abc]
response = hello World
b. get測試-拋出異常時
@LogAnnotation(logTitle = "get測試")@GetMapping("/hello")public String hello(@RequestParam(value="userId", required = false) String userId) throws Exception{try {int i = 1/0;}catch (Exception e) {throw new Exception("eeeeeee");}return "hello World";}
打印:
@anno logtitle = get測試
method = hello
params = [abc]
method has exception, e = java.lang.Exception: eeeeeee
3.2 post請求
@LogAnnotation(logTitle = "post測試")@PostMapping("/login")public String login(@RequestBody Department department) throws Exception{return "登錄成功";}
post請求,路徑:localhost:8081/login
body:
{"id":1,"departName":"部門名稱"
}
打印
@anno logtitle = post測試
method = login
params = [Department(id=1, departName=部門名稱)]
response = 登錄成功