【Spring技术原理】SpringMVC集成Java Bean Validation实现参数检验功能

简介: 【Spring技术原理】SpringMVC集成Java Bean Validation实现参数检验功能

目前Bean Validation(JSR-349)的新特性可以到官网查看,之前用的参数校验有很多,主要集中于:


  • 跨参数验证(比如密码和确认密码的验证)
  • 支持在消息中使用EL表达式
  • 方法参数/返回值验证
  • CDI和依赖注入
  • 分组转换



最开始接触Java Bean Validation的时候是Hibernate validator 5,而且spring4才开始使用的,接下来我们从以下几个方法讲解Bean Validation,当然不一定是新特性:


  • 集成Java Bean Validation到SpringMVC
  • 分组验证、分组顺序及级联验证
  • 消息中使用EL表达式
  • 方法参数/返回值验证
  • 自定义验证规则
  • 类级别验证器
  • 脚本验证器
  • cross-parameter,跨参数验证
  • 混合类级别验证器和跨参数验证器
  • 组合多个验证注解
  • 本地化


因为大多数时候验证都配合web框架使用,而且很多朋友都咨询过如分组/跨参数验证,所以本文介绍下这些,且是和SpringMVC框架集成的例子,其他使用方式(比如集成到JPA中)可以参考其官方文档:





添加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. 需要更换错误消息时是比较麻烦的,需要找到相应的类进行更换,并重新编译发布。




交接于资源文件


默认的错误消息文件是/org/hibernate/validator/ValidationMessages.properties,如下图所示:

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;
}
复制代码



错误信息内容


默认的错误消息键值如下图所示:


  • 消息键默认为:验证约束注解的全限定类名.message。
  • 在我们之前的测试文件中,错误消息键值是使用默认的,如何自定义错误消息文件和错误消息键值呢?



自定义的错误消息文件和错误消息键值


  • 自定义错误消息文件里的错误消息键值将覆盖默认的错误消息文件中的错误消息键值。
  • 自定义错误消息文件是具有国际化功能的。



定义错误消息文件


在类装载路径的根下创建ValidationMessages.properties文件,如在src目录下创建会自动复制到类装载路径的根下,并添加如下消息键值


自定义的错误消息文件和错误消息键值 自定义的错误消息文件里的错误消息键值将覆盖默认的错误消息文件中的错误消息键值。我们自定义的错误消息文件是具有国际化功能的。


javax.validation.constraints.Pattern.message=用户名必须以字母或下划线开头,后边可以跟字母数字下划线,长度在5-20之间。


  • 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=验证错误注解简单类名.验证对象名.字段名
  • Pattern.value=验证错误注解简单类名.字段名
  • 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中添加如下错误消息:

user.name.error=用户名格式不合法


在消息文件src/messages.properties中添加如下错误消息:

@Length(min=5, max=20, message="{user.name.length.error}")  
复制代码


  • user.name.length.error=用户名长度必须在5-20之间

错误消息中的5-20应该是从@Length验证约束注解中获取的,而不是在错误消息中硬编码,因此我们需要占位符的支持:

@Length(min=5, max=20, message="{user.name.length.error}")
复制代码


错误消息可以这样写:用户名长度必须在{min}-{max}之间。


错误消息占位符规则:{验证注解属性名}:


  • @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";  
}
复制代码


每一个模型对象后边都需要跟一个Errors或BindingResult对象来保存验证结果,其方法体内部可以使用这两个验证结果对象来选择出错时跳转的页面。




