一个注解搞定全局参数校验
一、引入maven依赖
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.58</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>${commons-lang3.version}</version>
</dependency>
<dependency>
<groupId>commons-beanutils</groupId>
<artifactId>commons-beanutils</artifactId>
<version>1.9.3</version>
</dependency>
</dependencies>
二、自定义参数校验注解和异常
/**
* @Author: guandezhi
* @Date: 2019/12/17 16:55
*/
@Target({ElementType.METHOD, ElementType.FIELD, ElementType.CONSTRUCTOR, ElementType.PARAMETER, ElementType.TYPE_USE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface ParamValidate {
}
/**
* @Author: guandezhi
* @Date: 2019/12/17 17:13
*/
public class ParamValidateException extends RuntimeException {
public ParamValidateException(String errorMsg) {
super(errorMsg);
}
public ParamValidateException(String errorMsg, Throwable e) {
super(errorMsg, e);
}
}
三、定义参数校验切面
/**
* 参数校验切面
*
* @Author: guandezhi
* @Date: 2019/12/17 15:07
*/
@Slf4j
@Aspect
@Component
public class ParamValidateAspect {
@Resource
private LocalValidatorFactoryBean localValidatorFactoryBean;
/**
* 切入controller的方法参数加了自定义注解ParamValidate的方法
*/
@Pointcut("execution(public * com.gdz.demo.controller.*." +
"*(@com.gdz.demo.annotation.ParamValidate (*),..)) ||" +
" execution(public * com.gdz.demo.controller.*." +
"*(..,@com.gdz.demo.annotation.ParamValidate (*)))")
public void webLog() {
}
@Before("webLog()")
public void before(JoinPoint joinPoint) throws Exception {
doBefore(joinPoint);
}
/**
* 参数校验
*
* @param joinPoint
*/
private void doBefore(JoinPoint joinPoint) {
Object paramValue = getMethodParamValue(joinPoint);
if (paramValue != null) {
Set<ConstraintViolation<Object>> validErrors = this.localValidatorFactoryBean.validate(paramValue, new Class[]{Default.class});
Iterator iterator = validErrors.iterator();
StringBuilder errorMsg = new StringBuilder();
while (iterator.hasNext()) {
ConstraintViolation constraintViolation = (ConstraintViolation) iterator.next();
String error = constraintViolation.getPropertyPath() + ":" + constraintViolation.getMessage();
errorMsg.append(iterator.hasNext() ? error + "; " : error);
}
if (!validErrors.isEmpty()) {
throw new ParamValidateException(errorMsg.toString());
}
}
}
/**
* 获取加了自定义参数校验注解的参数值
*
* @param joinPoint
* @return
*/
private Object getMethodParamValue(JoinPoint joinPoint) {
Object[] args = joinPoint.getArgs();
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
/*获取@ParamValidate注解*/
Annotation[][] parameterAnnotations = signature.getMethod().getParameterAnnotations();
if (parameterAnnotations != null) {
for (Annotation[] parameterAnnotation : parameterAnnotations) {
int paramIndex = ArrayUtils.indexOf(parameterAnnotations, parameterAnnotation);
for (Annotation annotation : parameterAnnotation) {
if (annotation != null && annotation instanceof ParamValidate) {
return args[paramIndex];
}
}
}
}
return null;
}
}
四、全局捕获参数校验异常,并转换成自己想要的格式返回。
/**
* @Author: guandezhi
* @Date: 2019/12/17 16:53
*/
@Slf4j
@ControllerAdvice
public class GlobalExceptionHandler {
@ResponseBody
@ExceptionHandler(value = Exception.class)
public ResultVo<Object> handleException(Exception e) {
String errorMsg = "";
ResultVo<Object> resultVo = new ResultVo<>();
if (e instanceof NullPointerException) {
errorMsg = "参数空指针异常";
resultVo.setResultCode(HttpCode.FAIL.getMsgCode());
} else if (e instanceof ParamValidateException) {
errorMsg = "请求参数匹配错误," + e.getLocalizedMessage();
resultVo.setResultCode(HttpCode.ILLEGAL_INPUT.getMsgCode());
} else {
errorMsg = e.getMessage();
resultVo.setResultCode(HttpCode.ERROR.getMsgCode());
log.error("系统异常:", e);
}
resultVo.setResultMsg(errorMsg);
return resultVo;
}
}
五、测试一下:只需要在需要校验的参数旁边加上@ParamValidate 即可
/**
* @Author: guandezhi
* @Date: 2020/1/17 15:04
*/
@Slf4j
@RestController
public class IndexController {
@PostMapping("/index")
public String test(@RequestBody @ParamValidate User user) {
return "success";
}
}
其中User实体如下:
/**
* @Author: guandezhi
* @Date: 2020/1/17 15:05
*/
@Data
public class User {
@NotNull(message = "用户名不能为空")
private String userName;
@NotBlank
private String city;
@Min(value = 1, message = "年龄最小值不能小于1")
@Max(value = 99, message = "年龄最大值不能大于99")
private int age;
@Size(min = 1, max = 3, message = "别名不能少于1个,大于3个")
private List<String> alias;
}
测试结果如下:
{
"resultCode": 401,
"resultMsg": "请求参数匹配错误,alias:别名不能少于1个,大于3个; age:年龄最大值不能大于99; userName:用户名不能为空",
"data": null
}
代码地址:https://github.com/dezhiguan/paramvalidate.git
还没有评论,来说两句吧...