AOP在项目中的实际应用V2.0
刚入行的时候,为了应付面试研究过AOP,写过AOP的实际应用的东西,但都是纸上谈兵,没有在项目中真正地使用过。不觉间入行有几年了,项目里边遇到过许多的场景都是使用过AOP的思想处理,在此分享下。
1.AOP处理返回值
1.问题描述及方案分析
项目采用前后端分离,后端返回JSON数据。同样的接口在PC和APP端都正常使用,但小程序出现一个这样的问题:所有的null值会被原样渲染到页面。按理说这是个前端问题,但是前端不知道为啥不处理,最后丢给了我。因为这样的接口,不在少数,所有的接口在拿到返回值时候都加个三元运算符处理每个属性的值是不现实的,而且要改的话需要动以前的接口,很危险。
综上,两个方案:
1.所以考虑AOP。(应该不会有人想到给数据字段加默认值吧,烧香拜佛,千万别让我遇到这样的同事)
2.Spring使用的Jackson将数据转的json,里边里有个注解(@JsonInclude(JsonInclude.Include.NON_NULL))可以使数据不参与序列化,非常方便。没有采用的原因是,AOP我可以灵活控制切入点,而给实体类加上注解,会影响所有用到该实体类的地方。
2.问题复现
举个栗子,现有接口如:
@RestController
@RequestMapping("/null")
public class SampleNullController {
/**
* 测试null值的处理
*
* @return r
*/
@RequestMapping(value = "/sample1", method = RequestMethod.GET)
public R<Sample> sample1() {
Sample Sample = new Sample();
Sample.setName("小明");
return R.data(Sample);
}
}
实体类栗子:
@Data
@ToString
public class Sample {
private Long id;
private String name;
private String address;
}
如果不进行处理,返回值肯定有null值,如图:
3.处理方案
AOP处理方法:
@Component
@Aspect
@Slf4j
public class ResponseAspect20220523 implements Ordered {
/**
* 定义切点
*/
@Pointcut("execution(* com.epo.xxx.controller.SampleNullController.sample1())")
public void pointCut() {
}
/**
* 环绕增强,用于处理返回值中null值转成空串(小程序插值表达式取值将null当成null字符串了)
*
* @param joinPoint joinPoint
* @return R
*/
@Around(value = "pointCut()")
@SuppressWarnings(value = "unchecked")
public R<Object> handleNull2String(ProceedingJoinPoint joinPoint) throws Throwable {
log.info("【ResponseAspect】【handleNull2String】线程:>>{}<<进入切点", Thread.currentThread().getName());
Object proceed = joinPoint.proceed();
log.info("【ResponseAspect】【handleNull2String】拦截到的数据是{}", JSONObject.toJSONString(proceed));
R<Object> r = (R<Object>) proceed;
ResponseNullUtils.handleNull(r.getData());
return r;
}
@Override
public int getOrder() {
return 1;
}
}
处理后效果,如图:
4.补充
Ordered接口可以不实现,不影响功能,我主要是为了控制此AOP切面的执行顺序。getOrder()方法返回值越小,执行顺序越靠前。