环境 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()); } }