springmvc 参数校验/aop失效/@PathVariable 参数为空
添加依赖
<!-- 参数校验 -->
<dependency>
<groupId>org.hibernate.validator</groupId>
<artifactId>hibernate-validator</artifactId>
<version>6.0..Final</version>
</dependency>
一.基本类型参数(String)校验
1.注解要写在接口中,实现类会自动继承,如果实现类的某个重写方法没有加上了注解,接口中却没有定义,运行时会产生redefine异常
接口:
User getUserById(@NotNull(message = "uid不能为null") @Min(value = 1,message = "uid不合法") Integer id);
实现类:
@Override
public User getUserById(@NotNull(message = "uid不能为null") @Min(value = 1,message = "uid不合法") Integer id) {
return userMapper.getUserById(id);
}
Controller(restful风格最容易出的问题就是参数为空,只要不传就是404,不要尝试:xxx/getUserById/null,这种写法是400,给url设置null没有意义,解决方式很简单,给Controller增加一个映射路径即可,空参数导致的bind异常可以用在全局异常处理器捕获即可,当然你在web.xml中统一处理404也可以):
@RequestMapping(value = {"/getUserById/{uid}","/getUserById"})
public @ResponseBody Object getUserById(@PathVariable Integer uid) {
return userService.getUserById(uid);
}
2.提供校验器,自定义异常(可选),全局异常处理器
校验器:
public class ParamsValidator {
public static ExecutableValidator getValidator() {
ValidatorFactory validatorFactory = Validation.buildDefaultValidatorFactory();
return validatorFactory.getValidator().forExecutables();
}
}
自定义异常(可选):
public class ValidParamException extends RuntimeException {
private static final long serialVersionUID = 1L;
private Set<ConstraintViolation<Object>> validateResult;
public ValidParamException() {
super();
}
public ValidParamException(String message) {
super(message);
}
public ValidParamException(Set<ConstraintViolation<Object>> validateResult) {
this.validateResult = validateResult;
}
public Set<ConstraintViolation<Object>> getValidateResult() {
return validateResult;
}
public void setValidateResult(Set<ConstraintViolation<Object>> validateResult) {
this.validateResult = validateResult;
}
@Override
public String getMessage() {
return validateResult.iterator().next().getMessage();
}
public Map<Object, String> getErrorMap() {
Map<Object, String> map = new HashMap<Object, String>(6);
Iterator<ConstraintViolation<Object>> iterator = validateResult.iterator();
while (iterator.hasNext()) {
ConstraintViolation<Object> cons = iterator.next();
Path propertyPath = cons.getPropertyPath();
String message = cons.getMessage();
map.put(propertyPath, message);
}
return map;
}
}
全局异常处理器:
@ControllerAdvice
@EnableWebMvc
public class GlobalExceptionHandler {
// 单参数校验
@ExceptionHandler(ValidParamException.class)
public @ResponseBody Map<Object, String> validParamException(HttpServletRequest req, ValidParamException vpe) {
return vpe.getErrorMap();
} // 对象类型参数校验
@ExceptionHandler(MethodArgumentNotValidException.class)
public @ResponseBody Map<Object, String> methodArgumentNotValidException(MethodArgumentNotValidException ex) {
String parameterName = ex.getParameter().getParameterName();
Map<Object, String> map = new HashMap<Object, String>(6);
map.put(parameterName, ex.getLocalizedMessage());
return map;
} // pathvariable不传递参数时抛出的异常
@ExceptionHandler(ServletRequestBindingException.class)
public @ResponseBody Map<Object, String> servletRequestBindingException(ServletRequestBindingException ex) {
Map<Object, String> map = new HashMap<Object, String>(6);
map.put("error", ex.getLocalizedMessage());
return map;
}
}
3.使用aop进行拦截
关于aop"失效"的问题有几点说明:
1)如果拦截controller,那么aop的配置要写在springmvc的配置文件中,拦截其他层(如service)写在spring的配置文件中
2)被拦截的类必须也被spring管理否则无法拦截成功
3)开启注解扫描时,springmvc只扫描@Controller类型的注解,其他的如@Service,@Repository注解由spring进行扫描
aop:
@Component
@Aspect
public class UserAspect { private ExecutableValidator validator = ParamsValidator.getValidator(); @Pointcut("execution (* cn.tele.service.*.*(..))")
private void pt() {
} @Before("pt()")
public void checkParams(JoinPoint jp) { Object target = jp.getTarget();
Object[] params = jp.getArgs();
MethodSignature methodSignature = (MethodSignature) jp.getSignature(); String[] paramNames = methodSignature.getParameterNames();
Method method = methodSignature.getMethod(); Set<ConstraintViolation<Object>> validateResult = validator.validateParameters(target, method, params);
if (!validateResult.isEmpty()) {
throw new ValidParamException(validateResult);
}
} }
4.测试结果:
1)传入-1

