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格式数据 本人平时开发中使用的 ...
随机推荐
- 最短路-Dijkstra算法整理
维基说的很全面:https://en.wikipedia.org/wiki/Dijkstra%27s_algorithm 理解: 先设置访问数组vis[]和距离数组dist[],开始时把源点(sour ...
- hdu1403 后缀数组
比较简单的应用. #include <stdio.h> #include <string.h> #define maxn 200002 int wa[maxn],wb[maxn ...
- Creating a Pulsing Circle Animation
原文 https://www.kirupa.com/animations/creating_pulsing_circle_animation.htm Outside of transitions th ...
- List<object> 转 List<T>
List<TAXIWAY_CENTER_LINE> kk = allObjs.Where(c => c.ToString() == "AMXM.TAXIWAY_CENTER ...
- 开发者说:Sentinel 流控功能在 SpringMVC/SpringBoot 上的实践
从用户的视角来感受一个开源项目的成长,是我们推出「开发者说」专栏的初衷,即在开发者进行开源项目选型时,提供更为立体的项目信息.专栏所有内容均来自作者原创/投稿,本文是「开发者说」的第6篇,作者 Jas ...
- ROS通过图形化界面控制和查看小乌龟参数
ROS图形化界面能够让我们快速开发ROS,也有利于我们观测数据. 下面介绍一下利用图形化界面控制小乌龟按照指令行进和查看小乌龟的行进参数. 首先我们需要做一些准备工作: 在Terminal中运行以下命 ...
- TOP10!全球顶级云计算公司战斗力排行榜
TOP10!全球顶级云计算公司战斗力排行榜 1亚马逊\VMware.微软 [PConline 资讯]现如今,不谈“云”,似乎会与这个时代格格不入.无论是企业还是个人,都会与“云”扯上关系.可以说,云计 ...
- BCompare 4 key SN 亲测可用
支持BCompare 4.2.3 32位,亲测可用 w4G-in5u3SH75RoB3VZIX8htiZgw4ELilwvPcHAIQWfwfXv5n0IHDp5hv 1BM3+H1XygMtiE0- ...
- nginx简单使用(windows)
本篇文章对术语不作讲解 下载nginx 首先,进入nginx官网http://nginx.org/en/download.html. 找到Stable version,此处的版本是稳定版本: 下载完成 ...
- jsp中文乱码六种情况---解决方案
转 jsp中文乱码六种情况---解决方案 2016年10月22日 21:32:55 阅读数:10672 来源:http://blog.csdn.net/lovesummerforever/articl ...