本系列将为大家介绍笔者在开发过程中使用aop的一些功能扩展,有从网上看到的,也有自己想的,如果有相似的代码,敬请海涵。
本章将介绍如果通过AOP来对请求的参数进行自动的非空检查并返回。相信部分同学的代码中会出现如下的例子:
if (parameters.get("openId") == null || StringUtils.isBlank(parameters.get("openId").toString())) {
result.setResult(Constant.FAIL);
result.setMessage("openId 为空,请检查参数");
logger.info("openId is null");
} else if (parameters.get("type") == null || StringUtils.isBlank(parameters.get("type").toString())) {
result.setResult(Constant.FAIL);
result.setMessage("type 为空,请检查参数");
logger.info("type is null");
} else if (signListByDays.equals(parameters.get("type").toString()) && (parameters.get("days") == null || StringUtils.isBlank(parameters.get("days").toString()))) {
result.setResult(Constant.FAIL);
result.setMessage("天数 为空,请检查参数");
logger.info("days is null");
}
又或者是
// 检查参数
if (parameters == null || StringUtils.isBlank(parameters.get("openId"))
|| StringUtils.isBlank(parameters.get("plateNumber"))
|| StringUtils.isBlank(parameters.get("frameNumber"))
|| StringUtils.isBlank(parameters.get("engineNumber"))
|| StringUtils.isBlank(parameters.get("registrationDate"))) {
result.setResult(Constant.FAIL);
result.setMessage("参数为空,请检查参数");
logger.info("parameters is null");
return result;
}
如果又增加了参数怎么办,继续在代码中添加判断,这样代码的侵入性太大,而且冗余度太多。为了解决这个问题。我们可以这么做。请看下面的一个controller 的方法
/**
* @Author Eric
* @Description 增加一个商品模板
* @Date 13:42 2019/1/29
* @Param [parameters]
* @return com.bxlsj.pojo.R
**/
@RequestMapping(method = RequestMethod.POST)
@RequestRequire(require="supplierId,sku,state,name,unit,purchasePrice,storage",parameter = ProductTempletDto.class)
public R addSupplier(@RequestBody ProductTempletDto productTempletDto){
try {
productTempletService.save(productTempletDto);
} catch (Exception e) {
logger.error("增加商品模板失败,{}", ExceptionUtil.getTrace(e));
return R.error(e.getMessage());
}
return R.ok();
}
添加一个注解@RequestRequire 让aop来统一的帮我们进行非空的判断。
第一步:添加一个注解@RequestRequire
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface RequestRequire {
/**
* 请求当前接口所需要的参数,多个以小写的逗号隔开
* @return
*/
public String require() default "";
/**
*传递参数的对象类型
*/
public Class<?> parameter() default Object.class;
}
第二步:再增加一个注解@SetPropertyName 这个注解的主要目的是为了非空检查返回属性的中文信息
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface SetPropertyName {
String value() default "";
}
第三步:编写切面类,代码不长就不仔细说了,最后注释掉的部分是可以持续扩展的,目前只检查了null和String类型空字符串的问题,如果还想对数字类型进行大于0等的判定,将注释的部分打开就可以了
/**
* @author Eric
* @version 1.0
* @ClassName: RequestRequireAspect
* @Description: TODO
* @company lsj
* @date 2019/1/30 9:49
**/
@Component
@Aspect
public class RequestRequireAspect {
private static final Logger logger = LoggerFactory.getLogger(RequestRequireAspect.class);
static final String split = ",";
@Pointcut("@annotation(com.bxlsj.base.annotation.RequestRequire)")
public void controllerInteceptor() {
}
/**
* controller层增强类,用于检测参数为空的情况
* @author Eric
* @date 9:52 2019/1/30
* @params pjp
* @throws
* @return java.lang.Object
**/
@Around("controllerInteceptor()")
public Object around(ProceedingJoinPoint pjp) throws Throwable {
// 获取注解的方法参数列表
Object[] args = pjp.getArgs();
// 获取被注解的方法
MethodInvocationProceedingJoinPoint mjp = (MethodInvocationProceedingJoinPoint) pjp;
MethodSignature signature = (MethodSignature) mjp.getSignature();
Method method = signature.getMethod();
// 获取方法上的注解
RequestRequire require = method.getAnnotation(RequestRequire.class);
// 以防万一,将中文的逗号替换成英文的逗号
String fieldNames=require.require().replace(",", ",");
// 从参数列表中获取参数对象
Object parameter=null;
for(Object pa:args){
//class相等表示是同一个对象
if (pa.getClass()==require.parameter() ) {
parameter=pa;
}
}
// 通过反射去和指定的属性值判断是否非空
// 获得参数的class
Class aClass = parameter.getClass();
// 遍历参数,找到是否为空
for(String name:fieldNames.split(split)){
Field declaredField = aClass.getDeclaredField(name);
String fieldName = declaredField.getName();
declaredField.setAccessible(true);
Object fieldObject = declaredField.get(parameter);
// 获取属性的中文名称
SetPropertyName spv = declaredField.getAnnotation(SetPropertyName.class);
if(spv != null && StringUtils.isNotBlank(spv.value())){
fieldName = spv.value();
}
if(fieldObject == null){
return R.error("参数" + fieldName + "不能为空");
}
// 如果type是类类型,则前面包含"class ",后面跟类名
if (declaredField.getGenericType().toString().equals("class java.lang.String")) {
if(StringUtils.isBlank((String)fieldObject)){
return R.error("参数" + fieldName + "不能为空");
}
}
// 如果是数字类型的
/* if (declaredField.getGenericType().toString().equals("class java.lang.Integer")
|| declaredField.getGenericType().toString().equals("class java.lang.Long")
|| declaredField.getGenericType().toString().equals("class java.lang.Double")
|| declaredField.getGenericType().toString().equals("class java.lang.Float")) {
if(fieldObject == null){
return R.error("参数" + fieldName + "不能为空");
}
} */
}
// 如果没有报错,放行
return pjp.proceed();
}
}
如果大家有什么疑问,欢迎留言交流
推荐:史上最全的java开发工具类 地址:https://github.com/EricLoveMia/JavaTools