2)不传

可以在aop中打印日志啥的
二.对象类型参数校验
1.在javaBean中添加注解,对一些特殊字段进行分组,如id,插入数据时,不需要校验可以为null,而查询,删除,更新等操作必须校验
@NotNull(message = "uid不能为null",groups = {Query.class,Update.class,Delete.class})
@Min(value = 1,message = "uid不合法")
private Integer uid;
@NotBlank(message = "姓名不能为空")
@Size(max = 20,message = "姓名最大长度为50个字符")
private String userName;
@NotBlank(message = "性别不能为空")
@Size(max = 20,message = "性别最大长度位20个字符")
private String sex;
@NotNull
@Max(value = 70,message = "最大年龄为70岁")
private Integer age;
@NotNull
private Integer departmentId;
@Value(value = "1")
private Integer state;
分组只是个标记,用接口定义就好
public interface Query {
}
2.在参数前添加@Valited注解,该注解支持分组,@Valid不支持,如果你选择的校验位置与上面定义的aop拦截的位置相同,那就会出问题了,
你的代码会走aop的逻辑然后去用你校验单个参数的校验器去进行校验,这样无法校验出问题,因此推荐放在controller层
@RequestMapping("/insertUser")
public @ResponseBody String insertUser(@Validated @RequestBody User user) {
Integer count = userService.insertUser(user);
return count ==1 ? "成功增加1条记录" : "增加" + user + "失败";
}
校验指定分组

3.抛出的异常会走上面贴出的全局异常处理器的代码
4.测试
1)正常情况,注意没有id

2)丢失userName

springmvc 参数校验/aop失效/@PathVariable 参数为空的更多相关文章
- 更加灵活的参数校验,Spring-boot自定义参数校验注解
上文我们讨论了如何使用@Min.@Max等注解进行参数校验,主要是针对基本数据类型和级联对象进行参数校验的演示,但是在实际中我们往往需要更为复杂的校验规则,比如注册用户的密码和确认密码进行校验,这个时 ...
- Spring Validation最佳实践及其实现原理,参数校验没那么简单!
之前也写过一篇关于Spring Validation使用的文章,不过自我感觉还是浮于表面,本次打算彻底搞懂Spring Validation.本文会详细介绍Spring Validation各种场景下 ...
- Spring Boot实现通用的接口参数校验
Spring Boot实现通用的接口参数校验 Harries Blog™ 2018-05-10 2418 阅读 http ACE Spring App API https AOP apache IDE ...
- SpringBoot实现通用的接口参数校验
本文介绍基于Spring Boot和JDK8编写一个AOP,结合自定义注解实现通用的接口参数校验. 缘由 目前参数校验常用的方法是在实体类上添加注解,但对于不同的方法,所应用的校验规则也是不一样的,例 ...
- 后端参数校验器v1.0(调用一个方法校验所有参数并得到校验结果,且包括错误原因)
一:介绍 在写后端时,面对多个参数,比如手机号码.密码等我们常常需要写验证逻辑,当需要验证的参数较多的时候我们会需要写很多的判断语句,这就造成了大量的代码冗余.因此我开发了一套参数验证器,只需要调用参 ...
- 接口参数校验之@Valid与BindingResult
接口方法往往需要对入参做一些校验,从而判断入参是否合格,而javax.validation包为我们提供了一些常用的参数校验注解,使用起来很方便. 下面这个示例是检验入参对象中的password是否为空 ...
- 徒手生撸一个验证框架,API 参数校验不再怕!
你们之中大概率早已练就了代码的拷贝.粘贴,无敌的码农神功,其实做久了业务功能开发,练就这两个无敌神功,那是迟早的事儿.今天先抛一个小问题,来打通你的任督二脉,就是很好奇的问一下:业务功能开发中,输入参 ...
- 接口参数校验(不使用hibernate-validator,规避大量if else)
引言 编写接口时,常用的参数校验使用hibernate-validator注解+@@Validated注解进行参数校验.当遇到一些特殊场景或需求,需要自己对参数进行手动校验时,会出现以下问题: 不可避 ...
- Flask开发技巧之参数校验
Flask开发技巧之参数校验 目录 Flask开发技巧之参数校验 1.请求参数分类 2.解决方案使用到的库 3.针对url查询参数与一般json格式 4.针对复杂json格式数据 本人平时开发中使用的 ...
随机推荐
- jq 添加内容
向页面动态添加内容,一般用于动态网页,需要即时请求数据,并更新在页面上,使用append()更多一些,empty() - 清空所有子元素,remove() - 清除自身所有子元素. append() ...
- @游记@ CSP2019
目录 @day -??@ @day -1@ @day 0@ @day 1@ @day 2@ @day ??@ @day ??+1@ @day -??@ 和 yhn 学长在校外偶遇. 聊了一些.他说现在 ...
- HZOJ 老司机的狂欢
比较神仙的一道题. 第一问还比较简单一点: t是否可行是单调的,考虑二分. 考虑对于两个人i,j合法的条件,设x(i)<x(j),那么$x(i)+\frac {a(i)*t^2}{2} < ...
- python基础---字符串常用方法汇总
s3 = '123's2 = ' 's1 = 'This Is \t Cash's='abcdefghijklmnopqrstuvwxyz's4 = "0000000this is stri ...
- 2015 Objective-C 三大新特性
http://www.cocoachina.com/ios/20150617/12148.html Overview 自 WWDC 2015 推出和开源 Swift 2.0 后,大家对 Swift 的 ...
- 权重衰减(weight decay)与学习率衰减(learning rate decay)
本文链接:https://blog.csdn.net/program_developer/article/details/80867468“微信公众号” 1. 权重衰减(weight decay)L2 ...
- oracle函数 UPPER(c1)
[功能]将字符串全部转为大写 [参数]c1,字符表达式 [返回]字符型 [示例] SQL> select upper('AaBbCcDd') upper from dual; UPPER --- ...
- 【转载】字符编码笔记:ASCII,Unicode和UTF-8
字符编码笔记:ASCII,Unicode和UTF-8 作者: 阮一峰 今天中午,我突然想搞清楚Unicode和UTF-8之间的关系,于是就开始在网上查资料. 结果,这个问题比我想象的复杂,从午饭后一直 ...
- PyODPS DataFrame 的代码在哪里跑
在使用 PyODPS DataFrame 编写数据应用时,尽管编写的是同一个脚本文件,但其中的代码会在不同位置执行,这可能导致一些无法预期的问题,本文介绍当出现相关问题时,如何确定代码在何处执行,以及 ...
- gensim的word2vec如何得出词向量(python)
首先需要具备gensim包,然后需要一个语料库用来训练,这里用到的是skip-gram或CBOW方法,具体细节可以去查查相关资料,这两种方法大致上就是把意思相近的词映射到词空间中相近的位置. 语料库t ...