day09-2-验证以及国际化

打印 上一主题 下一主题

主题 868|帖子 868|积分 2604

验证以及国际化

1.概述

(1)概述

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

  • JSR 303 是 Java 为 Bean 数据合法性校验提供的标准框架,它已经包含在 JavaEE 中
  • JSR 303 通过在 Bean 属性上标注类似于 @NotNull、@Max 等标注的注解指定校验规则,并通过标准的验证接口对 Bean 进行验证
  • JSR 303 提供的基本验证注解有:
注解功能说明@Null被注释的元素必须为null@NotNull被注释的元素不能为null@AssertTrue被注释的元素必须为true@AssertFalse被注释的元素必须为false@Min(value)被注释的元素必须是一个数字,其值必须大于等于指定的最小值@Max(value)被注释的元素必须是一个数字,其值必须小于等于指定的最大值@DecimalMin(value)被注释的元素必须是一个数字,其值必须大于等于指定的最小值@DecimalMax(value)被注释的元素必须是一个数字,其值必须小于等于指定的最大值@Size(max,min)被注释的元素的大小必须在指定的范围内@Digits(integer,fraction)被注释的元素必须是一个数字,其值必须在可接受的范围内@Past被注释的元素必须是一个过去的日期@Future被注释的元素必须是一个将来的日期@Pattern(value)被注释的元素必须符合指定的正则表达式(3)Hibernate Validator 扩展注解

  • Hibernate Validator 和 Hibernate 没有关系,只是 JSR 303 实现的一个扩展
  • Hibernate Validator 是 JSR 303的一个参考实现,除支持所有标准的校验注解外,它还支持以下的扩展注解:
注解功能说明@Email被注释的元素必须是电子邮件地址@Length被注释的字符串的大小必须在指定的范围内@NotEmpty被注释的字符串必须非空@Range被注释的元素必须在合适的范围内2.应用实例

需求说明
指定表单的数据格式,后端在接收到数据后,能够对数据进行校验,并给不符合格式的数据返回提示信息,显示在前端页面
2.1代码实现

