spring boot参数验证
必须要知道
- 简述 JSR303/JSR-349,hibernate validation,spring validation 之间的关系
JSR303 是一项标准,JSR-349 是其的升级版本,添加了一些新特性,他们规定一些校验规范即校验注解,如 @Null,@NotNull,@Pattern,他们位于 javax.validation.constraints 包下,只提供规范不提供实现;
hibernate validation 是对这个规范的实践,他提供了相应的实现,并增加了一些其他校验注解,如 @Email,@Length,@Range 等等,他们位于 org.hibernate.validator.constraints 包下;
spring validation,是对 hibernate validation 进行了二次封装,在 springmvc 模块中添加了自动校验,并将校验信息封装进了特定的类中;
spring mvc对spring validation的应用
get请求 参数验证
@RestController
@RequestMapping("/beavalidate")
public class BeanValidateController {
@GetMapping("/testget")
public ResultBody testGet(@Valid @NotBlank @RequestParam("name") String name){
return ResultBody.successBody("get方式验证成功!");
}
}
post请求 参数验证
@RestController
@RequestMapping("/beavalidate")
public class BeanValidateController {
@PostMapping("/testpost")
public ResultBody testPost(@Valid @RequestBody TagAddForm tagAddForm){
return ResultBody.successBody("验证成功!");
}
}
参数验证异常统一处理
如果我们没有对验证错误进行处理,调用接口的客户端无法知道到底是什么参数发生了错误,
还有就是如果前后端分离我们一般都是规定json格式传输数据,所以我们最好针对这个错误进行处理并返回格式化的内容。
定义错误相关的枚举
public interface IResult extends Serializable {
Integer getCode();
String getMessage();
}
public enum ResultEnum implements IResult {
/**
* 成功
*/
SUCCESS(10000, "成功"),
/**
* 请求参数异常
*/
ARGUMENT_EXCEPTION(10001, "请求信息异常");
private Integer code;
private String message;
ResultEnum(Integer code, String msg) {
this.code = code;
this.message = msg;
}
@Override
public Integer getCode() {
return code;
}
@Override
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
定义统一的json对象
@Data
public class ResultBody<T> {
/**
* 错误码
*/
private Integer code;
/**
* 提示信息
*/
private String message;
/**
* 具体数据
*/
private T body;
private ResultBody() {
}
/**
* 构造成功包体
*
* @return 成功的包体
*/
public static ResultBody successBody() {
return dowith(ResultEnum.SUCCESS.getCode(), ResultEnum.SUCCESS.getMessage(), new HashMap<>(1));
}
/**
* 构造成功的包体
*
* @param body 包体中body的内容
* @return 成功的包体
*/
public static ResultBody successBody(Object body) {
return dowith(ResultEnum.SUCCESS.getCode(), ResultEnum.SUCCESS.getMessage(), body);
}
/**
* 构造调用失败的包体
*
* @param result 错误码和提示信息内容
* @return 失败的包体
*/
public static ResultBody errorBody(IResult result) {
return dowith(result.getCode(), result.getMessage(), new HashMap<>(1));
}
/**
* 构造调用失败的包体
*
* @param result 错误码和提示信息内容
* @param body 包体内容
* @return 失败的包体
*/
public static ResultBody errorBody(IResult result, Object body) {
return dowith(result.getCode(), result.getMessage(), body);
}
/**
* 构造调用失败的包体
*
* @param result 错误码和提示信息内容
* @return 失败的包体
*/
public static ResultBody errorBody(IResult result, String message) {
return dowith(result.getCode(), message, null);
}
/**
* 构造调用失败的包体
*
* @param result 错误码和提示信息内容
* @param body 包体内容
* @return 失败的包体
*/
public static ResultBody errorBody(IResult result, Object body, String message) {
return dowith(result.getCode(), message, body);
}
}
定义异常处理器
@ControllerAdvice
public class ValidationExceptionHandler {
/**
* 处理post方式参数验证异常
* @param e
* @return
*/
@ExceptionHandler({MethodArgumentNotValidException.class})
@ResponseBody
public ResultBody notValidException(MethodArgumentNotValidException e) {
log.error("API参数校验异常:{}", e);
return this.wrapperBindingResult(e.getBindingResult());
}
/**
* 处理get方式参数验证异常
* @param e
* @return
*/
@ResponseBody
@ExceptionHandler({MissingServletRequestParameterException.class})
public ResultBody requestMissingParamsErrorHandler(MissingServletRequestParameterException e) {
log.error("MissingServletRequestParameterException:{}", e);
String errorMessage = e.getMessage();
ResultEnum resultEnum = ResultEnum.ARGUMENT_EXCEPTION;
return ResultBody.errorBody(resultEnum);
}
private ResultBody wrapperBindingResult(BindingResult bindingResult) {
ResultEnum resultEnum = ResultEnum.ARGUMENT_EXCEPTION;
StringBuilder errorMessage = new StringBuilder();
if ("prod".equals(this.profile)) {
errorMessage.append("请求信息异常");
} else {
Iterator var4 = bindingResult.getFieldErrors().iterator();
while(var4.hasNext()) {
FieldError fieldError = (FieldError)var4.next();
errorMessage.append(fieldError.getField()).append(fieldError.getDefaultMessage()).append(";");
}
}
resultEnum.setMessage(errorMessage.toString());
return ResultBody.errorBody(resultEnum);
}
}
效果
get方式参数验证
post方式参数验证:
非mvc环境下使用验证
在一些情况下我们并不是只是验证http请求参数的绑定,我们还需要java方法之间调用的参数验证。
不适用验证框架我们一般都是手动验证,但是手动验证是很费力的,下面就介绍一下在非mvc的情况下使用spring validation框架进行验证。
手动验证
定义bean添加验证注解
@Data
public class TagAddForm {
@NotEmpty(message = "标签名称不能为空")
private String name;
@Min(value = 1,message = "标签类型不能为空")
private int type;
}
编写手动验证逻辑
@Component
public class TagValidate {
/**
* 验证bean的参数
* <p>
* 手动验证
* </p>
*/
public void validateBean(){
TagAddForm tagAddForm=new TagAddForm();
ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
Validator validator = factory.getValidator();
Set<ConstraintViolation<TagAddForm>> violations = validator.validate(tagAddForm);
//为空代表验证通过
if (violations.size()==0){
return;
}
for(ConstraintViolation<TagAddForm> violation: violations) {
System.out.println((violation.getMessage()));
}
}
}
单元测试
@SpringBootTest
@RunWith(SpringRunner.class)
public class TestValidate {
@Autowired
private TagValidate tagValidate;
@Autowired
private UserValidate userValidate;
@Test
public void test(){
tagValidate.validateBean();
}
}
结果:
自动验证
业务类编写
在类上添加注解:@Validated 在方法上添加:@Valid注解
import org.springframework.stereotype.Component;
import org.springframework.validation.annotation.Validated;
import javax.validation.Valid;
@Validated
@Component
public class UserValidate {
public void add(@Valid TagAddForm tagAddForm){
System.out.println("添加标签");
}
}
测试
@SpringBootTest
@RunWith(SpringRunner.class)
public class TestValidate {
@Autowired
private UserValidate userValidate;
@Test
public void test2(){
//new一个 TagAddForm对象作为参数并没有为其赋值
TagAddForm tagAddForm=new TagAddForm();
userValidate.add(tagAddForm);
}
}
结果
spring boot参数验证的更多相关文章
- spring boot 参数传递(spring boot 参数传数 arg0 每一个参数 arg0#{arg0},arg1 #{arg1})
spring boot 参数传数 arg0 每一个参数 arg0#{arg0},arg1 #{arg1} @Select("select * from sys_user where nam ...
- Spring Boot 参数校验
1.背景介绍 开发过程中,后台的参数校验是必不可少的,所以经常会看到类似下面这样的代码 这样写并没有什么错,还挺工整的,只是看起来不是很优雅而已. 接下来,用Validation来改写这段 2.Spr ...
- Spring Boot系列(四) Spring Boot 之验证
这节没有高深的东西, 但有一些学习思路值得借鉴. JSR 303 (Bean Validation) Maven依赖 <dependency> <groupId>org.spr ...
- Spring Boot参数校验
1. 概述 作为接口服务提供方,非常有必要在项目中加入参数校验,比如字段非空,字段长度限制,邮箱格式验证等等,数据校验常用到概念:JSR303/JSR-349: JSR303是一项标准,只提供规范不提 ...
- Validated 注解完成 Spring Boot 参数校验
1. @Valid 和 @Validated @Valid 注解,是 Bean Validation 所定义,可以添加在普通方法.构造方法.方法参数.方法返回.成员变量上,表示它们需要进行约束校验. ...
- Spring Boot 微信-验证服务器有效性【转】
转:https://blog.csdn.net/jeikerxiao/article/details/68064145 概述 接入微信公众平台开发,开发者需要按照如下步骤完成: 在自己服务器上,开发验 ...
- 记一次spring boot参数初始化的问题
背景:接手一个项目,看到一个配置参数的引用: @Value("${webSocket.id}") 再看看配置application.yml: ... webSocket: id: ...
- Spring boot 参数相关注解
最近使用swagger的在线文档调试接口时发现老是报参数问题,最后发现是方法中参数上的注解有问题,今天把填的坑做一下总结. 1. RequestParam 该注解有两个属性: name/value:表 ...
- spring Boot登录验证之验证码 邮箱
一 验证码 登录login.jsp <%@ page contentType="text/html;charset=UTF-8" language="java&qu ...
随机推荐
- codeforces 749D Leaving Auction(二分)
题目链接:http://codeforces.com/problemset/problem/749/D 题意:就是类似竞拍,然后报价肯定要比上一个高,然后查询输入k个数表示那些人的竞拍无效, 输出最后 ...
- POJ 2230 Watchcow 欧拉图
Watchcow Time Limit: 3000MS Memory Limit: 65536K Total Submissions: 8800 Accepted: 3832 Specia ...
- DELPHI GDI + TGPFont UnitPixel 问题解决
查不少资料,在 GPfont := TGPFont.Create(fontFamily, Font.Size , FontStyleRegular,UnitPixel ); 时,显示的字体,并不是按D ...
- Linux基础_网站权限规划
Linux系统默认的权限: 对于文件来说, 默认的权限: rw-r--r-- 644 对于目录来说:rwxr-xr-x 755 网站比较安全的权限: 网址程序存放在/app/blog 目录下面. 1 ...
- 新建项目中的fail和missing之类的问题
首先必须要明白:每一个项目需要都要安装在本地仓库中去--->pom,war,jar无一例外 如果不安装会出现下面的错误: 解决的办法就是: 先clean后install项目,把他们安装到本地仓库 ...
- elk安装和使用
elk安装和使用 使用的版本都是5.2.0 elasticsearch-5.2.0安装 在官网 下载 elasticsearch tar包 解压安装 tar zxf elasticsearch-5.2 ...
- HBase的表结构
HBase以表的形式存储数据.表有行和列组成.列划分为若干个列族/列簇(column family). 如上图所示,key1,key2,key3是三条记录的唯一的row key值,column-fa ...
- soap get/post请求
pom.xml依赖: <dependency> <groupId>org.apache.httpcomponents</groupId> <artifactI ...
- MySQL实现Oracle rank()排序
一.Oracle写法介绍 MySQL5.7版本没有提供类似Oracle的分析函数,比如开窗函数over(...),oracle开窗函数over(...)使用的话一般是和order.partition ...
- LOVE POWER html与javaScript
1.纯HTML与javaScript编写的表白动态图 1.对于世界而言,你是一个人:但是对于某个人,你是他的整个世界. 2.不要为那些不愿在你身上花费时间的人而浪费你的时间. 3.我爱你,不是因为你是 ...