天天看點

Spring MVC資料格式化與驗證以及國際化和中文亂碼處理

Spring MVC資料格式化

基本介紹

說明: 在我們送出資料(比如表單時)SpringMVC 怎樣對送出的資料進行轉換和處理的

基本資料類型可以和字元串之間自動完成轉換,

比如:Spring MVC 上下文中内建了很多轉換器,可完成大多數 Java 類型的轉換工作。[互相轉換,這裡隻列出部分]

ConversionService converters =

java.lang.Boolean- >java.lang.String:org.springframework.core.convert.support.ObjectToStringConverter@f874ca java.lang.Character -> java.lang.Number : CharacterToNumberFactory@f004c9 java.lang.Character -> java.lang.String : ObjectToStringConverter@68a961 java.lang.Enum -> java.lang.String : EnumToStringConverter@12f060a java.lang.Number -> java.lang.Character : NumberToCharacterConverter@1482ac5 java.lang.Number -> java.lang.Number : NumberToNumberConverterFactory@126c6f java.lang.Number -> java.lang.String : ObjectToStringConverter@14888e8 java.lang.String -> java.lang.Boolean : StringToBooleanConverter@1ca6626 java.lang.String -> java.lang.Character : StringToCharacterConverter@1143800 java.lang.String -> java.lang.Enum : StringToEnumConverterFactory@1bba86e java.lang.String -> java.lang.Number : StringToNumberConverterFactory@18d2c12 java.lang.String -> java.util.Locale : StringToLocaleConverter@3598e1 java.lang.String -> java.util.Properties : StringToPropertiesConverter@c90828 java.lang.String -> java.util.UUID : StringToUUIDConverter@a42f23 java.util.Locale -> java.lang.String : ObjectToStringConverter@c7e20a java.util.Properties -> java.lang.String : PropertiesToStringConverter@367a7f java.util.UUID -> java.lang.String : ObjectToStringConverter@112b07f …….

基本資料類型和字元串自動轉換

代碼執行個體 -頁面示範方式

需求->基本資料類型可以和字元串之間自動完成轉換

Spring MVC資料格式化與驗證以及國際化和中文亂碼處理

建立Monster 類

java複制代碼public class Monster {
    private Integer id;
    private String email;
    private Integer age;
    private String name;
    

    public Monster(Integer id, String email, Integer age, String name,) {
        this.id = id;
        this.email = email;
        this.age = age;
        this.name = name;
       
    }

    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 + '\'' +
                '}';
    }
}
           

建立data_valid.jsp

html複制代碼<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>SpringMVC[資料格式/驗證等]</title>
</head>
<body>
<h1>SpringMVC[資料格式/驗證等]</h1>
<hr>
<a href="<%=request.getContextPath()%>/addMonsterUI">添加妖怪</a>
</body>
</body>
</html>
           

建立MonsterHandler類

java複制代碼    @RequestMapping(value = "/addMonsterUI")
    public String addMonsterUI(Map<String, Object> map) {

        map.put("monster", new Monster());
        return "datavalid/monster_addUI";
    }
           

建立monster_addUI.jsp

html複制代碼<html>
<head>
    <title>添加妖怪</title>
</head>
<body>
<h3>添加妖怪</h3>

<form:form action="save" method="post" modelAttribute="monster">
    妖怪名字: <form:input path="name"/><br><br>
    妖怪年齡~: <form:input path="age"/><br><br>
    電子郵件: <form:input path="email"/> <br><br>
    <input type="submit" value="添加妖怪"/>
</form:form>
</body>
</html>
           

解讀:

1. 這裡的表單,我們使用springMVC的标簽來完成

2. SpringMVC 表單标簽在顯示之前必須在 request 中有一個 bean,

該 bean 的屬性和表單标簽的字段要對應!

request 中的 key 為: form 标簽的 modelAttrite 屬性值, 比如這裡的monster

3. SpringMVC 的 form:form 标簽的 action 屬性值中的 / 不代表 WEB 應用的根目錄.

4. <form:form action="?" method="POST" modelAttribute="monster">

這裡需要給request增加一個 monster,因為jsp 頁面 的modelAttribute="monster"需要這時是springMVC的内部的檢測機制 即使是一個空的也需要,否則報錯.

說明

如果你跳轉的頁面使用springmvc标簽就需要準備一個對象,放入request域中,這個對象的屬性名 monster, 對應springmvc表單标簽的 modelAttribute="monster"

階段測試一下

Spring MVC資料格式化與驗證以及國際化和中文亂碼處理

繼續完成功能

建立success.jsp

html複制代碼<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>添加成功</title>
</head>
<body>
<h1>恭喜, 添加成功~</h1>
</body>
</html>
           

修改 MonsterHandler.java , 增加處理添加請求

編寫方法,處理添加妖怪

1. springmvc可以将送出的資料,按照參數名和對象的屬性名比對

2. 直接封裝到對象中->前面講解模型資料時,講過String => Integer