(1)引入验证和国际化相关的jar包
(2)Monster.java,属性添加注解以验证格式
  1. package com.li.web.datavalid.entity;
  2. import org.hibernate.validator.constraints.Email;
  3. import org.hibernate.validator.constraints.NotEmpty;
  4. import org.hibernate.validator.constraints.Range;
  5. import org.springframework.format.annotation.DateTimeFormat;
  6. import org.springframework.format.annotation.NumberFormat;
  7. import java.util.Date;
  8. /**
  9. * @author 李
  10. * @version 1.0
  11. */
  12. public class Monster {
  13.     @NotEmpty
  14.     private Integer id;
  15.     @Email
  16.     private String email;
  17.     //表示接收到的age的值必须在1-100之间
  18.     @Range(min = 1, max = 100)
  19.     private Integer age;
  20.     //Asserts that the annotated string, collection,
  21.     // map or array is not {@code null} or empty.
  22.     @NotEmpty
  23.     private String name;
  24.     @DateTimeFormat(pattern = "yyyy-MM-dd")
  25.     private Date birthday;
  26.     @NumberFormat(pattern = "###,###.##")
  27.     private Float salary;
  28.     public Monster() {
  29.     }
  30.     public Monster(Integer id, String email, Integer age, String name, Date birthday, Float salary) {
  31. <bean
  32.       id="messageSource">
  33.    
  34.     <property name="basename" value="i18n"/>
  35. </bean>this.id = id;
  36. <bean
  37.       id="messageSource">
  38.    
  39.     <property name="basename" value="i18n"/>
  40. </bean>this.email = email;
  41. <bean
  42.       id="messageSource">
  43.    
  44.     <property name="basename" value="i18n"/>
  45. </bean>this.age = age;
  46. <bean
  47.       id="messageSource">
  48.    
  49.     <property name="basename" value="i18n"/>
  50. </bean>this.name = name;
  51. <bean
  52.       id="messageSource">
  53.    
  54.     <property name="basename" value="i18n"/>
  55. </bean>this.birthday = birthday;
  56. <bean
  57.       id="messageSource">
  58.    
  59.     <property name="basename" value="i18n"/>
  60. </bean>this.salary = salary;
  61.     }
  62.     public Integer getId() {
  63. <bean
  64.       id="messageSource">
  65.    
  66.     <property name="basename" value="i18n"/>
  67. </bean>return id;
  68.     }
  69.     public Date getBirthday() {
  70. <bean
  71.       id="messageSource">
  72.    
  73.     <property name="basename" value="i18n"/>
  74. </bean>return birthday;
  75.     }
  76.     public void setBirthday(Date birthday) {
  77. <bean
  78.       id="messageSource">
  79.    
  80.     <property name="basename" value="i18n"/>
  81. </bean>this.birthday = birthday;
  82.     }
  83.     public Float getSalary() {
  84. <bean
  85.       id="messageSource">
  86.    
  87.     <property name="basename" value="i18n"/>
  88. </bean>return salary;
  89.     }
  90.     public void setSalary(Float salary) {
  91. <bean
  92.       id="messageSource">
  93.    
  94.     <property name="basename" value="i18n"/>
  95. </bean>this.salary = salary;
  96.     }
  97.     public void setId(Integer id) {
  98. <bean
  99.       id="messageSource">
  100.    
  101.     <property name="basename" value="i18n"/>
  102. </bean>this.id = id;
  103.     }
  104.     public String getEmail() {
  105. <bean
  106.       id="messageSource">
  107.    
  108.     <property name="basename" value="i18n"/>
  109. </bean>return email;
  110.     }
  111.     public void setEmail(String email) {
  112. <bean
  113.       id="messageSource">
  114.    
  115.     <property name="basename" value="i18n"/>
  116. </bean>this.email = email;
  117.     }
  118.     public Integer getAge() {
  119. <bean
  120.       id="messageSource">
  121.    
  122.     <property name="basename" value="i18n"/>
  123. </bean>return age;
  124.     }
  125.     public void setAge(Integer age) {
  126. <bean
  127.       id="messageSource">
  128.    
  129.     <property name="basename" value="i18n"/>
  130. </bean>this.age = age;
  131.     }
  132.     public String getName() {
  133. <bean
  134.       id="messageSource">
  135.    
  136.     <property name="basename" value="i18n"/>
  137. </bean>return name;
  138.     }
  139.     public void setName(String name) {
  140. <bean
  141.       id="messageSource">
  142.    
  143.     <property name="basename" value="i18n"/>
  144. </bean>this.name = name;
  145.     }
  146.     @Override
  147.     public String toString() {
  148. <bean
  149.       id="messageSource">
  150.    
  151.     <property name="basename" value="i18n"/>
  152. </bean>return "Monster{" +
  153. <bean
  154.       id="messageSource">
  155.    
  156.     <property name="basename" value="i18n"/>
  157. </bean><bean
  158.       id="messageSource">
  159.    
  160.     <property name="basename" value="i18n"/>
  161. </bean>"id=" + id +
  162. <bean
  163.       id="messageSource">
  164.    
  165.     <property name="basename" value="i18n"/>
  166. </bean><bean
  167.       id="messageSource">
  168.    
  169.     <property name="basename" value="i18n"/>
  170. </bean>", email='" + email + '\'' +
  171. <bean
  172.       id="messageSource">
  173.    
  174.     <property name="basename" value="i18n"/>
  175. </bean><bean
  176.       id="messageSource">
  177.    
  178.     <property name="basename" value="i18n"/>
  179. </bean>", age=" + age +
  180. <bean
  181.       id="messageSource">
  182.    
  183.     <property name="basename" value="i18n"/>
  184. </bean><bean
  185.       id="messageSource">
  186.    
  187.     <property name="basename" value="i18n"/>
  188. </bean>", name='" + name + '\'' +
  189. <bean
  190.       id="messageSource">
  191.    
  192.     <property name="basename" value="i18n"/>
  193. </bean><bean
  194.       id="messageSource">
  195.    
  196.     <property name="basename" value="i18n"/>
  197. </bean>", birthday=" + birthday +
  198. <bean
  199.       id="messageSource">
  200.    
  201.     <property name="basename" value="i18n"/>
  202. </bean><bean
  203.       id="messageSource">
  204.    
  205.     <property name="basename" value="i18n"/>
  206. </bean>", salary=" + salary +
  207. <bean
  208.       id="messageSource">
  209.    
  210.     <property name="basename" value="i18n"/>
  211. </bean><bean
  212.       id="messageSource">
  213.    
  214.     <property name="basename" value="i18n"/>
  215. </bean>'}';
  216.     }
  217. }
