環境 SpringBoot2.0
maven
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-aop</artifactId> </dependency> <dependency> <groupId>com.google.code.gson</groupId> <artifactId>gson</artifactId> <version>2.8.2</version> </dependency>
自定義一個注解MyLog
package com.zns.annotation; import java.lang.annotation.*; @Target({ ElementType.PARAMETER, ElementType.METHOD }) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface MyLog { /** 描述 */ String desc() default ""; }
增加一個切面MyLogAspect
package com.zns.aspect; import com.google.gson.Gson; import com.zns.annotation.MyLog; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.*; import org.aspectj.lang.reflect.MethodSignature; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.scheduling.annotation.EnableAsync; import org.springframework.stereotype.Component; import org.springframework.web.context.request.RequestContextHolder; import org.springframework.web.context.request.ServletRequestAttributes; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; import java.net.URLDecoder; import java.util.Arrays; import java.util.stream.Collectors; @Aspect @Component @EnableAsync public class MyLogAspect { private static final Logger logger = LoggerFactory.getLogger(MyLogAspect.class); @Autowired private Gson gson; /** * 用包名的方式定義切入點 */ /*@Pointcut("execution(* com.zns.controller.*.*(..))") public void pointCut() { }*/ /** * 用注解的方式定義切入點 */ @Pointcut("@annotation(com.zns.annotation.MyLog)") public void pointCut() { } /** * 前置通知 * * @param joinPoint */ @Before("pointCut()") public void doBeforeAdvice(JoinPoint joinPoint) { //System.out.println("進入方法前執行....."); } /** * 后置異常通知 */ @AfterThrowing("pointCut()") public void throwss(JoinPoint jp) { //System.out.println("方法異常時執行....."); } /** * 后置最終通知,final增強,不管是拋出異常或者正常退出都會執行 */ @After("pointCut()") public void after(JoinPoint jp) { //System.out.println("方法最后執行....."); } /** * 處理完請求,返回內容 * * @param ret */ @AfterReturning(returning = "ret", pointcut = "pointCut()") public void doAfterReturning(Object ret) { //System.out.println("方法的返回值 : " + ret); } /** * 環繞通知,相當於MethodInterceptor */ @Around("pointCut()") public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable { //請求返回信息 Object res = null; //請求開始時間 long startTime = System.currentTimeMillis(); //請求結束時間 long endTime = 0L; //請求時長(毫秒) long duration = 0L; try { //執行方法 res = joinPoint.proceed(); endTime = System.currentTimeMillis(); duration = endTime - startTime; return res; } finally { try { //方法執行完成后增加日志 MethodSignature signature = (MethodSignature) joinPoint.getSignature(); HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); //客戶端操作系統 String osName = System.getProperty("os.name"); //客戶端操作系統版本 String osVersion = System.getProperty("os.version"); //客戶端瀏覽器的版本類型 String userAgent = request.getHeader("user-agent"); //請求ip String requestIp = request.getRemoteAddr(); //請求url String requestUrl = request.getRequestURL().toString(); //請求uri String requestUri = request.getRequestURI(); //請求方式 get,post等 String requestType = request.getMethod(); //請求參數 String requestParam = getParams(joinPoint, request); //請求執行的類路徑 String classPath = signature.getDeclaringTypeName(); //請求執行的方法名 String methodName = signature.getName(); //獲取注解的自定義屬性 MyLog annotation = signature.getMethod().getAnnotation(MyLog.class); String desc = ""; if (annotation != null) { desc = annotation.desc(); } //輸出 System.out.println("客戶端操作系統: " + osName); System.out.println("客戶端操作系統版本: " + osVersion); System.out.println("客戶端瀏覽器的版本類型: " + userAgent); System.out.println("請求ip: " + requestIp); System.out.println("請求url: " + requestUrl); System.out.println("請求uri: " + requestUri); System.out.println("請求方式: " + requestType); System.out.println("請求參數: " + requestParam); System.out.println("請求執行的類路徑: " + classPath); System.out.println("請求執行的方法名: " + methodName); System.out.println("請求執行的方法描述: " + desc); System.out.println("請求開始時間: " + startTime); System.out.println("請求結束時間: " + endTime); System.out.println("請求時長(毫秒): " + duration); System.out.println("請求返回信息: " + gson.toJson(res)); } catch (Exception e) { System.out.println(e.getMessage()); e.printStackTrace(); } } } /** * 獲取請求參數 支持get,post(含與不含@RequestBody接收都可以獲取) * * @param joinPoint * @param request * @return * @throws Exception */ public String getParams(JoinPoint joinPoint, HttpServletRequest request) throws Exception { String method = request.getMethod(); String queryString = request.getQueryString(); String params = ""; Object[] args = joinPoint.getArgs(); if (args.length > 0) { if ("POST".equals(method)) { Object object = args[0]; //過濾掉 ServletRequest 和 ServletResponse 類型的參數 Object paramObject = Arrays.stream(args).filter(t -> !(t instanceof ServletRequest) && !(t instanceof ServletResponse)).collect(Collectors.toList()); params = gson.toJson(paramObject); } else if ("GET".equals(method)) { params = queryString; } params = URLDecoder.decode(params, "utf-8"); } return params; } }
控制器調用測試
package com.zns.controller; import com.zns.annotation.MyLog; import com.zns.bean.Person; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @RestController public class TestController { @RequestMapping(path = "/hello") @MyLog(desc = "這是一個hello") public String testHello(HttpServletRequest request, HttpServletResponse response) throws Exception { return "hello,world"; } @RequestMapping(path = "/query") @MyLog(desc = "這是一個查詢") public Person query(@RequestBody Person person,HttpServletRequest request, HttpServletResponse response) throws Exception { return new Person(person.getId(), person.getName()); } }