AOP
1. 引入依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
2. 写注解
@Target({ ElementType.PARAMETER, ElementType.METHOD }) //什么能用
@Retention(RetentionPolicy.RUNTIME) // 什么时候起效果 SOURCE:java文件 CLASS:class文件 RUNTIME: 字节码文件
@Documented //告诉Spring这是个切点
public @interface Log
{
/**
* 处理类型
*/
public String handleType() default "";
/**
* 操作功能
*/
public String czgn() default "";
}
3. 操作切点
/**
* 操作切点
*
* @author user
* @date 2022/12/03
*/
@Aspect
@Component
@DependsOn("springFactoryUtils")
public class LogMark {
private Map<String , CzjlMapService> beanMap = SpringFactoryUtils.getBeanMap(CzjlMapService.class);
//1. 定义切点
@Pointcut("@annotation(com.example.yiruo.user.annotation.Log)")
public void logPointCut(){};
//2。 实现切点
//切点前
@Before("logPointCut() && @annotation(log)")
public void beforePointCut(JoinPoint joinPoint,Log log){
Object[] args = joinPoint.getArgs();
CzjlMapService czjlMapService = beanMap.get(log.handleType());
czjlMapService.before(args,log);
}
//切点后执行
@AfterReturning(returning = "result",pointcut = "@annotation(com.example.yiruo.user.annotation.Log)")
public void veforePointCut(JoinPoint joinPoint,Object result){
JSONObject outJson = (JSONObject) result;
if(200 == Integer.valueOf(outJson.get("code").toString())){
Object[] args = joinPoint.getArgs();
//获取 handle
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
String handle = signature.getMethod().getAnnotation(Log.class).handleType();
CzjlMapService czjlMapService = beanMap.get(handle);
czjlMapService.after(args,signature);
}
}
}
@Component
@Slf4j
public abstract class CzjlMapService {
public void before(Object[] args, Log loga){
log.info("handle:{},入参:{}",loga.handleType(),String.valueOf(args));
}
public abstract void after(Object[] args, MethodSignature signature);
}
/**
* 部门查询handle
*
* @author user
* @date 2022/12/03
*/
@Component("bmcx")
@Slf4j
public class BmcxHandle extends CzjlMapService {
@Override
public void after(Object[] args, MethodSignature signature) {
DeptVo dept = (DeptVo) args[0];
log.info("操作功能:{},操作值:{}",signature.getMethod().getAnnotation(Log.class).czgn(),String.valueOf(dept));
}
}
4. 使用切点
@Log(handleType = "aa" ,czgn="部门查询")
@GetMapping("/getlist")
public JSONObject getList(){
}
统一异常拦截
对前后端都比较友好
前端:接口不会暴露
后端:不用在每个接口上写一堆try catch
实现原理
@RestControllerAdvice 和 @ExceptionHandler
@RestControllerAdvice: 扫描所有的controller
@RestControllerAdvice
@Slf4j
public class ExceptionAdvice {
@ResponseBody
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
@ExceptionHandler(Exception.class)
public JSONObject execptionHandler(Exception e){
log.error("执行异常",e);
if(e instanceof MethodArgumentNotValidException){
MethodArgumentNotValidException exception = (MethodArgumentNotValidException) e;
//返回精简信息(具体某个字段没有通过校验的原因)
return JSONObjectUtil.error(exception.getBindingResult().getFieldError().getDefaultMessage())
}
else if(e instanceof ServiceException){
ServiceException exception = (ServiceException) e;
return JSONObjectUtil.error(exception.getMessage());
}
else{
return JSONObjectUtil.error("内部错误,请联系管理员!");
}
}
}
其中 ServiceException是自己定义的异常,MethodArgumentNotValidException是@Valid注解抛出的异常