复制代码
(3)MonsterHandler.java
  1. package com.li.web.datavalid;
  2. import com.li.web.datavalid.entity.Monster;
  3. import org.springframework.context.annotation.Scope;
  4. import org.springframework.stereotype.Controller;
  5. import org.springframework.validation.Errors;
  6. import org.springframework.validation.ObjectError;
  7. import org.springframework.web.bind.annotation.RequestMapping;
  8. import org.springframework.web.bind.annotation.RequestMethod;
  9. import javax.validation.Valid;
  10. import java.util.Map;
  11. /**
  12. * @author 李
  13. * @version 1.0
  14. */
  15. @Controller
  16. @Scope(value = "prototype")
  17. public class MonsterHandler {
  18.     /**
  19.      * 1.SpringMVC可以将提交的数据,按照参数名和形参对象的属性名匹配,
  20.      * 然后直接封装到对象中[模型数据]
  21.      * 2.@Valid Monster monster 表示对monster接收的数据进行校验
  22.      * 3.校验的发生的时机:在SpringMVC底层反射调用目标方法时,会接收到http请求接收到的数据,
  23.      * 然后根据注解来进行验证。在验证过程中,如果出现了错误,就把错误信息填充到errors和 map中
  24.      * @param monster
  25.      * @param errors  表示如果校验出现了错误,会将校验的错误信息保存到errors中
  26.      * @param map     map不但会保存monster对象,如果校验出现错误,也会将校验的错误信息放到map中
  27.      * @return
  28.      */
  29.     @RequestMapping(value = "/save", method = RequestMethod.POST)
  30.     public String save(@Valid Monster monster, Errors errors, Map<String, Object> map) {
  31. <bean
  32.       id="messageSource">
  33.    
  34.     <property name="basename" value="i18n"/>
  35. </bean>System.out.println("----monster----" + monster);
  36. <bean
  37.       id="messageSource">
  38.    
  39.     <property name="basename" value="i18n"/>
  40. </bean>//为了查看验证的情况,输出map和errors
  41. <bean
  42.       id="messageSource">
  43.    
  44.     <property name="basename" value="i18n"/>
  45. </bean>System.out.println("=======map=======");
  46. <bean
  47.       id="messageSource">
  48.    
  49.     <property name="basename" value="i18n"/>
  50. </bean>for (Map.Entry<String, Object> entry : map.entrySet()) {
  51. <bean
  52.       id="messageSource">
  53.    
  54.     <property name="basename" value="i18n"/>
  55. </bean>    System.out.println("key=" + entry.getKey() +
  56. <bean
  57.       id="messageSource">
  58.    
  59.     <property name="basename" value="i18n"/>
  60. </bean><bean
  61.       id="messageSource">
  62.    
  63.     <property name="basename" value="i18n"/>
  64. </bean>    " value=" + entry.getValue());
  65. <bean
  66.       id="messageSource">
  67.    
  68.     <property name="basename" value="i18n"/>
  69. </bean>    System.out.println("--------");
  70. <bean
  71.       id="messageSource">
  72.    
  73.     <property name="basename" value="i18n"/>
  74. </bean>}
  75. <bean
  76.       id="messageSource">
  77.    
  78.     <property name="basename" value="i18n"/>
  79. </bean>System.out.println("=======errors=======");
  80. <bean
  81.       id="messageSource">
  82.    
  83.     <property name="basename" value="i18n"/>
  84. </bean>for (ObjectError error : errors.getAllErrors()) {
  85. <bean
  86.       id="messageSource">
  87.    
  88.     <property name="basename" value="i18n"/>
  89. </bean>    System.out.println("error="+error);
  90. <bean
  91.       id="messageSource">
  92.    
  93.     <property name="basename" value="i18n"/>
  94. </bean>}
  95.    
  96. <bean
  97.       id="messageSource">
  98.    
  99.     <property name="basename" value="i18n"/>
  100. </bean>return "datavalid/success";
  101.     }
  102. }
复制代码
(4)monster_addUI.jsp:
  1. <%@taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
  2. <%@ page contentType="text/html;charset=UTF-8" language="java" %>
  3. <html>
  4. <head>
  5.     <title>添加妖怪</title>
  6. </head>
  7. <body>
  8. <h3>添加妖怪</h3>
  9. <form:form action="save" method="post" modelAttribute="monster">
  10.     妖怪id:<form:input path="id"/><br/><br/>
  11.     妖怪名字:<form:input path="name"/><br/><br/>
  12.     妖怪年龄:<form:input path="age"/><br/><br/>
  13.     妖怪生日:<form:input path="birthday"/> 要求以"yyyy-MM-dd"的格式<br/><br/>
  14.     妖怪工资:<form:input path="salary"/> 要求以"###,###.##"的格式<br/><br/>
  15.     电子邮件:<form:input path="email"/><br/><br/>
  16.     <input type="submit" value="添加妖怪"/>
  17. </form:form>
  18. </body>
  19. </html>
