HibernateValidation校验注解详解
在前后端传递数据的时候,往往后端需要校验传递数据的格式,⽐如⽤户名的格式,密码是否为空。我们可以在service层编写代码判断,但是当我们在多处需要校验传递来的数据的时候,就会出现⼤量重复的代码,⼀旦出错,就需要多处修改,⾮常⿇烦,⽽且这样我们的软件将会⾮常槽糕。这时,我们可以⽤Hibernate Validation的注解来进⾏校验,⼗分的⽅便简洁,Hibernate Validation是Spring⾃带的校验框架,在javax.validation包下可以到。下⾯我们来详细讲解⼀下Hibernate Validation的使⽤以及如何⾃定义注解来处理数据的校验。
⼀、使⽤Hibernate Validation校验注解
如何使⽤Hibernate Validation呢?我们来假设这样⼀个场景,我们需要创建⼀个⽤户,这时后端需要校验前台传来的数据。下⾯我们来看看这个实例怎么编写代码。
⾸先,⽤MockMvc来伪造请求进⾏测试,这⾥为了⽅便不编写前端代码了。
@Test
public void whenPostSuccess() throws Exception {
Date date=(Date) new java.util.Date();
System.out.Time());
String content="{\"username\":\"shinelon\",\"password\":null,\"birthday\":"+Time()+"}";
String result=mockMvc.perform(post("/user")
.content(content)
.contentType(MediaType.APPLICATION_JSON_UTF8))
.andExpect(status().isOk())
.andExpect(jsonPath("$.id").value(1))
.andReturn().getResponse().getContentAsString();
System.out.println(result);
}
上⾯的代码传递了⼀段json字符串到后台,与表单提交不同的是,表单提交的参数会⾃动封装到⽤户
实体类中,但是json字符串不会封装到实体类中,那怎么办呢?这时我们需要⽤到@RequestBody注解,在参数前加⼊这个参数,它会⾃动将json字符串按照映射到相应的字段中,并且当后端处理好业务后返回到前端的数据也会被处理成json字符串,这就给我们的开发带来了很好好处。
我们接着上⾯的场景,前端创建⽤户,后台来接收参数进⾏校验:
Controller层代码:
@PostMapping("/user")
public User create(@Valid @RequestBody User user,BindingResult errors) {
if(errors.hasErrors()) {
}
user.setId(1);
System.out.Id());
System.out.Username());
System.out.Password());
System.out.Birthday());
return user;
}
在上⾯的代码中,我们会看到@Valid注解和BindingResult errors,这就是我们的正题Hibernate Validation注解,当我们在参数user前⾯加上@Valid注解时,它就会在该类上⾃动校验相应的字段,当然User类中肯定需要对字段进⾏限制校验格式,下⾯我们会说明。我们再看看最后⼀个参数BindingResult,这个参数就是当你前台传递的数据校验不通过的时候处理⼀些错误信息的。如果没有BindingResult参数,当传递来的数据在@Valid注解中校验不通过的时候,它会直接返回错误的状态给⽤户,这也许和不友好,并且我们有些时候需要收集⼀些⽇志,⽐如记录你输⼊的⼀些错误信息,这时就需要⽤到BindingResult参数,它会在校验不通过的时候任然进⼊URL映射的⽅法中进⾏⼀些出来,这时我们可以打印具体的错误信息给⽤户以友好的展⽰,必须要说明的⼀点是,这个参数必须要在@Valid注解的参数的后⾯。
下⾯我们来看看在user类中的注解。
public class User {
private int id;
public String username;
@NotBlank
validation框架
public String password;
private Date birthday;
//省略get,set⽅法
我们以密码不为空来校验数据,在之前的代码中,我们password设置为null,肯定校验失败,不过我们加了BindingResult参数,它会进⼊⽅法体中打印错误⽇志,下⾯是打印的错误⽇志:
上⾯是Hibernate Validation内部⾃带的默认错误信息,有时候需要设置⾃定义的错误信息,这时我们就可以使⽤message参数来指定。
public class User {
private int id;
public String username;
//使⽤这个注解表⽰前台传回来的密码不能为空
@NotBlank(message="密码不能为空")        //这个注解是hibernate validator中提供的开源项⽬
public String password;
@Past(message="⽣⽇的⽇期必须是过去的时间")      //表⽰⽣⽇必须是过去的时间
private Date birthday;
下⾯是测试代码,Controller层的代码不变,还是上⾯的:
@Test
public void whenPostSuccess() throws Exception {
//⼀年以后的时间
Date date=(Date) new java.util.w().plusYears(1).
atZone(ZoneId.systemDefault()).toInstant().toEpochMilli());
System.out.Time());
String content="{\"username\":\"shinelon\",\"password\":null,\"birthday\":"+Time()+"}";
String result=mockMvc.perform(post("/user")
.content(content)
.contentType(MediaType.APPLICATION_JSON_UTF8))
.andExpect(status().isOk())
.andExpect(jsonPath("$.id").value(1))
.
andReturn().getResponse().getContentAsString();
System.out.println(result);
}
运⾏结果我们会发现打印了⾃定义的错误信息:
上⾯是Hibernate Validation⼏个简单的注解⽰例,下⾯这张图是Hibernate Validation的注解详解:
有些的读者可以⾃⾏试验上⾯的注解,这⾥就介绍到这⾥,下⾯我们来看看如何⾃定义注解。
⼆、⾃定义校验注解
有些场景Hibernate Validation不⾜以满⾜我们的需求,这时我们需要⾃定义注解来校验代码。
如何⾃定义注解呢?
⾸先,我们需要编写⼀个注解类:
MyValidator.java:
package cn.shinelon.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import javax.validation.Constraint;
import javax.validation.Payload;
@Target({ElementType.METHOD,ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy=MyConstraintValidator.class)
public @interface MyValidator {
//⾃定义注解必须实现这三个属性
String message();
Class<?>[] groups() default{};
Class<? extends Payload>[] payload() default{};
}
然后编写该注解要处理校验的类
MyConstraintValidator.java:
/**
*
*/
package cn.shinelon.annotation;
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import org.springframework.beans.factory.annotation.Autowired;
import cn.shinelon.service.impl.HelloServiceImpl;
/**
* @author Shinelon
*
*/
public class MyConstraintValidator implements ConstraintValidator<MyValidator, Object> {
@Autowired
public HelloServiceImpl helloServiceImpl;
@Override
public boolean isValid(Object arg0, ConstraintValidatorContext arg1) {
helloServiceImpl.hello(" "+arg0);
System.out.println(arg0);
//返回true或者false表⽰是否校验成功
return false;
}
//初始化
@Override
public void initialize(MyValidator arg0) {
System.out.println("my validator init");
}
}
该类实现了ConstraintValidator
public interface HelloService {
public void hello(String name);
}
实现类:
@Service
public class HelloServiceImpl implements HelloService {
/* (non-Javadoc)
* @see cn.shinelon.service.HelloService#hello()
*/
@Override
public void hello(String name) {
System.out.println("hello"+name);
}
}
定义好注解后,我们将注解加载username字段上进⾏测试,因为注解中isValid⽅法返回的false,就是说校验失败。
@MyValidator(message="这是⼀个⾃定义注解")
public String username;
然后我们继续运⾏上⾯的单元测试,可以看到我们的⾃定义注解⽣效。
⾄此,我们就给⼤家介绍完Hibernate Validation校验注解的使⽤以及⾃定义注解来进⾏校验。欢迎留⾔讨论。

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。