SpringMVC参数校验,包括JavaBean和基本类型的校验
该示例项目使用SpringBoot,添加web和aop依赖。
SpringMVC最常用的校验是对一个javaBean的校验,默认使用hibernate-validator校验框架。而网上对校验单个参数,譬如String,int之类的资料极少,这一篇就是讲这个的。
校验JavaBean
package com.example.bean;
import org.hibernate.validator.constraints.Length;
import org.hibernate.validator.constraints.NotEmpty;
/**
* Created by admin on 17/5/3.
*/
public class User {
private Long id;
@NotEmpty(message = "姓名不能为空")
private String name;
@NotEmpty(message = "密码不能为空")
@Length(min = 6, message = "密码长度不能小于6位")
private String password;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
定义了@NotEmpty等标签后,结合在Controller里使用@Valid即可完成参数的校验。
package com.example.controller;
import com.example.bean.User;
import org.hibernate.validator.constraints.Length;
import org.hibernate.validator.constraints.Range;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.validation.Valid;
/**
* Created by wuwf on 17/4/27.
*
*/
@RestController
public class FirstController {
@RequestMapping("/first")
public Object first(@Valid User user, BindingResult bindingResult) {
return "first controller";
}
@RequestMapping("/second")
public @Length Object second(@Length(min = 6, message = "密码长度不能小于6位") String password) {
return "second controller";
}
@RequestMapping("/third")
public @Length Object third(@Range(min = 6, max = 10, message = "数据需要大于6小于10") int num, @Length(min = 6, message = "密码长度不能小于6位") String password) {
return "third controller";
}
@RequestMapping("/four")
public @Length Object four(int page) {
return "four controller";
}
}
譬如first方法里,只需要加上@Valid标签即可完成校验。如果校验不通过,那么错误信息就会封装到BindingResult对象了,可以通过bindingResult的相关方法获取详细的错误信息并返回给用户。
访问:http://localhost:8080/first?name=1&password=1 debug可看到
如果不加BindingResult则会抛出异常。
此时即可完成表单类,或者用户注册之类的类似请求的参数校验了,可以选择获取bindingResult信息后直接return给用户。如果这样的需要校验的地方比较多,每个都单独处理比较麻烦,可以通过aop统一处理返回,后面会讲到。
校验的标签可参考:http://blog.csdn.net/catoop/article/details/51278675
相关文章:http://412887952-qq-com.iteye.com/blog/2312356
校验基本类型
在很多场景下,我们不需要校验一个javaBean,更多的是校验单个的int,String等。也就是controller里的second和third方法。像方法中写的那样,但是直接写上去,是不起作用的,校验框架并没有去校验,我们需要做的就是让它生效。
参考如下:https://diamondfsd.com/article/78fa12cd-b530-4a90-b438-13d5a0c4e26c
http://blog.csdn.net/catoop/article/details/51284638
直接上代码吧
package com.example.aop;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.hibernate.validator.internal.engine.path.PathImpl;
import org.springframework.core.LocalVariableTableParameterNameDiscoverer;
import org.springframework.core.ParameterNameDiscoverer;
import org.springframework.stereotype.Component;
import org.springframework.validation.BeanPropertyBindingResult;
import org.springframework.validation.ObjectError;
import javax.validation.ConstraintViolation;
import javax.validation.Validation;
import javax.validation.ValidatorFactory;
import javax.validation.executable.ExecutableValidator;
import java.lang.reflect.Method;
import java.util.List;
import java.util.Set;
/**
* Created by wuwf on 17/4/27.
* 参数校验切面
*/
@Aspect
@Component
public class ValidAspect {
private ObjectError error;
@Pointcut("execution(public * com.example.controller.*.*(..))")
public void valid() {
}
//环绕通知,环绕增强,相当于MethodInterceptor
@Around("valid()")
public Object arround(ProceedingJoinPoint pjp) {
System.out.println("方法环绕start.....");
try {
//取参数,如果没参数,那肯定不校验了
Object[] objects = pjp.getArgs();
if (objects.length == 0) {
return pjp.proceed();
}
/**************************校验封装好的javabean**********************/
//寻找带BindingResult参数的方法,然后判断是否有error,如果有则是校验不通过
for (Object object : objects) {
if (object instanceof BeanPropertyBindingResult) {
//有校验
BeanPropertyBindingResult result = (BeanPropertyBindingResult) object;
if (result.hasErrors()) {
List<ObjectError> list = result.getAllErrors();
for (ObjectError error : list) {
System.out.println(error.getCode() + "---" + error.getArguments() + "--" + error.getDefaultMessage());
//返回第一条校验失败信息。也可以拼接起来返回所有的
return error.getDefaultMessage();
}
}
}
}
/**************************校验普通参数*************************/
// 获得切入目标对象
Object target = pjp.getThis();
// 获得切入的方法
Method method = ((MethodSignature) pjp.getSignature()).getMethod();
// 执行校验,获得校验结果
Set<ConstraintViolation<Object>> validResult = validMethodParams(target, method, objects);
//如果有校验不通过的
if (!validResult.isEmpty()) {
String[] parameterNames = parameterNameDiscoverer.getParameterNames(method); // 获得方法的参数名称
for(ConstraintViolation<Object> constraintViolation : validResult) {
PathImpl pathImpl = (PathImpl) constraintViolation.getPropertyPath(); // 获得校验的参数路径信息
int paramIndex = pathImpl.getLeafNode().getParameterIndex(); // 获得校验的参数位置
String paramName = parameterNames[paramIndex]; // 获得校验的参数名称
System.out.println(paramName);
//校验信息
System.out.println(constraintViolation.getMessage());
}
//返回第一条
return validResult.iterator().next().getMessage();
}
return pjp.proceed();
} catch (Throwable e) {
e.printStackTrace();
return null;
}
}
private ParameterNameDiscoverer parameterNameDiscoverer = new LocalVariableTableParameterNameDiscoverer();
private final ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
private final ExecutableValidator validator = factory.getValidator().forExecutables();
private <T> Set<ConstraintViolation<T>> validMethodParams(T obj, Method method, Object[] params) {
return validator.validateParameters(obj, method, params);
}
}
注释写的比较清楚了,这是一个aop切面类,拦截请求,并获取方法里的所有参数。第65行到85行是对普通参数进行校验的。
加上这几行代码后在controller里写的那些才会生效,并且把校验信息保存到了ConstraintViolation的Set集合里,判断Set是否有值,即可知道是否有校验不通过的信息,然后就可以取到校验信息并返回给用户,然后结束方法。
而49到62行,主要是判断是否存在BindingResult参数,如果有,说明有校验javaBean的意图,如果BindingResult有值,说明存在校验不通过的信息,那么就可以做处理了。通过这样的aop切面,就可以不用在每个controller方法里去处理校验信息了。
原文地址:https://blog.csdn.net/tianyaleixiaowu/article/details/71173059
SpringMVC参数校验,包括JavaBean和基本类型的校验的更多相关文章
- SpringMVC由浅入深day02_1课程安排_2包装类型pojo参数绑定_3集合类型绑定
springmvc第二天 高级知识 复习: springmvc框架: DispatcherServlet前端控制器:接收request,进行response HandlerMapping处理器映射器: ...
- SpringMVC参数校验(针对`@RequestBody`返回`400`)
SpringMVC参数校验(针对@RequestBody返回400) 前言 习惯别人帮忙做事的结果是自己不会做事了.一直以来,spring帮我解决了程序运行中的各种问题,我只要关心我的业务逻辑,设计好 ...
- SpringMVC表单或Json中日期字符串与JavaBean的Date类型的转换
SpringMVC表单或Json中日期字符串与JavaBean的Date类型的转换 场景一:表单中的日期字符串和JavaBean的Date类型的转换 在使用SpringMVC的时候,经常会遇到表单中的 ...
- spring参数类型异常输出(二), SpringMvc参数类型转换错误输出(二)
spring参数类型异常输出(二), SpringMvc参数类型转换错误输出(二) >>>>>>>>>>>>>>&g ...
- spring参数类型异常输出,SpringMvc参数类型转换错误输出
spring参数类型异常输出, SpringMvc参数类型转换错误输出 >>>>>>>>>>>>>>>> ...
- HandlerMethodReturnValueHandler SpringMVC 参数解析 继承关系以及各解析器解析类型
I HandlerMethodReturnValueHandler (org.springframework.web.method.support) AbstractMessageConverterM ...
- HandlerMethodArgumentResolver SpringMVC 参数解析 继承关系以及各解析器解析类型
HandlerMethodArgumentResolver SpringMVC 参数解析 继承关系以及各解析器解析类型 I HandlerMethodArgumentResolver (org.spr ...
- SpringMVC初写(二)映射类型、限制和数据绑定
映射路径 a)映射路径的概述 所谓的映射路径,就是匹配请求路径和执行方法关系的路径 请求路径:http://localhost:8080/springmvc-demo-cofig/say.do 映射路 ...
- SpringMVC参数绑定学习总结【前后端数据参数传递】
目录 1. 绑定机制 2. 支持的数据类型 3. 参数请求中文乱码解决 4.自定义类型转换器 5.最后参数绑定学习小结 SpringMVC作为Controller层(等价servlet和struts中 ...
随机推荐
- Leetcode598.Range Addition II范围求和2
给定一个初始元素全部为 0,大小为 m*n 的矩阵 M 以及在 M 上的一系列更新操作. 操作用二维数组表示,其中的每个操作用一个含有两个正整数 a 和 b 的数组表示,含义是将所有符合 0 < ...
- MySQL 开启远程访问权限 | 宝塔系统
1.进入 MySQL 管理菜单 2.选择权限为所有人
- pip安装依赖与生成依赖
一.安装依赖 从requirements.txt安装依赖库 pip install -r requirements 当提示权限不够时,前面加上sudo#下面就是一个requirements.txt文件 ...
- 微信网页授权demo1
要授权首先要网页域名授权 然后就index.php代码如下 <?php require_once("./function.php"); $url = 'http://'.$_ ...
- font-family:黑体;导致css定义全部不起作用
css文件里font-family: "黑体";这句会导致后面的css定义全部不起作用了. 只要把font-family: "黑体"; 改成 font-fami ...
- 在vue项目中同时使用element-ui和mint-ui,的时候,.babelrc配置文件怎么写
我们安装vue组件库的时候,考虑到大小问题,需要根据需要仅引入部分组件 借助 babel-plugin-component,我们可以只引入需要的组件,以达到减小项目体积的目的. 但是在配置 .bab ...
- 笔记:投机和投资 F4NNIU
笔记:投机和投资 F4NNIU 投机是零和交易. 投资是正和博弈. 投机看是短期,只关心当下. 投资是看的长期,更关注未来. 投机容易分散注意力. 投资更关心交易外的注意力. 投机像是看运气,运气有好 ...
- Python接口自动化(一)接口基础
HTTP接口熟悉 常见接口介绍 接口工具的使用 fiddler如何mock数据 常见接口基础面试 如何理解接口?前后端解耦,前端和后端数据对接桥梁 接口测试和功能测试区别在哪?接口测试是功能测试的一种 ...
- 使用Fiddler抓取到的“姐夫酷”API接口
下午本来准备抓取些网页视频地址,做一个小的视频app,用来学习ijkplayer,无意中发现了一个app--姐夫酷,这是一个很简单的网页,它也有相应的一个比较简单的android app. 于是心血来 ...
- 【JZOJ4929】【NOIP2017提高组模拟12.18】B
题目描述 在两个n*m的网格上染色,每个网格中被染色的格子必须是一个四联通块(没有任何格子被染色也可以),四联通块是指所有染了色的格子可以通过网格的边联通,现在给出哪些格子在两个网格上都被染色了,保证 ...