相关文章
|
4月前
|
Java
Java开发实现图片URL地址检验,如何编码?
【10月更文挑战第14天】Java开发实现图片URL地址检验,如何编码?
127 4
|
17天前
|
监控 Java Nacos
使用Spring Boot集成Nacos
通过上述步骤,Spring Boot应用可以成功集成Nacos,利用Nacos的服务发现和配置管理功能来提升微服务架构的灵活性和可维护性。通过这种集成,开发者可以更高效地管理和部署微服务。
111 17
|
10天前
|
存储 缓存 Java
Java中的分布式缓存与Memcached集成实战
通过在Java项目中集成Memcached,可以显著提升系统的性能和响应速度。合理的缓存策略、分布式架构设计和异常处理机制是实现高效缓存的关键。希望本文提供的实战示例和优化建议能够帮助开发者更好地应用Memcached,实现高性能的分布式缓存解决方案。
32 9
|
2月前
|
人工智能 自然语言处理 Java
FastExcel:开源的 JAVA 解析 Excel 工具,集成 AI 通过自然语言处理 Excel 文件,完全兼容 EasyExcel
FastExcel 是一款基于 Java 的高性能 Excel 处理工具,专注于优化大规模数据处理,提供简洁易用的 API 和流式操作能力,支持从 EasyExcel 无缝迁移。
135 9
FastExcel:开源的 JAVA 解析 Excel 工具,集成 AI 通过自然语言处理 Excel 文件,完全兼容 EasyExcel
|
19天前
|
缓存 安全 Java
Spring Boot 3 集成 Spring Security + JWT
本文详细介绍了如何使用Spring Boot 3和Spring Security集成JWT,实现前后端分离的安全认证概述了从入门到引入数据库,再到使用JWT的完整流程。列举了项目中用到的关键依赖,如MyBatis-Plus、Hutool等。简要提及了系统配置表、部门表、字典表等表结构。使用Hutool-jwt工具类进行JWT校验。配置忽略路径、禁用CSRF、添加JWT校验过滤器等。实现登录接口,返回token等信息。
202 12
|
18天前
|
人工智能 安全 Dubbo
Spring AI 智能体通过 MCP 集成本地文件数据
MCP 作为一款开放协议,直接规范了应用程序如何向 LLM 提供上下文。MCP 就像是面向 AI 应用程序的 USB-C 端口,正如 USB-C 提供了一种将设备连接到各种外围设备和配件的标准化方式一样,MCP 提供了一个将 AI 模型连接到不同数据源和工具的标准化方法。
|
28天前
|
Java API Apache
java集成stable diffusion
通过REST API和JNI两种方法,我们可以在Java应用程序中集成Stable Diffusion模型。REST API方法更加简单和易于维护,而JNI方法则提供更高的性能。根据具体应用场景和需求,选择合适的集成方法,可以充分利用Stable Diffusion的强大功能,实现高效的图像生成和处理。
56 15
|
25天前
|
存储 安全 Java
Spring Boot 3 集成Spring AOP实现系统日志记录
本文介绍了如何在Spring Boot 3中集成Spring AOP实现系统日志记录功能。通过定义`SysLog`注解和配置相应的AOP切面,可以在方法执行前后自动记录日志信息,包括操作的开始时间、结束时间、请求参数、返回结果、异常信息等,并将这些信息保存到数据库中。此外,还使用了`ThreadLocal`变量来存储每个线程独立的日志数据,确保线程安全。文中还展示了项目实战中的部分代码片段,以及基于Spring Boot 3 + Vue 3构建的快速开发框架的简介与内置功能列表。此框架结合了当前主流技术栈,提供了用户管理、权限控制、接口文档自动生成等多项实用特性。
72 8
|
2月前
|
Java 开发者 微服务
Spring Boot 入门:简化 Java Web 开发的强大工具
Spring Boot 是一个开源的 Java 基础框架,用于创建独立、生产级别的基于Spring框架的应用程序。它旨在简化Spring应用的初始搭建以及开发过程。
89 6
Spring Boot 入门:简化 Java Web 开发的强大工具
|
3月前
|
人工智能 前端开发 Java
基于开源框架Spring AI Alibaba快速构建Java应用
本文旨在帮助开发者快速掌握并应用 Spring AI Alibaba,提升基于 Java 的大模型应用开发效率和安全性。
291 12
基于开源框架Spring AI Alibaba快速构建Java应用