JSR 303 验证以及国际化具体使用加案例分析

简介: JSR 303 验证以及国际化具体使用加案例分析

?前言

JSR 303 验证以及国际化具体使用加案例分析

?个人简介:大家好,我是尘觉,希望我的文章可以帮助到大家,您的满意是我的动力??


?JSR 303 验证以及国际化具体使用加案例分析

● 概述

  1. 对输入的数据(比如表单数据),进行必要的验证,并给出相应的提示信息。
  2. 对于验证表单数据,springMVC 提供了很多实用的注解, 这些注解由 JSR 303 验证框架提供.

● JSR 303 验证框架

  1. JSR 303 是 Java 为 Bean 数据合法性校验提供的标准框架,它已经包含在 JavaEE 中
  2. JSR 303 通过在 Bean 属性上标注类似于 @NotNull、@Max 等标准的注解指定校验规则,并通过标准的验证接口对 Bean 进行验证
  3. JSR 303 提供的基本验证注解有:

● Hibernate Validator 扩展注解

  1. Hibernate Validator 和 Hibernate 没有关系,只是 JSR 303 实现的一个扩展.
  2. Hibernate Validator 是 JSR 303 的一个参考实现,除支持所有标准的校验注解外,它还支持以下的扩展注解:
  3. 扩展注解有如下

?使用实例-代码实现上面的需求

引入验证和国际化相关的 jar 包

修改 Monster.java

@Range(min = 1,max = 100)
    private Integer age;
    //@NotEmpty 表示name不能为空
    //Asserts that the annotated string, collection, map or array is not {@code null} or empty.
    @NotEmpty
    private String name;

修改 MonsterHandler.java

  • @Valid Monster monster :表示对monster接收的数据进行校验
  • Errors errors 表示如果校验出现错误,将校验的错误信息保存 errors
  • Map map 表示如果校验出现错误, 将校验的错误信息保存 map 同时保存monster对象
  • 校验发生的时机: 在springmvc底层,反射调用目标方法时,会接收到http请求的数据,然后根据注解来进行验证
  • 在验证过程中,如果出现了错误,就把错误信息填充errors 和 map
@RequestMapping(value = "/save")
    public String save(@Valid Monster monster, Errors errors, Map<String, Object> map) {
        System.out.println("----monster---" + monster);
        //我们为了看到验证的情况,我们输出map 和 errors
        System.out.println("===== map ======");
        for (Map.Entry<String, Object> entry : map.entrySet()) {
            System.out.println("key= " + entry.getKey() + " value=" + entry.getValue());
        }
        System.out.println("===== errors ======");
        if (errors.hasErrors()) {//判断是否有错误
            List<ObjectError> allErrors = errors.getAllErrors();
            for (ObjectError error : allErrors) {
                System.out.println("error=" + error);
            }
            return "datavalid/monster_addUI";
        }
        return "datavalid/success";
    }

—这里可以测试一下,看看效果----

配置国际化文件 springDispatcherServlet-servlet.xml

<!-- 配置国际化错误信息的资源处理bean -->
    <bean id="messageSource" class=
            "org.springframework.context.support.ResourceBundleMessageSource">
        <!-- 配置国际化文件名字
            如果你这样配的话,表示messageSource回到 src/i18nXXX.properties去读取错误信息
         -->
        <property name="basename" value="i18n"></property>
    </bean>

创建国际化文件i18n.properties

这是Unicode码 不知道也没有关系 可以百度搜索转换工具就好了 因为直接输入中文可能会导致乱码或者解析所以这里使用Unicode

NotEmpty.monster.name=\u7528\u6237\u540d\u4e0d\u80fd\u4e3a\u7a7a
typeMismatch.monster.age=\u5e74\u9f84\u8981\u6c42\u5728\u0031\u002d\u0031\u0035\
u0030\u4e4b\u95f4
typeMismatch.monster.birthday=\u751f\u65e5\u683c\u5f0f\u4e0d\u6b63\u786e
typeMismatch.monster.salary=\u85aa\u6c34\u683c\u5f0f\u4e0d\u6b63\u786e

修改 monster_addUI.jsp , 回显错误信息

<form:form action="save" method="post" modelAttribute="monster">
    妖怪名字: <form:input path="name"/> <form:errors path="name"/>  <br><br>
    妖怪年龄~: <form:input path="age"/> <form:errors path="age"/> <br><br>
    电子邮件: <form:input path="email"/> <form:errors path="email"/>  <br><br>
    妖怪生日: <form:input path="birthday"/> <form:errors path="birthday"/> 要求以"9999-11-11"的形式<br><br>
    妖怪薪水: <form:input path="salary"/> <form:errors path="salary"/> 要求以"123,890.12"的形式<br><br>
    <input type="submit" value="添加妖怪"/>