java複制代碼
    @RequestMapping(value = "/save")
    public String save(Monster monster) {
        System.out.println("----monster---" + monster);
       
        return "datavalid/success";
    }
           

測試

浏覽器: http://localhost:8080/springmvc/data_valid.jsp

1) 如果age 輸入的是 數字,則通過, 說明SpringMVC可以将送出的字元串 數字,比如"28",轉成 Integer/int

2) 如果不是數字,則給出 400 的頁面

Spring MVC資料格式化與驗證以及國際化和中文亂碼處理

3) 如何給出對應的提示,我們後面馬上講解

-Postman 完成

Spring MVC資料格式化與驗證以及國際化和中文亂碼處理

1) 如果age 輸入的是 數字,則通過, 說明SpringMVC可以将送出的字元串 數字,比如"28", 轉成 Integer/int

2) 如果不是數字,則給出 400 的頁面 與上面測試一模一樣

特殊資料類型和字元串間的轉換

應用執行個體 -頁面示範方式

1. 特殊資料類型和字元串之間的轉換使用注解(比如日期,規定格式的小數比如貨币形式

等)

2. 對于日期和貨币可以使用 @DateTimeFormat 和 @NumberFormat 注解. 把這兩個注

解标記在字段上即可

Spring MVC資料格式化與驗證以及國際化和中文亂碼處理

修改 Monster.java , 增加 birthday 和 salary 字段

java複制代碼public class Monster {
    private Integer id;


    private String email;

    private Integer age;

    private String name;

    @DateTimeFormat(pattern = "yyyy-MM-dd")
    private Date birthday;

    @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 +
                '}';
    }
}
           

修改 monster_addUI, 增加 birthday 和salary字段

html複制代碼妖怪年齡~: <form:input path="age"/> <br><br>
妖怪生日: <form:input path="birthday"/> 要求以"9999-11-11"的形式<br><br>
妖怪工資: <form:input path="salary"/> 要求以"123,890.12"的形式<br><br>
           

測試

1) 如果 birthday 和 salary 是按照指定格式輸入,則通過, 說明 SpringMVC 可以按注解指定

格式轉換

2) 如果沒有按照注解指定格式,則給出 400 的頁面

3) 如何給出對應的提示,我們後面馬上講解

Spring MVC資料格式化與驗證以及國際化和中文亂碼處理
Spring MVC資料格式化與驗證以及國際化和中文亂碼處理

驗證以及國際化

● 概述

1. 對輸入的資料(比如表單資料),進行必要的驗證,并給出相應的提示資訊。

2. 對于驗證表單資料,springMVC 提供了很多實用的注解, 這些注解由 JSR 303 驗證架構提供.

● JSR 303 驗證架構

1. JSR 303 是 Java 為 Bean 資料合法性校驗提供的标準架構,它已經包含在 JavaEE 中

2. JSR 303 通過在 Bean 屬性上标注類似于 @NotNull、@Max 等标準的注解指定校驗規則,并通過标準的驗證接口對 Bean 進行驗證

3. JSR 303 提供的基本驗證注解有:

Spring MVC資料格式化與驗證以及國際化和中文亂碼處理

● Hibernate Validator 擴充注解

1. Hibernate Validator 和 Hibernate 沒有關系,隻是 JSR 303 實作的一個擴充.

2. Hibernate Validator 是 JSR 303 的一個參考實作,除支援所有标準的校驗注解外,它還支援以下的擴充注解:

3. 擴充注解有如下

Spring MVC資料格式化與驗證以及國際化和中文亂碼處理

使用執行個體-代碼實作上面的需求

Spring MVC資料格式化與驗證以及國際化和中文亂碼處理

引入驗證和國際化相關的 jar 包

Spring MVC資料格式化與驗證以及國際化和中文亂碼處理

修改 Monster.java

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<String, Object> map 表示如果校驗出現錯誤, 将校驗的錯誤資訊儲存 map 同時儲存monster對象
  • 校驗發生的時機: 在springmvc底層,反射調用目标方法時,會接收到http請求的資料,然後根據注解來進行驗證
  • 在驗證過程中,如果出現了錯誤,就把錯誤資訊填充errors 和 map
java複制代碼
    @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";
    }
           

---這裡可以測試一下,看看效果----

Spring MVC資料格式化與驗證以及國際化和中文亂碼處理
Spring MVC資料格式化與驗證以及國際化和中文亂碼處理
Spring MVC資料格式化與驗證以及國際化和中文亂碼處理

配置國際化檔案 springDispatcherServlet-servlet.xml

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

XML複制代碼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 , 回顯錯誤資訊

html複制代碼<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>
           

完成測試

Spring MVC資料格式化與驗證以及國際化和中文亂碼處理

細節說明和注意事項

1. 在需要驗證的 Javabean/POJO 的字段上加上相應的驗證注解.

2. 目标方法上,在 JavaBean/POJO 類型的參數前, 添加 @Valid 注解. 告知 SpringMVC 該 bean 是需要驗證的

