应对场景
在一些项目中,会有这样的一个场景,对某个接口所接受到的所有请求,进行入库记录,并记载该次请求的状态(成功与否),或业务中涉及任务时,也需要对该任务进行入库记录甚至跟踪。
最简单的实现方式,是在controler层接收到请求后,解析入参并入库保存请求(任务)信息,service层处理完逻辑后再解析返回并更新任务信息。
但这只是一次顺利的请求并成功返回的场景,如果接口返回失败,或在service层的任意地方发生异常、err,都让任务的数据库更新操作很难完成。当然,应对代码抛出异常的问题,结合全局参数异常捕获器(@RestControllerAdvice)也能有效解决任务更新问题,但代码总归是比较臃肿。
解决方案
使用AOP编程思想,结合反射、注解等知识,为接口搭建“门卫”,达到出入记录的目的。
详细逻辑是,在controller层接收到请求前,对请求进行解析并入库记录,在controller层接口返回后(包括成功,失败,异常)对请求进行解析并入库更新。
思路整理:
- 在接口方法上加上自定义注解,以接口方法为接入点处理逻辑
- @Before()在切点前解析并记录请求信息
- @AfterReturning()在切点返回内容后解析并更新请求信息
具体实现
自定义注解Warehousing.java
import java.lang.annotation.*;
/**
* 入库注解
*/
@Retention(RetentionPolicy.RUNTIME) //作用于运行时
@Target({
ElementType.METHOD}) //作用于方法
@Documented //包含在JavaDoc 中
public @interface Warehousing {
/**
* 描述信息
*
* @return
*/
String description() default "";
}
入库切片类WarehousingAspect.java,实现上注解的具体动作。
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestAttributes;
import