</form:form>
</body>
</html>

完成测试

细节说明和注意事项

  1. 在需要验证的 Javabean/POJO 的字段上加上相应的验证注解.
  2. 目标方法上,在 JavaBean/POJO 类型的参数前, 添加 @Valid 注解. 告知 SpringMVC 该 bean 是需要验证的
  3. 在 @Valid 注解之后, 添加一个 Errors 或 BindingResult 类型的参数, 可以获取到验证的错误信息
  4. 需要使用  标签来显示错误消息, 这个标签,需要写在 标签内生效.
  5. 错误消息的国际化文件 i18n.properties , 中文需要是 Unicode 编码,使用工具转码.

√ 格式: 验证规则.表单 modelAttribute 值.属性名=消息信息

√ NotEmpty.monster.name=\u540D\u5B57\u4E0D\u80FD\u4E3A\u7A7A

√ typeMismatch.monster.age=\u7C7B\u578B\u4E0D\u5339\u914D

  1. 注解@NotNull 和 @NotEmpty 的区别说明

\1) 查看源码可以知道 : @NotEmpty Asserts that the annotated string, collection, map or array is not {@code null} or empty.

\2) 查看源码可以知道 : @NotNull * The annotated element must not be {@code null}.* Accepts any type.

\3) 解读:如果是字符串验证空, 建议使用 @NotEmpty

  1. SpingMVC 验证时,会根据不同的验证错误, 返回对应的信息

注解的结合使用

● 问题提出, age 没有, 是空的,提交确是成功了

解决方案注解组合使用

使用@NotNull + @Range 组合使用解决
public class Monster {
    private Integer id;
    //email是string,使用@NotEmpty
    @NotEmpty
    private String email;
    //@Range(min = 1,max = 100)
    //表示接收的age值,在 1-100之间
    @NotNull(message = "age不能为空")
    @Range(min = 1,max = 100)
    private Integer age;
    //@NotEmpty 表示name不能为空
    //Asserts that the annotated string, collection, map or array is not {@code null} or empty.
    @NotEmpty
    private String name;
    @NotNull(message = "生日不能为空")
    @DateTimeFormat(pattern = "yyyy-MM-dd")
    private Date birthday;
    @NotNull(message = "薪水不能为空")
    @NumberFormat(pattern = "###,###.##")
    private Float salary;
    public Monster(Integer id, String email, Integer age, String name, Date birthday, Float salary) {
        this.id = id;
        this.email = email;
        this.age = age;
        this.name = name;
        this.birthday = birthday;
        this.salary = salary;
    }
    public Date getBirthday() {
        return birthday;
    }
    public void setBirthday(Date birthday) {
        this.birthday = birthday;
    }
    public Float getSalary() {
        return salary;
    }
    public void setSalary(Float salary) {
        this.salary = salary;
    }
    public Monster() {
    }
    public Integer getId() {
        return id;
    }
    public void setId(Integer id) {
        this.id = id;
    }
    public String getEmail() {
        return email;
    }
    public void setEmail(String email) {
        this.email = email;
    }
    public Integer getAge() {
        return age;
    }
    public void setAge(Integer age) {
        this.age = age;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    @Override
    public String toString() {
        return "Monster{" +
                "id=" + id +
                ", email='" + email + '\'' +
                ", age=" + age +
                ", name='" + name + '\'' +
                ", birthday=" + birthday +
                ", salary=" + salary +
                '}';
    }
}
测试

这时 age 不能为空,同时必须是 1-100, (也不能输入 haha, hello 等不 能转成数字的内容)

?数据类型转换校验核心类-DataBinder

● DataBinder 工作机制-了解

图例 Spring MVC 通过反射机制对目标方法进行解析,将请求消息绑定到处理方法的入参中。

数据绑定的核心部件是 DataBinder,运行机制如下

- Debug 一下 validate 得到验证 errors

从serverRequest拿到相应的数据然后 拿到处理方法的签名得到你的方法的一些形参的信息并且进行封装把你这入参参数传给我们 比如要封装的对象流程先进行数据类型的转换如果发送错误直接放到BindingResult在进行数据校验如果出错了就继续放入最后放到error中显示输出

错误信息就在这里面

类图

取消某个属性的绑定

说明

在默认情况下,表单提交的数据都会和 pojo 类型的 javabean 属性绑定,如果程序员在开发中,希望取消某个属性的绑定,也就是说,不希望接收到某个表单对应的属性的值,则可以通过 @InitBinder 注解取消绑定.