复制代码
(5)测试
提交的数据:年龄这里故意填写不符合格式的数据(1-100)
后台输出了默认的错误信息:
  1. ----monster----Monster{id=1, email='king@sohu.com', age=999, name='king', birthday=Tue Jan 01 00:00:00 CST 1924, salary=1267.22}
  2. =======map=======
  3. key=monster value=Monster{id=1, email='king@sohu.com', age=999, name='king', birthday=Tue Jan 01 00:00:00 CST 1924, salary=1267.22}
  4. --------
  5. key=org.springframework.validation.BindingResult.monster value=org.springframework.validation.BeanPropertyBindingResult: 1 errors
  6. Field error in object 'monster' on field 'age': rejected value [999]; codes [Range.monster.age,Range.age,Range.java.lang.Integer,Range]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [monster.age,age]; arguments []; default message [age],100,1]; default message [需要在1和100之间]
  7. --------
  8. =======errors=======
  9. error=Field error in object 'monster' on field 'age': rejected value [999]; codes [Range.monster.age,Range.age,Range.java.lang.Integer,Range]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [monster.age,age]; arguments []; default message [age],100,1]; default message [需要在1和100之间]
复制代码
(6)自定义错误信息:配置 springDispatcherServlet-servlet.xml
  1. <bean
  2.       id="messageSource">
  3.    
  4.     <property name="basename" value="i18n"/>
  5. </bean>
复制代码
(7)在src 目录下创建国际化文件 i18n.properties
中文要使用 unicode 编码处理
  1. NotEmpty.monster.name=\u7528\u6237\u540d\u4e0d\u80fd\u4e3a\u7a7a
  2. typeMismatch.monster.age=\u5e74\u9f84\u8981\u6c42\u5728\u0031\u002d\u0031\u0035\u0030\u4e4b\u95f4
  3. typeMismatch.monster.birthday=\u751f\u65e5\u683c\u5f0f\u4e0d\u6b63\u786e
  4. typeMismatch.monster.salary=\u85aa\u6c34\u683c\u5f0f\u4e0d\u6b63\u786e
复制代码
(8)修改 monster_addUI.jsp 的 form ,回显错误信息
  1. <form:form action="save" method="post" modelAttribute="monster">
  2.     妖怪id:<form:input path="id"/><form:errors path="id"/><br/><br/>
  3.     妖怪名字:<form:input path="name"/><form:errors path="name"/><br/><br/>
  4.     妖怪年龄:<form:input path="age"/><form:errors path="age"/><br/><br/>
  5.     妖怪生日:<form:input path="birthday"/><form:errors path="birthday"/>
  6.     要求以"yyyy-MM-dd"的格式<br/><br/>
  7.     妖怪工资:<form:input path="salary"/><form:errors path="salary"/>
  8.     要求以"###,###.##"的格式<br/><br/>
  9.     电子邮件:<form:input path="email"/><form:errors path="email"/><br/><br/>
  10.     <input type="submit" value="添加妖怪"/>
  11. </form:form>
复制代码
(9)再次进行测试
没有在properties文件中配置的提示,将会按照默认的错误信息回显
2.2细节说明和注意事项


  • 在需要验证的 Javabean/POJO 的字段上添加相应的验证注解
  • 目标方法上,在 Javabean/POJO 类型的参数前,添加 @Valid 注解以告知 SpringMVC 该 Bean 是需要验证的
  • 在 @Valid 注解之后,添加一个 Errors 或 BindingResult 类型的参数,可以获取到验证的错误信息
    校验的发生的时机:SpringMVC 底层反射调用目标方法前,会接收到 http 请求接收到的数据,然后根据验证注解来进行验证。在验证过程中,如果出现了错误,就把错误信息填充到 errors,map 等参数中

  • 需要使用  标签来显示错误信息,该标签需要写在  标签内生效
  • 自定义错误消息的国际化文件 i18n.properties,如果是中文需要使用 unicode 编码处理。
    格式为:验证规则.表单modelAttribute值.属性名=错误提示信息

  • 注意@NotNull 和 @NotEmpty 的区别
    @NotEmpty:
    1. Asserts that the annotated string, collection, map or array is not {@code null} or empty.
    复制代码
    @NotNull:
    1. The annotated element must not be {@code null}. Accepts any type.
    复制代码
    如果是字符串验证空,建议使用 @NotEmpty
  • SpringMVC 验证时,同一个属性,会根据不同的验证错误,返回不同的错误信息
3.注解的结合使用


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

千千梦丶琪

金牌会员
这个人很懒什么都没写!
快速回复 返回顶部 返回列表