Spring Boot校验

来源:互联网 发布:js校验文本框输入数字 编辑:程序博客网 时间:2024/06/18 15:28

开发web项目有时候我们需要对controller层传过来的参数进行一些基本的校验,比如非空,非null,整数值的范围,字符串的个数,日期,邮箱等等。最常见的就是我们直接写代码校验,这样以后比较繁琐,而且不够灵活。

Bean Validation 1.0(JSR-303)是一个校验规范,在Spring Boot项目由于自带了Hibernate validator 5(http://hibernate.org/validator/)实现,所以我们可以非常方便的使用这个特性 。

核心的pom依赖:

<dependency>    <groupId>org.hibernate</groupId>    <artifactId>hibernate-validator</artifactId>    <version>5.3.1.Final</version></dependency>

首先,需要我们声明一个Bean,注入校验器到Spring Boot的运行环境

@Configuration@EnableAutoConfigurationpublic class FactoryConfig {        final static Logger logger= LoggerFactory.getLogger(FactoryConfig.class);     @Bean    public MethodValidationPostProcessor methodValidationPostProcessor(){     return new MethodValidationPostProcessor();    }        }

校验常用的注解如下:

@AssertFalse 校验false@AssertTrue 校验true@DecimalMax(value=,inclusive=) 小于等于value,inclusive=true,是小于等于@DecimalMin(value=,inclusive=) 与上类似@Max(value=) 小于等于value@Min(value=) 大于等于value@NotNull  检查Null@Past  检查日期@Pattern(regex=,flag=)  正则@Size(min=, max=)  字符串,集合,map限制大小@Valid 对po实体类进行校验

下面看一个使用例子:

package hello;import javax.validation.constraints.Min;import javax.validation.constraints.NotNull;import javax.validation.constraints.Size;public class PersonForm {    //名字不能为空,而且长度必须在2和30之间    @NotNull(message = "名称不能为空")    @Size(min=2, max=30, message = "名字长度必须在2和30之间")    private String name;        //年龄不能为空,而且必须大于等于18岁    @NotNull    @Min(18)    private Integer age;    public String getName() {        return this.name;    }    public void setName(String name) {        this.name = name;    }    public Integer getAge() {        return age;    }    public void setAge(Integer age) {        this.age = age;    }    public String toString() {        return "Person(Name: " + this.name + ", Age: " + this.age + ")";    }}

接着看下如何在Controller层使用

//非实体类参数可以直接使用注解 @GetMapping("/check")@ResponseBodypublic String check(@Min(0,message = "kpId必须大于等于0") @RequestParam int kpId,@RequestParam int level) {        return "ok";}    //实体类注解校验使用@Valid    @PostMapping("/")    public String checkPersonInfo(@Valid PersonForm personForm, BindingResult bindingResult) {        if (bindingResult.hasErrors()) {            return "form";        }        return "redirect:/results";    }

注意上面的Spring提供的BindingResult是错误结果的一个封装,我们可以在web页面中通过这个对象拿到详细的错误信息,

<td th:if="${#fields.hasErrors('age')}" th:errors="*{age}">Age Error</td>

spring boot 1.4默认使用 hibernate validator 5.2.4 Final实现校验功能。hibernate validator 5.2.4 Final是JSR 349 Bean Validation 1.1的具体实现。 一 初步使用hibernate vilidator主要使用注解的方式对bean进行校验,初步的例子如下所示:

package com.learn.validate.domain;import javax.validation.constraints.Min;import org.hibernate.validator.constraints.NotBlank;public class Student {//在需要校验的字段上指定约束条件 @NotBlank private String name; @Min(3) private int age; @NotBlank private String classess;  public String getName() {  return name; } public void setName(String name) {  this.name = name; } public int getAge() {  return age; } public void setAge(int age) {  this.age = age; } public String getClassess() {  return classess; } public void setClassess(String classess) {  this.classess = classess; }}

然后在controller中可以这样调用,加上@Validated注解即可。

package com.learn.validate.controller;import org.springframework.validation.annotation.Validated;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RestController;import com.learn.validate.domain.Student;@RestControllerpublic class ValidateController { @RequestMapping(value="testStudent") public void testStudent(@Validated Student student) { }}

如果校验失败,默认会返回Spring boot 框架的出错信息。是一个json串,里面有详细的出错描述。

二 使用gruops 属性来实现区别不同的校验需求
在上面的例子中,如果Student bean想要用于两个不同的请求中,每个请求有不同的校验需求,例如一个请求只需要校验name字段,一个请求需要校验name和age两个字段,那该怎么做呢?
使用注解的groups属性可以很好的解决这个问题,如下所示:

package com.learn.validate.domain;import javax.validation.constraints.Min;import org.hibernate.validator.constraints.NotBlank;public class Student {    //使用groups属性来给分组命名,然后在需要的地方指定命令即可    @NotBlank(groups=NAME.class)    private String name;    @Min(value=3,groups=AGE.class)    private int age;    @NotBlank    private String classess;    public String getName() {        return name;    }    public void setName(String name) {        this.name = name;    }    public int getAge() {        return age;    }    public void setAge(int age) {        this.age = age;    }    public String getClassess() {        return classess;    }    public void setClassess(String classess) {        this.classess = classess;    }    public interface NAME{};    public interface AGE{};}

根据需要在@Validated属性中指定需要校验的分组名,可以指定1到多个。指定到的分组名会全部进行校验,不指定的不校验。

package com.learn.validate.controller;import org.springframework.validation.annotation.Validated;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RestController;import com.learn.validate.domain.Student;import com.learn.validate.domain.Student.AGE;import com.learn.validate.domain.Student.NAME;@RestControllerpublic class ValidateController {    @RequestMapping(value="testStudent")    public void testStudent(@Validated Student student) {    }    @RequestMapping(value="testStudent1")    public void testStudent1(@Validated(NAME.class) Student student) {    }    @RequestMapping(value="testStudent2")    public void testStudent2(@Validated({NAME.class,AGE.class})     Student student) {    }}

三 使用 @ScriptAssert 注解校验复杂的业务逻辑
如果需要校验的业务逻辑比较复杂,简单的@NotBlank,@Min注解已经无法满足需求了,这时可以使用@ScriptAssert来指定进行校验的方法,通过方法来进行复杂业务逻辑的校验,然后返回 true或false来表明是否校验成功。例如下面的例子:

package com.learn.validate.domain;import javax.validation.constraints.Min;import org.hibernate.validator.constraints.NotBlank;import org.hibernate.validator.constraints.ScriptAssert;import com.learn.validate.domain.Student.CHECK;//通过script 属性指定进行校验的方法,传递校验的参数,//依然可以通过groups属性指定分组名称@ScriptAssert(lang="javascript",script="com.learn.validate.domain.Student.checkParams(_this.name,_this.age,_this.classes)",groups=CHECK.class)public class Student { @NotBlank(groups=NAME.class) private String name; @Min(value=3,groups=AGE.class) private int age; @NotBlank private String classess; public String getName() {  return name; } public void setName(String name) {  this.name = name; } public int getAge() {  return age; } public void setAge(int age) {  this.age = age; } public String getClassess() {  return classess; } public void setClassess(String classess) {  this.classess = classess; } public interface NAME{}; public interface AGE{}; public interface CHECK{}; //注意进行校验的方法要写成静态方法,否则会出现  //TypeError: xxx is not a function 的错误 public static boolean checkParams(String name,int age,String classes) {  if(name!=null&&age>8&classes!=null)  {   return true;  }  else  {   return false;  } }}

在需要的地方,通过分组名称进行调用

package com.learn.validate.controller;import org.springframework.validation.annotation.Validated;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RestController;import com.learn.validate.domain.Student;import com.learn.validate.domain.Student.CHECK;@RestControllerpublic class ValidateController { @RequestMapping(value="testStudent3") public void testStudent3(@Validated(CHECK.class) Student student) { }}


作者:vasthua
链接:http://www.jianshu.com/p/a9b1e2f7a749
來源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。


原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 运费险退到天猫垫付账户了怎么办 淘宝卖家食品有问题该怎么办 美团外卖不要辣椒给放了怎么办 旺旺卖家拒收我的消息怎么办 淘宝清空购物车大奖到上限了怎么办 游戏无响应除了退出还能怎么办 淘宝给差评了卖家一直打电话怎么办 电脑说带宽问题无法观看视频怎么办 手机淘宝上的购买信息删除了怎么办 为什么支付宝有钱淘宝付不了怎么办 苹果平板电脑上的淘宝点不开怎么办 淘宝付了两次款只有一个订单怎么办 淘宝付款显示支付宝账号异常怎么办 手机老卡换新卡淘宝付不了款怎么办 淘宝买东西退款卖家拒绝退款怎么办 淘宝店铺收藏图片怎么点不了怎么办 手机淘宝显示用户被限制登录怎么办 淘宝设置登录密码原密码忘了怎么办 斑马智行淘宝号换没法登录了怎么办 淘宝卖家手机版显示宝贝不全怎么办 在电脑上登的淘宝账号退不了怎么办 淘宝买家退款不退货写假货怎么办 淘宝卖家已发布商品没货了怎么办 京东换货附近没有京东自提点怎么办 一直显示手机淘宝已停止运行怎么办 唯品会买了不可以退货的衣服怎么办 淘宝店卖东西邮费太贵怎么办 支付宝登录上去必须手机验证怎么办 支付宝里的钱被盗了怎么办 淘宝绑定的支付宝账号忘记了怎么办 支付宝绑定的微博账号忘记了怎么办 怎么知道自己的淘宝密码忘了怎么办 更换扣扣头像图片太大放不下怎么办 每次登入淘宝都要手机验证码怎么办 手机停机收不到唯品会验证码怎么办 魅蓝手机账户密码忘了怎么办 支付宝登录失败请稍后再试怎么办 万王之王3d限制注册了怎么办 绑定手机号无法登陆以前微信怎么办 手机号注册了淘宝如果不用了怎么办 淘宝网登陆要手机验证码怎么办