  1. 编写一个方法, 使用@InitBinder 标识的该方法,可以对 WebDataBinder 对象进行初始化。WebDataBinder 是 DataBinder 的子类,用于完成由表单字段到 JavaBean 属性的绑定
  2. @InitBinder 方法不能有返回值,它必须声明为 void。
  3. @InitBinder 方法的参数通常是是 WebDataBinder

● 案例-不希望接收怪物的名字属性

修改 MonsterHandler.java

@InitBinder
    public void initBinder(WebDataBinder webDataBinder) {
        //测试完,记得注销了.
        webDataBinder.setDisallowedFields("name");
    }

解读

  1. 方法上需要标注 @InitBinder springmvc底层会初始化 WebDataBinder
  2. 调用 webDataBinder.setDisallowedFields(“name”) 表示取消指定属性的绑定
    即:当表单提交字段为 name时, 就不在把接收到的name值,填充到model数据的monster的name属性
  3. 机制:springmvc 在底层通过反射调用目标方法时, 接收到http请求的参数和值,使用反射+注解技术取消对指定属性的填充
  4. setDisallowedFields支持可变参数,可以填写多个字段
  5. 如果我们取消某个属性绑定,验证就没有意义了,应当把验证的注解去掉, name属性会使用默认值null一般来说,如果不接收表单字段提交数据,则该对象字段的验证也就没有意义了可以注 销掉,比如 注销 //@NotEmpt

修改 Monster.java

?总结

在需要验证的 Javabean/POJO 的字段上加上相应的验证注解.

JSR 303 验证是一款非常好用的验证框架 使用的时候要注意组合

目标方法上,在 JavaBean/POJO 类型的参数前, 添加 @Valid 注解. 告知 SpringMVC 该 bean 是需要验证的

错误消息的国际化文件 i18n.properties , 中文需要是 Unicode 编码,使用工具转码.


文章到这里就结束了,如果有什么疑问的地方请指出,诸佬们一起来评论区一起讨论?

希望能和诸佬们一起努力,今后我们一起观看感谢您的阅读?

如果帮助到您不妨3连支持一下,创造不易您们的支持是我的动力?


目录
相关文章
|
1天前
|
SQL 设计模式 Java
Java编码规范与最佳实践
Java编码规范与最佳实践
21 0
|
9月前
|
编解码 前端开发 Java
springMVC--数据验证以及国际化
springMVC--数据验证以及国际化
91 0
Yii2的国际化和本地化支持是什么?底层原理是什么?
Yii2的国际化和本地化支持是什么?底层原理是什么?
120 0
|
XML JavaScript Java
技术分享 | 接口自动化测试中如何对xml 格式做断言验证?
在服务端自动化测试过程中,发起请求之后还需要对响应值进行验证,验证响应信息符合预期值之后,这一条接口自动化测试用例才算完整的通过。所以这一章节,将会讲解在接口自动化测试中,是如何对服务端返回的 XML 格式响应内容做断言验证。
|
JSON Java BI
JSR310新日期API(完结篇)-生产实战
前面通过五篇文章基本介绍完JSR-310常用的日期时间API以及一些工具类,这篇博文主要说说笔者在生产实战中使用JSR-310日期时间API的一些经验。
386 0
JSR310新日期API(完结篇)-生产实战
|
Java 数据库连接 API
4. Validator校验器的五大核心组件,一个都不能少
4. Validator校验器的五大核心组件,一个都不能少
4. Validator校验器的五大核心组件,一个都不能少
|
前端开发 Java 数据库连接
SpringMVC的数据验证和JSR 303国际化显示(十一)下
SpringMVC的数据验证和JSR 303国际化显示(十一)下
289 0
SpringMVC的数据验证和JSR 303国际化显示(十一)下
|
前端开发 JavaScript Java
SpringMVC的数据验证和JSR 303国际化显示(十一)上
SpringMVC的数据验证和JSR 303国际化显示(十一)上
194 0
SpringMVC的数据验证和JSR 303国际化显示(十一)上
|
前端开发 Java 数据库连接
SpringMVC的数据验证和JSR 303国际化显示(十一)中
SpringMVC的数据验证和JSR 303国际化显示(十一)中
184 0
SpringMVC的数据验证和JSR 303国际化显示(十一)中
|
XML 前端开发 数据安全/隐私保护
Struts2利用验证框架实现数据验证(十一)中
Struts2利用验证框架实现数据验证(十一)
145 0
Struts2利用验证框架实现数据验证(十一)中
http://www.vxiaotou.com