https://412887952-qq-com.iteye.com/blog/2299732
SpringMVC自带@Valid和@Validated两个注解可用来检查参数,但只能检查参数是bean的情况,对于参数是String或者Long类型的就不适用了,而且有时候这两个注解又突然失效了(没有仔细去调查过原因),对此,可以利用Spring的AOP和自定义注解,自己写一个参数校验的功能。
注解是一个特殊的类,它可以给对象、参数、方法添加额外的这个类信息。说白了就是添加了更多的信息,我们可以称注解信息为元信息。我们通过java的运行时公共方法可以获取这些信息。所以,注解只有当你定义了专门的注解处理程序的时候才有用,否则一无是处!
注解就是springAOP最好的使用例子。
当请求过来的时候,spring框架的拦截器会检查被请求的controller方法接口中的注解,根据注解类型,调用不同的AOP处理程序进行处理。
先定义一个注解:
/**
* 对 String 参数类型起非空校验作用
*/
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.PARAMETER, ElementType.METHOD})
@Inherited
public @interface NotNull {
String msg() default " 字段不能为null";
String msg1() default " 字段不能为blank";
}
再写一个切面,处理被注解的参数:
@Slf4j
@Aspect
@Component
public class NotNullValidAspect {
@Pointcut("execution(public * com.infoholdcity.parking.*.web..*(..)) && @annotation(com.infoholdcity.parking.common.annotation.NotNull)")
public void checkParam(){}
@Before("checkParam()")
public void beforePointcut(JoinPoint joinPoint) {
log.debug("参数验证中……");
//获取参数对象
Object[] args = joinPoint.getArgs();
//获取方法参数
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
Parameter[] parameters = signature.getMethod().getParameters();
for (int i = 0; i < parameters.length; i++) {
Parameter parameter = parameters[i];
//HttpServletRequest、HttpServletResponse、HttpSession时,都不做处理
if (parameter.getType().isAssignableFrom(HttpServletRequest.class) || parameter.getType().isAssignableFrom(HttpSession.class) ||
parameter.getType().isAssignableFrom(HttpServletResponse.class)) {
continue;
}
log.debug("参数类型:"+ parameter.getType().getName());
log.debug("参数名:"+ parameter.getName());
//该参数有该注解,且是String类型
NotNull notNull = parameter.getAnnotation(NotNull.class);
if (notNull != null && String.class.isAssignableFrom(parameter.getType())) {
if (args[i] == null) {
throw new ParamBlankException(parameter.getName() + notNull.msg());
}else if(StringUtils.isBlank(args[i].toString())){
throw new ParamBlankException(parameter.getName() + notNull.msg1());
}
//TODO
continue;
}
}
}
}
定义一个异常,用于捕获:
/**
* String参数为null或blank异常
*/
public class ParamBlankException extends RuntimeException{
public ParamBlankException() {
}
public ParamBlankException(String message) {
super(message);
}
}
全局异常处理器:
@ControllerAdvice
public class GlobalExceptionHandler {
/**
* 手机号,车牌号格式校验, 在自定义类参数前加 @Validated 即可生效
* @param e
* @return
*/
@ExceptionHandler(MethodArgumentNotValidException.class)
@ResponseBody
public RestResponse<Object> exceptionMethod1(MethodArgumentNotValidException e) {
RestResponse<Object> rr = new RestResponse<Object>();
BindingResult bindingResult = e.getBindingResult();
FieldError fieldError = bindingResult.getFieldError();
rr.setStatus("500");
rr.setMessage(fieldError.getField() + " " + fieldError.getDefaultMessage());
return rr;
}
/**
* 手机号,车牌号格式校验
* @param e
* @return
*/
@ExceptionHandler(ParamBlankException.class)
@ResponseBody
public RestResponse<Object> exceptionMethod2(ParamBlankException e) {
RestResponse<Object> rr = new RestResponse<Object>();
rr.setStatus("500");
rr.setMessage(e.getMessage());
return rr;
}
@ExceptionHandler(Exception.class)
@ResponseBody
public RestResponse<Object> exceptionMethod(Exception ex) {
RestResponse<Object> rr = new RestResponse<Object>();
rr.setStatus("500");
rr.setMessage("inner error of server." + ex.getMessage());
return rr;
}
}
接口里的注解使用:
@PostMapping("/login")
@ApiOperation(value = "用户登录/注册接口")
@ApiImplicitParams({
@ApiImplicitParam(name = "identifyCode", value = "用户输入的验证码", required = true),
@ApiImplicitParam(name = "telNumber", value = "用户手机号", required = true),
})
public RestResponse login(BaseMsg baseMsg, @NotNull String identifyCode) {
return this.wrap(baseMsgService.login(baseMsg, identifyCode));
}
https://blog.csdn.net/oKuZuoZhou/article/details/81024795
切入点的定义
http://www.jfinal.com/share/1306
注解传入数组
https://blog.csdn.net/piaoranyuji/article/details/89448632
request
https://www.iteye.com/blog/elim-1812584
不适用aop
https://blog.csdn.net/qq_15071263/article/details/83825132
参考