Spring功能介绍SpringMVC集成Java Bean Validation实现参数检验功

家资是何物,积帙列梁梠。这篇文章主要讲述Spring功能介绍SpringMVC集成Java Bean Validation实现参数检验功相关的知识,希望能为你提供帮助。
目前Bean Validation(JSR-349)的新特性可以到官网查看,之前用的参数校验有很多,主要集中于:

  • 跨参数验证(比如密码和确认密码的验证)
  • 支持在消息中使用EL表达式
  • 方法参数/返回值验证
  • CDI和依赖注入
  • 分组转换
【Spring功能介绍SpringMVC集成Java Bean Validation实现参数检验功】最开始接触java Bean Validation的时候是Hibernate validator 5,而且spring4才开始使用的,接下来我们从以下几个方法讲解Bean Validation,当然不一定是新特性:
  • 集成Java Bean Validation到SpringMVC
    • 分组验证、分组顺序及级联验证
    • 消息中使用EL表达式
    • 方法参数/返回值验证
    • 自定义验证规则
    • 类级别验证器
    • 脚本验证器
    • cross-parameter,跨参数验证
    • 混合类级别验证器和跨参数验证器
    • 组合多个验证注解
    • 本地化
因为大多数时候验证都配合web框架使用,而且很多朋友都咨询过如分组/跨参数验证,所以本文介绍下这些,且是和SpringMVC框架集成的例子,其他使用方式(比如集成到JPA中)可以参考其官方文档:
  • 规范:http://beanvalidation.org/1.1/spec/
  • hibernate validator文档:http://hibernate.org/validator/
添加hibernate validator依赖:
< dependency> < groupId> org.hibernate< /groupId> < artifactId> hibernate-validator< /artifactId> < version> latest.version< /version> < /dependency>

如果想在消息中使用EL表达式,请确保EL表达式版本是 2.2或以上,至少需要进行Tomcat7以上。
< dependency> < groupId> javax.el< /groupId> < artifactId> javax.el-api< /artifactId> < version> 2.2.4< /version> < scope> provided< /scope> < /dependency>

请确保您使用的Web容器有相应版本的el jar包。
web服务的展示
@Controller public class HelloWorldController { @RequestMapping("/validate/hello") public String validate(@Valided @ModelAttribute("user") UserModel user, Errors errors) { if(errors.hasErrors()) { return "validate/error"; } return "redirect:/success"; } }

硬编码错误消息
@NotNull(message = "用户名不能为空") @Length(min=5, max=20, message="用户名长度必须在5-20之间") @Pattern(regexp = "^[a-zA-Z_]\\\\w{4,19}$", message = "用户名必须以字母下划线开头,可由字母数字下划线组成") private String username;

如上所示,错误消息使用硬编码指定,这种方式是不推荐使用的,因为在如下场景是不适用的:
  1. 在国际化场景下,需要对不同的国家显示不同的错误消息;
  2. 需要更换错误消息时是比较麻烦的,需要找到相应的类进行更换,并重新编译发布。
交接于资源文件
public class User implements Serializable { @NotNull(message = "{user.id.null}") private Long id; @NotEmpty(message = "{user.name.null}") @Length(min = 5, max = 20, message = "{user.name.length.illegal}") @Pattern(regexp = "[a-zA-Z]{5,20}", message = "{user.name.illegal}") private String name; @NotNull(message = "{user.password.null}") private String password; }

错误信息内容
默认的错误消息键值如下图所示:
Spring功能介绍SpringMVC集成Java Bean Validation实现参数检验功

文章图片

  • 消息键默认为:验证约束注解的全限定类名.message。
  • 在我们之前的测试文件中,错误消息键值是使用默认的,如何自定义错误消息文件和错误消息键值呢?
自定义的错误消息文件和错误消息键值
  • 自定义错误消息文件里的错误消息键值将覆盖默认的错误消息文件中的错误消息键值。
  • 自定义错误消息文件是具有国际化功能的。
定义错误消息文件在类装载路径的根下创建ValidationMessages.properties文件,如在src目录下创建会自动复制到类装载路径的根下,并添加如下消息键值
自定义的错误消息文件和错误消息键值
自定义的错误消息文件里的错误消息键值将覆盖默认的错误消息文件中的错误消息键值。我们自定义的错误消息文件是具有国际化功能的。
  • org.springframework.validation.beanvalidation.LocalValidatorFactoryBean
  • org.hibernate.validator.HibernateValidator
此时错误消息键值的查找会先到classpath下ValidationMessages.properties中找,找不到再到默认的错误消息文件中找。
使用Spring的MessageSource Bean进行消息键值的查找
如果我们的环境是与spring集成,还是应该使用Spring提供的消息支持,具体配置如下
  • org.springframework.context.support.ReloadableResourceBundleMessageSource
    • basename:classpath:messages
    • fileEncodings:utf-8
    • cacheSeconds:120
在消息文件src/messages.properties中添加如下错误消息:
  • javax.validation.constraints.Pattern.message=用户名必须以字母或下划线开头,后边可以跟字母数字下划线,长度在5-20之间。
配置了messageSource Bean时,默认将为验证的对象自动生成如下错误消息键:
  • 验证错误注解简单类名.验证对象名.字段名
  • 验证错误注解简单类名.字段名
  • 验证错误注解简单类名.字段类型全限定类名
  • 验证错误注解简单类名
public String pattern(@Valided @ModelAttribute("model") PatternModel model, Errors errors)

将自动产生如下错误消息键:
  • Pattern.model.value=https://www.songbingjia.com/android/验证错误注解简单类名.验证对象名.字段名
  • Pattern.value=https://www.songbingjia.com/android/验证错误注解简单类名.字段名
  • Pattern.java.lang.String=验证错误注解简单类名.字段类型全限定类名
  • Pattern=验证错误注解简单类名
自定义错误消息键值
大部分场景下,以上两种方式无法满足我们的需求,因此我们需要自定义错误消息键值。
public class PatternModel { @Pattern(regexp = "^[a-zA-Z_][\\\\w]{4,19}$", message="{user.name.error}") private String value; }

在消息文件src/messages.properties中添加如下错误消息:
在消息文件src/messages.properties中添加如下错误消息:
@Length(min=5, max=20, message="{user.name.length.error}")

  • user.name.length.error=用户名长度必须在5-20之间
@Length(min=5, max=20, message="{user.name.length.error}")

错误消息占位符规则:{验证注解属性名}:
  • @Length有min和max属性,则在错误消息文件中可以通过{min}和{max}来获取;
  • @Max有value属性,则在错误消息文件中可以通过{value}来获取。
user.name.length.error=用户名长度必须在{min}-{max}之间

功能处理方法上多个验证参数的处理
当我们在一个功能处理方法上需要验证多个模型对象时,需要通过如下形式来获取验证结果:
@RequestMapping("/validate/multi") public String multi( @Valid @ModelAttribute("a") A a, BindingResult aErrors, @Valid @ModelAttribute("b") B b, BindingResult bErrors) { if(aErrors.hasErrors()) { //如果a模型对象验证失败 return "validate/error"; } if(bErrors.hasErrors()) { //如果a模型对象验证失败 return "validate/error"; } return "redirect:/success"; }


    推荐阅读