3. 在 @Valid 注解之後, 添加一個 Errors 或 BindingResult 類型的參數, 可以擷取到驗證的錯誤資訊

4. 需要使用 <form:errors path="email"></form:errors> 标簽來顯示錯誤消息, 這個标簽,需要寫在<form:form> 标簽内生效.

5. 錯誤消息的國際化檔案 i18n.properties , 中文需要是 Unicode 編碼,使用工具轉碼.

√ 格式: 驗證規則.表單 modelAttribute 值.屬性名=消息資訊

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

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

5. 注解@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

6. SpingMVC 驗證時,會根據不同的驗證錯誤, 傳回對應的資訊

注解的結合使用

● 問題提出, age 沒有, 是空的,送出确是成功了

Spring MVC資料格式化與驗證以及國際化和中文亂碼處理
Spring MVC資料格式化與驗證以及國際化和中文亂碼處理

● 解決方案注解組合使用

使用@NotNull + @Range 組合使用解決

java複制代碼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 等不 能轉成數字的内容)

Spring MVC資料格式化與驗證以及國際化和中文亂碼處理

資料類型轉換校驗核心類-DataBinder

● DataBinder 工作機制-了解

圖例 Spring MVC 通過反射機制對目标方法進行解析,将請求消息綁定到處理方法的入參中。

資料綁定的核心部件是 DataBinder,運作機制如下

Spring MVC資料格式化與驗證以及國際化和中文亂碼處理

- Debug 一下 validate 得到驗證 errors

流程先進行資料類型的轉換如果發送錯誤直接放到BindingResult

在進行資料校驗如果出錯了就繼續放入

最後放到error和map中顯示輸出

Spring MVC資料格式化與驗證以及國際化和中文亂碼處理

取消某個屬性的綁定

說明

在預設情況下,表單送出的資料都會和 pojo 類型的 javabean 屬性綁定,如果程式員在開發中,希望取消某個屬性的綁定,也就是說,不希望接收到某個表單對應的屬性的值,則可以通過 @InitBinder 注解取消綁定.

1. 編寫一個方法, 使用@InitBinder 辨別的該方法,可以對 WebDataBinder 對象進行初始化。WebDataBinder 是 DataBinder 的子類,用于完成由表單字段到 JavaBean 屬性的綁定

2. @InitBinder 方法不能有傳回值,它必須聲明為 void。

3. @InitBinder 方法的參數通常是是 WebDataBinder

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

修改 MonsterHandler.java

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

Spring MVC資料格式化與驗證以及國際化和中文亂碼處理

中文亂碼處理

自定義中文亂碼過濾器

● 說明

當表單送出資料為中文時,會出現亂碼,我們來解決一下(提示:先恢複 name 屬性的綁定)

Spring MVC資料格式化與驗證以及國際化和中文亂碼處理
Spring MVC資料格式化與驗證以及國際化和中文亂碼處理

建立過濾器MyCharacterFilter

java複制代碼public class MyCharacterFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    @Override
    public void doFilter(ServletRequest servletRequest,
                         ServletResponse servletResponse,
                         FilterChain filterChain) throws IOException, ServletException {
        //這裡加入對編碼的處理
        servletRequest.setCharacterEncoding("utf-8");
        //放行請求,這個規則和前面講過的java web的過濾器一樣
        filterChain.doFilter(servletRequest, servletResponse);

    }

    @Override
    public void destroy() {

    }
}
           

配置 web.xml , 将該過濾器配置在最前

XML複制代碼    <!--配置進行中文亂碼的過濾器
    攔截所有請求,處理編碼, 提醒,把過濾器配置到web.xml前面
    -->    
    <filter>
        <filter-name>MyCharacterFilter</filter-name>
        <filter-class>com.wyxdu.web.filter.MyCharacterFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>MyCharacterFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
           

完成測試

Spring MVC資料格式化與驗證以及國際化和中文亂碼處理
Spring MVC資料格式化與驗證以及國際化和中文亂碼處理

Spring 提供的過濾器進行中文

XML複制代碼    <!--配置進行中文亂碼的過濾器
    攔截所有請求,處理編碼, 提醒,把過濾器配置到web.xml前面
    -->
<!--    <filter>-->
<!--        <filter-name>MyCharacterFilter</filter-name>-->
<!--        <filter-class>com.wyxdu.web.filter.MyCharacterFilter</filter-class>-->
<!--    </filter>-->
<!--    <filter-mapping>-->
<!--        <filter-name>MyCharacterFilter</filter-name>-->
<!--        <url-pattern>/*</url-pattern>-->
<!--    </filter-mapping>-->


    <!--配置Spring提供的過濾器,解決中文亂碼問題-->

    <filter>
        <filter-name>CharacterEncodingFilter</filter-name>
        <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
        <init-param>
            <param-name>encoding</param-name>
            <param-value>utf-8</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>CharacterEncodingFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
           

完成測試

Spring MVC資料格式化與驗證以及國際化和中文亂碼處理

Spring MVC資料格式化與驗證以及國際化和中文亂碼處理

繼續閱讀