一、springboot中的aop配置
1、添加依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
2、添加切面类
package com.example.demo.aop;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
import java.util.Arrays;
@Slf4j
@Aspect
@Component
public class LogAspect {
/**
* 可以配置多个切面,来对多个切面做操作,方法名称为方法名,并在下边的before登使用
*
* 非异常顺序:@Around中的方法-->@Before->controller-->@AfterReturning--> @After-->@Around执行完
* 异常顺序:@Around中的方法-->@Before-->controller @AfterThrowing--> @After-->@Around执行完(不捕获异常)
*
* 另外发现一个很又有的注解@SneakyThrows
*/
@Pointcut("execution(public * com.example.demo.controller.*.*(..))")
public void webControllerLog(){}
@Pointcut("execution(public * com.example.demo.service.*.*(..))")
public void webServicePractice(){}
@Before("webServicePractice()")
public void deServiceBefore(JoinPoint joinPoint) throws Throwable {
// 接收到请求,记录请求内容
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletRequest request = attributes.getRequest();
// 记录下请求内容
log.info("URL : " + request.getRequestURL().toString());
System.out.println("URL : " + request.getRequestURL().toString());
System.out.println("HTTP_METHOD : " + request.getMethod());
System.out.println("IP : " + request.getRemoteAddr());
System.out.println("CLASS_METHOD : " + joinPoint.getSignature().getDeclaringTypeName() + "." + joinPoint.getSignature().getName());
System.out.println("ARGS : " + Arrays.toString(joinPoint.getArgs()));
}
@Before("webControllerLog()")
public void deBefore(JoinPoint joinPoint) throws Throwable {
// 接收到请求,记录请求内容
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletRequest request = attributes.getRequest();
// 记录下请求内容
System.out.println("URL : " + request.getRequestURL().toString());
System.out.println("HTTP_METHOD : " + request.getMethod());
System.out.println("IP : " + request.getRemoteAddr());
System.out.println("CLASS_METHOD : " + joinPoint.getSignature().getDeclaringTypeName() + "." + joinPoint.getSignature().getName());
System.out.println("ARGS : " + Arrays.toString(joinPoint.getArgs()));
}
//后置最终通知,final增强,不管是抛出异常或者正常退出都会执行
@After("webControllerLog()")
public void after(JoinPoint jp){
System.out.println("方法最后执行.....");
}
@AfterReturning(returning = "ret", pointcut = "webControllerLog()")
public void doAfterReturning(Object ret) throws Throwable {
// 处理完请求,返回内容
System.out.println("方法的返回值 : " + ret);
}
//后置异常通知
@AfterThrowing(pointcut = "webControllerLog()",throwing = "ex")
public void throwsMethod(JoinPoint jp){
System.out.println("方法异常时执行.....");
}
// /**
// * 环绕通知,环绕增强,相当于MethodInterceptor
// * ***可以不配置,并建议不配置,
// * 如果不配置直接进入before,异常会被捕获到,如果处理了异常则不会进入@AfterThrowing,可以使用 throws Throwable抛出,或者使用@SneakyThrows抛出异常
// */
// @SneakyThrows
// @Around("webControllerLog()")
// public Object arround(ProceedingJoinPoint pjp) {
// System.out.println("方法环绕start.....");
try {
// // 进入@before
// Object o = pjp.proceed();
// System.out.println("方法环绕proceed,结果是 :" + o);
// return o;
// 这个地方如果处理异常,如果发成异常则不会进入@AfterThrowing
} catch (Throwable e) {
e.printStackTrace();
return null;
}
// }
}
3、创建一个测试类
package com.example.demo.controller;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
/**
* 测试aop
*/
@Slf4j
@Api(tags = "测试aop")
@RestController(value = "/aop")
public class AopController {
@RequestMapping(value = "/aop",method = RequestMethod.GET,produces = "application/json;charset=UTF-8" )
@ApiOperation(value = "测试aop",notes = "。。。")
public String aopMethod(){
log.info("controller层返回的方法");
return "aop方法返回";
}
@RequestMapping(value = "/aopException",method = RequestMethod.GET,produces = "application/json;charset=UTF-8" )
@ApiOperation(value = "测试异常aop捕获",notes = "。。。")
public int exceptionMethod(){
log.info("aop异常返回的方法");
return 1/0;
}
}
4、结果
URL : http://localhost:8080/aop
HTTP_METHOD : GET
IP : 0:0:0:0:0:0:0:1
CLASS_METHOD : com.example.demo.controller.AopController.aopMethod
ARGS : []
2020-05-10 16:16:04.877 INFO 8692 --- [nio-8080-exec-9] c.example.demo.controller.AopController : controller层返回的方法
方法最后执行.....
方法的返回值 : aop方法返回
具体的注意事项等在代码中有注释,此文只是一个简单的配置没有解释
二、统一异常处理
@RestControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(Exception.class)
public String customException(Exception e){
return "q3123";
}
}
根据不同的@ExceptionHandler(Exception.class)来捕获不同类型的异常来处理,并根据自己的返回数据类型来处理;
注意:一些情况可能引起@RestControllerAdvice注解的无效,如aop中的环绕处理,如果捕获到了异常则@RestControllerAdvice就无法捕获;