我的博客:兰陵笑笑生,欢迎浏览博客!
上一章 SpringBoot入门实践(五)-开源日志框架介绍当中,我们介绍了常用的开源日志框架。本期总结我在项目中是如何使用JSR实现请求参数的验证的。
前言
从Spring4开始,已经实现了对JSR-349(Bean Validation,是JSR303的升级 )的全面支持,Bean Validation API在javax。validation.CONSTRAINTS 中以JAVA注解的形式定义了一组可应用于域对象的约束,另外可以使用注解开发和应用自定义验证器,如类级验证器。
一、Spring中配置Bean Validation的支持
使用方式:
定义对象属性的验证约束:
public class Singer {
@NotNull(message = "名称不能为空")
@Size(min = 2, max = 5)
private String fistName;
private String lastName;
@NotNull(message = "性别不能为空")
private Genre genre;
....
}
配置一个类型为LocalValidatorFactoryBean 的bean
package com.miroservice.chapter2.config;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.ComponentScan;import org.springframework.context.annotation.Configuration;import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean;@Configuration@ComponentScan("com.miroservice")
public class AppConfig {
/** * 默认会在类路径下搜索Hibernate validator的库 * @return */
@Bean
LocalValidatorFactoryBean validator(){
return new LocalValidatorFactoryBean();
}
}
创建一个验证服务,一旦定义了LocalValidatorFactoryBean ,既可以在应用程序任何位置注入Validator的实例
import com.miroservice.chapter2.pojo.Singer;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Component;import javax.validation.ConstraintViolation;import javax.validation.Validator;import java.util.Set;
@Component
public class ValidateComponent {
/** * 注入一个javax.validation.Validator 实例 */
@Autowired
private Validator validator;
public Set<ConstraintViolation<Singer>> validatorSinger(Singer singer) {
return validator.validate(singer);
}
}
测试:
package com.miroservice.chapter2.web;
import com.miroservice.chapter2.config.AppConfig;
import com.miroservice.chapter2.pojo.Singer;
importorg.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.support.GenericApplicationContext;
import javax.validation.ConstraintViolation;
import java.util.Set;
public class JSR349Demo {
public static void main(String[] args) {
GenericApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig.class);
ValidateComponent validateController = ctx.getBean(ValidateComponent.class); Singer singer = new Singer();
singer.setFistName("j");
singer.setLastName("l");
singer.setGenre(null);
validatorSinger(singer, validateController);
}
private static void validatorSinger(Singer singer,
ValidateComponent validateController) {
final Set<ConstraintViolation<Singer>> constraintViolations = validateController.validatorSinger(singer);
listVidlations(constraintViolations);
}
private static void listVidlations(Set<ConstraintViolation<Singer>> set) {
for (ConstraintViolation<Singer> v : set) {
System.out.print("property:" v.getPropertyPath() ",value:"
v.getInvalidValue() ";error:" v.getMessage());
}
}
}
打印结果
二、常用的注解解释
- 1@Null 被注释的元素必须为 null
- 2@NotNull 被注释的元素必须不为 null
- 4 @AssertTrue 被注释的元素必须为 true
- 5 @AssertFalse 被注释的元素必须为 false
- 6 @Min(value) 被注释的元素必须是一个数字,其值必须大于等于指定的最小值7
- @Max(value) 被注释的元素必须是一个数字,其值必须小于等于指定的最大值
- 8 @DecimalMin(value) 被注释的元素必须是一个数字,其值必须大于等于指定的最小值
- 9 @DecimalMax(value) 被注释的元素必须是一个数字,其值必须小于等于指定的最大值
- 10 @Size(max=, min=) 被注释的元素的大小必须在指定的范围内
- 11 @Digits (integer, fraction) 被注释的元素必须是一个数字,其值必须在可接受的范围内
- 12 @Past 被注释的元素必须是一个过去的日期
- 13 @Future 被注释的元素必须是一个将来的日期14
- @Pattern(regex=,flag=) 被注释的元素必须符合指定的正则表达式15
- 16 Hibernate Validator 附加的 constraint
- 17 @NotBlank(message =) 验证字符串非null,且长度必须大于0
- 18 @Email 被注释的元素必须是电子邮箱地址
- 19 @Length(min=,max=) 被注释的字符串的大小必须在指定的范围内
- 20 @NotEmpty 被注释的字符串的必须非空21
- @Range(min=,max=,message=) 被注释的元素必须在合适的范围内
Hibernate Validator参考实现 http://hibernate.org/validator/
三、springBoot中web请求的POJO验证
使用方式:
定义对象属性的验证约束:
import javax.validation.constraints.NotNull;import javax.validation.constraints.Size;
public class Singer {
@NotNull(message = "名称不能为空")
@Size(min = 2, max = 5)
private String fistName;
private String lastName;
@NotNull(message = "性别不能为空")
private Genre genre;
...
}
定义Controller
import com.miroservice.chapter2.common.HttpResponse;
import com.miroservice.chapter2.pojo.Singer;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import javax.validation.Valid;
@RestController
public class SingerController {
/**
* 添加@Valid 注解
* @param singer
* @return
*/
@PostMapping("/singer")
private String validator(@Valid @RequestBody Singer singer) {
System.out.print(singer);
return "ok";
}
测试:请求 http://localhost:8081/singer
{
"fistName":null,
"genre":"FEMALE"
}
返回结果
{
"timestamp": "2020-01-11T15:16:22.851 0000",
"status": 400,
"error": "Bad Request",
"errors": [
{
"codes": [
"NotNull.singer.fistName",
"NotNull.fistName",
"NotNull.java.lang.String",
"NotNull"
],
"arguments": [
{
"codes": [
"singer.fistName",
"fistName"
],
"arguments": null,
"defaultMessage": "fistName",
"code": "fistName"
}
],
"defaultMessage": "名称不能为空",
"objectName": "singer",
"field": "fistName",
"rejectedValue": null,
"bindingFailure": false,
"code": "NotNull"
}
],
"message": "Validation failed for object='singer'. Error count: 1",
"path": "/singer"
}
自定义返回结果
入参的第二个地方,绑定BindingResult,当Bean中属性不满足是,可以获取到注解上的信息,并放回到
自定义的结果中。
@PostMapping("/singer")
private HttpResponse validator(@Valid @RequestBody Singer singer, BindingResult result)
{
if (result.hasErrors()) {
return HttpResponse.error(result.getFieldError().getDefaultMessage());
} return HttpResponse.ok();
}
返回结果
{
"code": 500,
"message": "名称不能为空",
"requestid": "eebb0bf86dc24aabb9051bf832542828"
}
四、创建自定义注解验证器
对于一些复杂的验证,比如说手机号码的验证,需要多个条件,或者一个验证的POJO中包含了另一个类,出现了这样的需求也是常有的,这就需要我们自定义创建验证器了,以手机的长度为例,我们自定义一个手机号的验证。
创建自定义注解
import javax.validation.Constraint;
import javax.validation.Payload;
import java.lang.annotation.*;
@Documented
//使用的验证器,自定义验证器
@Constraint(validatedBy = PhoneValidator.class)
//注解的使用级别是方法、属性上
@Target({ElementType.METHOD,ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface Phone {
//如果 验证经过PhoneValidator的验证返回false ,则默认返回的信息
String message() default "长度必须大于11";
/**
*
* @return
*/
Class<?>[] groups() default {};
Class<? extends Payload>[] payload()
default {}
;
}
创建验证器
package com.miroservice.chapter2.pojo;
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
/**
*
自定义实现对phone的验证逻辑
*/
public class PhoneValidator implements ConstraintValidator<Phone,String> {
/**
* value就是属性
*
*/
@Override
public boolean isValid(String value, ConstraintValidatorContext context) {
if(value==null||value.trim().length()<12){
return false;
}else {
return true;
}
}
}
对象添加手机号属性并添加注解
public class Singer {
@NotNull(message = "名称不能为空")
@Size(min = 2, max = 5)
private String fistName;
private String lastName;
@NotNull(message = "性别不能为空")
private Genre genre;
@Phone()
private String phone;
...
}
测试 http://localhost:8081/singer
请求参数
{
"phone" : 1,
"fistName": "zhang",
"genre":"MALE"
}
请求结果
{
"code": 500,
"message": "长度必须大于11",
"requestid": "38cc357c07144d098e7c5730cc8f4c08"
}
五、总结
以上就是本期的分享,你还可以关注本博客的#Spring Boot入门实践系列!#
本文由博客一文多发平台 OpenWrite 发布!