必须要知道

  • 简述 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参数验证的更多相关文章

  1. spring boot 参数传递(spring boot 参数传数 arg0 每一个参数 arg0#{arg0},arg1 #{arg1})

    spring boot 参数传数 arg0 每一个参数 arg0#{arg0},arg1  #{arg1} @Select("select * from sys_user where nam ...

  2. Spring Boot 参数校验

    1.背景介绍 开发过程中,后台的参数校验是必不可少的,所以经常会看到类似下面这样的代码 这样写并没有什么错,还挺工整的,只是看起来不是很优雅而已. 接下来,用Validation来改写这段 2.Spr ...

  3. Spring Boot系列(四) Spring Boot 之验证

    这节没有高深的东西, 但有一些学习思路值得借鉴. JSR 303 (Bean Validation) Maven依赖 <dependency> <groupId>org.spr ...

  4. Spring Boot参数校验

    1. 概述 作为接口服务提供方,非常有必要在项目中加入参数校验,比如字段非空,字段长度限制,邮箱格式验证等等,数据校验常用到概念:JSR303/JSR-349: JSR303是一项标准,只提供规范不提 ...

  5. Validated 注解完成 Spring Boot 参数校验

    1.  @Valid 和 @Validated @Valid 注解,是 Bean Validation 所定义,可以添加在普通方法.构造方法.方法参数.方法返回.成员变量上,表示它们需要进行约束校验. ...

  6. Spring Boot 微信-验证服务器有效性【转】

    转:https://blog.csdn.net/jeikerxiao/article/details/68064145 概述 接入微信公众平台开发,开发者需要按照如下步骤完成: 在自己服务器上,开发验 ...

  7. 记一次spring boot参数初始化的问题

    背景:接手一个项目,看到一个配置参数的引用: @Value("${webSocket.id}") 再看看配置application.yml: ... webSocket: id: ...

  8. Spring boot 参数相关注解

    最近使用swagger的在线文档调试接口时发现老是报参数问题,最后发现是方法中参数上的注解有问题,今天把填的坑做一下总结. 1. RequestParam 该注解有两个属性: name/value:表 ...

  9. spring Boot登录验证之验证码 邮箱

    一 验证码 登录login.jsp <%@ page contentType="text/html;charset=UTF-8" language="java&qu ...

随机推荐

  1. 深度递归必须知道的尾调用(Lambda)

    引导语 本文从一个递归栈溢出说起,像大家介绍一下如何使用尾调用解决这个问题,以及尾调用的原理,最后还提供一个解决方案的工具类,大家可以在工作中放心用起来. 递归-发现栈溢出 现在我们有个需求,需要计算 ...

  2. 关于ASP.NET中WEBAPI中POST请求中FromBody修饰的string类型的参数服务器端获取不到值FromBody空值的简单解决方法

    其实解决办法很简单,就是POST请求的时候,来自实体的参数,content-type:application/x-www-form-urlencoded情况下,是默认按照键值对来解析的,比如param ...

  3. shell中日期循环的方式

    第一种 # 这里的例子以周为循环 !/bin/bash begin_date="20160907" end_date="20170226" while [ &q ...

  4. 009 Python基本图形绘制

    目录 一.概论 二.方法论 三.实践能力 一.概论 深入理解Python语言 实例2: Python蟒蛇绘制 模块1: turtle库的使用 turtle程序语法元素分析 二.方法论 Python语言 ...

  5. lambda表达式的一些学习

    关于lambda表达式的一些学习,例举出来. 1.学生实体类 public class Student { private String name; private int age; public S ...

  6. 使用ECMAScript 6 模块封装代码

    JavaScript 用"共享一切"的方法加载代码,这是该语言中最容易出错且最容易让人感到困惑的地方.其他语言使用诸如包这样的概念来定义代码作用域,但在 ECMAScript 6 ...

  7. TestNG(十二) 参数化测试

    <?xml version="1.0" encoding="utf-8" ?> <suite name = "parameter&q ...

  8. Aspose.Cell导出带chart图表

    最终实现的效果就是这样,代码比较多,我放在了CSDN上了,是无需模板的,别听网上瞎吹,说什么要模板,地址是:https://download.csdn.net/download/chanelwtt/1 ...

  9. [Advanced Python] 10 - Transfer parameters

    动态库调用 一.Python调用 .so From: Python调用Linux下的动态库(.so) (1) 生成.so:.c to .so lolo@-id:workme$ gcc -Wall -g ...

  10. 转载:elastic5.x部署常见问题总结

    原博文名称:ElasticSearch 5.0.0 安装部署常见错误或问题 原博文地址为:http://www.dajiangtai.com/community/18136.do?origin=csd ...