在实际的java开发中,参数校验是个比较零碎繁琐的事情,但是却必不可少,本文通过aop来实现对参数的校验,可以节省大量的时间和提交代码的可读性与整洁性,方便更加集中的编写业务逻辑。
代码:
ParamCheckAop:
package com.yzs.plat.process.common.aop;
import com.yzs.plat.process.common.annotation.ValidateFiled;
import com.yzs.plat.process.common.annotation.ValidateGroup;
import com.yzs.plat.process.common.utils.oConvertUtils;
import com.yzs.plat.process.common.vo.Result;
import com.yzs.plat.process.modules.process.entity.SUserinfo;
import com.yzs.plat.process.modules.process.service.ISUserinfoService;
import lombok.extern.slf4j.Slf4j;
import org.activiti.engine.ProcessEngine;
import org.activiti.engine.history.HistoricTaskInstance;
import org.activiti.engine.task.Task;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.lang.annotation.Annotation;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
/**
* 参数检查AOP
*/
@Aspect
@Component
@Slf4j
public class ParamCheckAop {
@Autowired
private ISUserinfoService userinfoService;
@Autowired
private ProcessEngine processEngine;
@Around("@annotation(com.yzs.plat.process.common.annotation.ValidateGroup)")
public Object validateAround(ProceedingJoinPoint joinPoint) throws Throwable {
Result> result = null ;
ValidateGroup an;
Object[] args ;
Method method;
Object target;
String methodName;
boolean flag = false; // 是否发生异常
try{
methodName = joinPoint.getSignature().getName();
target = joinPoint.getTarget();
method = getMethodByClassAndName(target.getClass(), methodName); //得到拦截的方法
args = joinPoint.getArgs(); //方法的参数
an = (ValidateGroup)getAnnotationByMethod(method ,ValidateGroup.class );
result = validateFiled(an.fileds() , args);
}catch(Exception e){
flag = true;
}finally{
if(result == null && !flag){
log.info("参数校验---------验证通过-------------");
return joinPoint.proceed();
}
else{
log.info("参数校验---------验证未通过-----------");
return result;
}
}
}
/**
* 验证参数是否合法
*/
public Result> validateFiled(ValidateFiled[] valiedatefiles , Object[] args) throws SecurityException, IllegalArgumentException, NoSuchMethodException, IllegalAccessException, InvocationTargetException{
for (ValidateFiled validateFiled : valiedatefiles) {
Object arg;
if("".equals(validateFiled.filedName()) ){
arg = args[validateFiled.index()];
}else{
arg = getFieldByObjectAndFileName(args[validateFiled.index()] ,
validateFiled.filedName() );
}
if(validateFiled.notNull()){ //判断参数是否为空
if(arg == null )
return Result.error(validateFiled.msg());
}else{ //如果该参数能够为空,并且当参数为空时,就不用判断后面的了 ,直接返回true
if(arg == null )
return null;
}
if(validateFiled.maxLen() > 0){ //判断字符串最大长度
if(((String)arg).length() > validateFiled.maxLen())
return Result.error(validateFiled.msg());
}
if(validateFiled.minLen() > 0){ //判断字符串最小长度
if(((String)arg).length() < validateFiled.minLen())
return Result.error(validateFiled.msg());
}
if(validateFiled.maxVal() != -1){ //判断数值最大值
if( (Integer)arg > validateFiled.maxVal())
return Result.error(validateFiled.msg());
}
if(validateFiled.minVal() != -1){ //判断数值最小值
if((Integer)arg < validateFiled.minVal())
return Result.error(validateFiled.msg());
}
if(!"".equals(validateFiled.regStr())){ //判断正则
if(arg instanceof String){
if(!((String)arg).matches(validateFiled.regStr()))
return Result.error(validateFiled.msg());
}else{
return Result.error(validateFiled.msg());
}
}
if(validateFiled.isUid()) { // 验证uid是否存在
if(oConvertUtils.isEmpty(arg)){
return Result.error("uid不能为空!");
}
SUserinfo suid = userinfoService.query().eq("SUIID", arg).one();
if(suid == null) {
return Result.error(validateFiled.msg());
}
}
if(validateFiled.isTaskId()) { // 验证taskId是否存在
HistoricTaskInstance historicTaskInstance = processEngine.getHistoryService().createHistoricTaskInstanceQuery().taskId(arg.toString()).singleResult();
Task task = processEngine.getTaskService().createTaskQuery().taskId(arg.toString()).singleResult();
if(historicTaskInstance == null && task == null) {
return Result.error(validateFiled.msg());
}
}
}
return null;
}
/**
* 根据对象和属性名得到 属性
*/
public Object getFieldByObjectAndFileName(Object targetObj , String fileName) throws SecurityException, NoSuchMethodException, IllegalArgumentException, IllegalAccessException, InvocationTargetException, InvocationTargetException {
String tmp[] = fileName.split("\\.");
Object arg = targetObj ;
for (int i = 0; i < tmp.length; i++) {
Method methdo = arg.getClass().
getMethod(getGetterNameByFiledName(tmp[i]));
arg = methdo.invoke(arg);
}
return arg ;
}
/**
* 根据属性名 得到该属性的getter方法名
*/
public String getGetterNameByFiledName(String fieldName){
return "get" + fieldName.substring(0 ,1).toUpperCase() + fieldName.substring(1) ;
}
/**
* 根据目标方法和注解类型 得到该目标方法的指定注解
*/
public Annotation getAnnotationByMethod(Method method , Class annoClass){
Annotation all[] = method.getAnnotations();
for (Annotation annotation : all) {
if (annotation.annotationType() == annoClass) {
return annotation;
}
}
return null;
}
/**
* 根据类和方法名得到方法
*/
public Method getMethodByClassAndName(Class c , String methodName){
Method[] methods = c.getDeclaredMethods();
for (Method method : methods) {
if(method.getName().equals(methodName)){
return method ;
}
}
return null;
}
}
ValidateGroup:
package com.yzs.plat.process.common.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface ValidateGroup {
ValidateFiled[] fileds() ;
}
ValidateFiled:
package com.yzs.plat.process.common.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface ValidateFiled {
/**
* 提示信息
*/
String msg() default "";
/**
* 参数索引位置
*/
int index() default -1 ;
/**
* 如果参数是基本数据类型或String ,就不用指定该参数,如果参数是对象,要验证对象里面某个属性,就用该参数指定属性名
*/
String filedName() default "" ;
/**
* 正则验证
*/
String regStr() default "";
/**
* 是否能为空 , 为true表示不能为空 , false表示能够为空
*/
boolean notNull() default false;
/**
* 是否能为空 , 为true表示不能为空 , false表示能够为空
*/
int maxLen() default -1 ;
/**
* 最小长度 , 用户验证字符串
*/
int minLen() default -1 ;
/**
*最大值 ,用于验证数字类型数据
*/
int maxVal() default -1 ;
/**
*最小值 ,用于验证数值类型数据
*/
int minVal() default -1 ;
/**
* 是否是uid
* @return
*/
boolean isUid() default false;
/**
* 是否是taskId
* @return
*/
boolean isTaskId() default false;
}
具体使用:
/**
* 个人-启动一个流程
*/
@PostMapping("/startupProcess")
@ApiOperation("个人-启动一个流程")
@ApiImplicitParams({
@ApiImplicitParam(name = "delta", value = "增量", dataType = "BigDecimal"),
@ApiImplicitParam(name = "name", value = "姓名", dataType = "String"),
@ApiImplicitParam(name = "note", value = "注解", dataType = "String"),
@ApiImplicitParam(name = "processDefinitionId", value = "流程定义Id", dataType = "String"),
@ApiImplicitParam(name = "tenantId", value = "租户Id", dataType = "String"),
@ApiImplicitParam(name = "uid", value = "用户id", dataType = "String"),
@ApiImplicitParam(name = "attachment", value = "附件", dataType = "JSONObject")
})
@ValidateGroup(fileds = {
@ValidateFiled(index=0, notNull=true,msg = "delta不能为空!"),
@ValidateFiled(index=1, notNull=true,msg = "name不能为空!"),
@ValidateFiled(index=2, notNull=true,msg = "note不能为空!"),
@ValidateFiled(index=3, notNull=true,msg = "processDefinitionId不能为空!"),
@ValidateFiled(index=4, notNull=true,msg = "tenantId不能为空!"),
@ValidateFiled(index=5, notNull=true,msg = "uid不能为空!"),
@ValidateFiled(index=5, isUid=true,msg = "uid(用户id)不存在!"),
})
public Result> startProcess(
BigDecimal delta,
String name,
String note,
String processDefinitionId,
String tenantId,
String uid,
String attachment){
运行结果: