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格式数据 本人平时开发中使用的 ...
随机推荐
- 中国境内PE\VC\投资公司名单
中国境内PE\VC\投资公司名单 1.青云创投 2.高盛 3.红杉资本 4.鼎晖创投 5.枫丹国际 6.派杰投资银行 7.凯雷投资 8.长安私人资本 9.格林雷斯 10.汉能资本 11.启明创投 12 ...
- 笔记:在 Windows 10 WSL Ubuntu 18.04 安装 Odoo12 (2019-06-09)
笔记:在 Windows 10 WSL Ubuntu 18.04 安装 Odoo12 原因 为了和服务器一样的运行环境. 使用 Ubuntu 运行 Odoo 运行更快. 方便使用 Windows 10 ...
- css3 练习
css3 文本效果 css3中包含几个新的文本特征 在本章中您将了解一下文本属性 text-shadow box-shadow word-wrap word-break css3 的文本阴影 css3 ...
- Javascript 用来验证电话号码的正则
Javascript 用来验证电话号码的正则 在学习 Javascript 时学习到的. function telephoneCheck(str) { // return /^(1\s?)?(\d{3 ...
- Namenode文件系统命名空间映像文件及修改日志
- @hdu - 6598@ Harmonious Army
目录 @description@ @solution@ @accepted code@ @details@ @description@ n 个士兵,每个士兵可以选择加入 A 组或 B 组. 有 m 个 ...
- @雅礼集训01/10 - T1@ matrix
目录 @description@ @solution@ @accepted code@ @details@ @description@ 给定一个矩阵.求它的所有子矩阵中本质不同的行的个数之和. inp ...
- HZOJ visit
对于前30%的数据,可以考虑dp,f[i][j][k]表示时间为i,在i,j位置的方案数,枚举转移即可.要注意的是可以走到矩阵外. 对于另外30%数据,考虑推一下式子,设向右走y步,左z,上s,下x. ...
- python基础之逻辑题(3)
Python基础之逻辑题(3) 1.编写一个函数实现将IP地址转换成一个整数 2.求结果:---lambda 3.求a的结果 4.求下面nums的输出 5.求下面片段的输出 6.写出程序的结果:--- ...
- php三目运算计算三个数最大值最小值
文章地址:https://www.cnblogs.com/sandraryan/ $x = 10; $y = 45; $z = 3; //求出三个数字中最大值最小值 //先比较x y,如果x> ...