使⽤springvalidation完成数据后端校验-⾃定义校验的注解-判
断是否为空
引⼊依赖
我们使⽤maven构建springboot应⽤来进⾏demo演⽰。
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
我们只需要引⼊spring-boot-starter-web依赖即可,如果查看其⼦依赖,可以发现如下的依赖:
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
</dependency>
<dependency>
<groupId>com.</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
验证了我之前的描述,web模块使⽤了hibernate-validation,并且databind模块也提供了相应的数据绑定功能。
构建启动类
⽆需添加其他注解,⼀个典型的启动类
@SpringBootApplication
public class ValidateApp {
public static void main(String[] args) {
SpringApplication.run(ValidateApp.class, args);
}
}
创建需要被校验的实体类
public class Foo {
@NotBlank
private String name;
@Min(18)
private Integer age;
@Pattern(regexp = "^1(3|4|5|7|8)\\d{9}$",message = "⼿机号码格式错误")
@NotBlank(message = "⼿机号码不能为空")
private String phone;
@Email(message = "邮箱格式错误")
private String email;
//... getter setter
}
使⽤⼀些⽐较常⽤的校验注解,还是⽐较浅显易懂的,字段上的注解名称即可推断出校验内容,每⼀个注解都包含了message字段,⽤于校验失败时作为提⽰信息,特殊的校验注解,如Pattern(正则校验),还可以⾃⼰添加正则表达式。
在@Controller中校验数据
springmvc为我们提供了⾃动封装表单参数的功能,⼀个添加了参数校验的典型controller如下所⽰。
@Controller
public class FooController {
@RequestMapping("/foo")
public String foo(@Validated Foo foo <1>, BindingResult bindingResult <2>) {
if(bindingResult.hasErrors()){
for (FieldError fieldError : FieldErrors()) {
//...
}
return "fail";
}
return "success";
}
}
值得注意的地⽅:
<1> 参数Foo前需要加上@Validated注解,表明需要spring对其进⾏校验,⽽校验的信息会存放到其后的BindingResult中。注意,必须相邻,如果有多个参数需要校验,形式可以如下。foo(@Validated Foo foo, BindingResult fooBindingResult ,@Validated Bar bar, BindingResult barBindingResult);即⼀个校验类对应⼀个校验结果。
<2> 校验结果会被⾃动填充,在controller中可以根据业务逻辑来决定具体的操作,如跳转到错误页⾯。
⼀个最基本的校验就完成了,总结下框架已经提供了哪些校验:
JSR提供的校验注解:
@Null 被注释的元素必须为 null
@NotNull 被注释的元素必须不为 null
@AssertTrue 被注释的元素必须为 true
@AssertFalse 被注释的元素必须为 false
@Min(value) 被注释的元素必须是⼀个数字,其值必须⼤于等于指定的最⼩值
@Max(value) 被注释的元素必须是⼀个数字,其值必须⼩于等于指定的最⼤值
@DecimalMin(value) 被注释的元素必须是⼀个数字,其值必须⼤于等于指定的最⼩值
@DecimalMax(value) 被注释的元素必须是⼀个数字,其值必须⼩于等于指定的最⼤值
@Size(max=, min=) 被注释的元素的⼤⼩必须在指定的范围内
@Digits (integer, fraction) 被注释的元素必须是⼀个数字,其值必须在可接受的范围内
@Past 被注释的元素必须是⼀个过去的⽇期
@Future 被注释的元素必须是⼀个将来的⽇期
@Pattern(regex=,flag=) 被注释的元素必须符合指定的正则表达式
Hibernate Validator提供的校验注解:
@NotBlank(message =) 验证字符串⾮null,且长度必须⼤于0
@Email 被注释的元素必须是电⼦邮箱地址
@Length(min=,max=) 被注释的字符串的⼤⼩必须在指定的范围内
@NotEmpty 被注释的字符串的必须⾮空
@Range(min=,max=,message=) 被注释的元素必须在合适的范围内
校验实验
实验告诉我们,校验结果起了作⽤。并且,可以发现当发⽣多个错误,spring validation不会在第⼀个错误发⽣后⽴即停⽌,⽽是继续试错,告诉我们所有的错误。debug可以查看到更多丰富的错误信息,这些都是spring validation为我们提供的便捷特性,基本适⽤于⼤多数场景。
你可能不满⾜于简单的校验特性,下⾯进⾏⼀些补充。
分组校验
如果同⼀个类,在不同的使⽤场景下有不同的校验规则,那么可以使⽤分组校验。未成年⼈是不能喝酒的,⽽在其他场景下我们不做特殊的限制,这个需求如何体现同⼀个实体,不同的校验规则呢?
改写注解,添加分组:
Class Foo{
@Min(value = 18,groups = {Adult.class})
private Integer age;
public interface Adult{}
public interface Minor{}
}
这样表明,只有在Adult分组下,18岁的限制才会起作⽤。
Controller层改写:
@RequestMapping("/drink")
public String drink(@Validated({Foo.Adult.class}) Foo foo, BindingResult bindingResult) {
if(bindingResult.hasErrors()){
for (FieldError fieldError : FieldErrors()) {
//...
}
return "fail";
}
return "success";
}
@RequestMapping("/live")
public String live(@Validated Foo foo, BindingResult bindingResult) {
if(bindingResult.hasErrors()){
for (FieldError fieldError : FieldErrors()) {
//...
}
return "fail";
}
return "success";
}
drink⽅法限定需要进⾏Adult校验,⽽live⽅法则不做限制。
⾃定义校验
业务需求总是⽐框架提供的这些简单校验要复杂的多,我们可以⾃定义校验来满⾜我们的需求。⾃定义spring validation⾮常简单,主要分为两步。
1 ⾃定义校验注解
我们尝试添加⼀个“字符串不能包含空格”的限制。
@Target({METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER})
@Retention(RUNTIME)
@Documented
@Constraint(validatedBy = {CannotHaveBlankValidator.class})<1>
public @interface CannotHaveBlank {
//默认错误消息
String message() default "不能包含空格";
//分组
Class<?>[] groups() default {};
//负载
Class<? extends Payload>[] payload() default {};
//指定多个时使⽤
@Target({FIELD, METHOD, PARAMETER, ANNOTATION_TYPE})
@Retention(RUNTIME)
@Documented
@interface List {
CannotHaveBlank[] value();
}
}
我们不需要关注太多东西,使⽤spring validation的原则便是便捷我们的开发,例如payload,List ,groups,都可以忽略。
<1> ⾃定义注解中指定了这个注解真正的验证者类。
2 编写真正的校验者类
public class CannotHaveBlankValidator implements <1> ConstraintValidator<CannotHaveBlank, String> {
@Override
public void initialize(CannotHaveBlank constraintAnnotation) {
}
@Override
public boolean isValid(String value, ConstraintValidatorContext context <2>) {
//null时不进⾏校验
if (value != null && ains(" ")) {
<3>
//获取默认提⽰信息
String defaultConstraintMessageTemplate = DefaultConstraintMessageTemplate();
System.out.println("default message :" + defaultConstraintMessageTemplate);
//禁⽤默认提⽰信息
context.disableDefaultConstraintViolation();
//设置提⽰语
context.buildConstraintViolationWithTemplate("can not contains blank").addConstraintViolation();
return false;
}
springmvc的注解有哪些return true;
}
}
<1> 所有的验证者都需要实现ConstraintValidator接⼝,它的接⼝也很形象,包含⼀个初始化事件⽅法,和⼀个判断是否合法的⽅法。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论