<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ??碼云GVP開源項目 12k star Uniapp+ElementUI 功能強大 支持多語言、二開方便! 廣告
                # 第四章 Controller接口控制器詳解(6)——跟著開濤學SpringMVC ### [第一章 Web MVC簡介 —— 跟開濤學SpringMVC](http://jinnianshilongnian.iteye.com/blog/1593441 "第一章 Web MVC簡介 —— 跟開濤學SpringMVC") ### [第二章 Spring MVC入門 —— 跟開濤學SpringMVC](http://jinnianshilongnian.iteye.com/blog/1594806 "第二章 Spring MVC入門 —— 跟開濤學SpringMVC ") ### [第三章 DispatcherServlet詳解 ——跟開濤學SpringMVC](http://jinnianshilongnian.iteye.com/blog/1602617 "第三章 DispatcherServlet詳解 ——跟開濤學SpringMVC") ### [第四章 Controller接口控制器詳解(1)——跟著開濤學SpringMVC](http://jinnianshilongnian.iteye.com/blog/1608234 "第四章 Controller接口控制器詳解(1)——跟著開濤學SpringMVC") ### [第四章 Controller接口控制器詳解(2)——跟著開濤學SpringMVC](http://jinnianshilongnian.iteye.com/blog/1611743 "第四章 Controller接口控制器詳解(2)——跟著開濤學SpringMVC") ### [第四章 Controller接口控制器詳解(3)——跟著開濤學SpringMVC](http://jinnianshilongnian.iteye.com/blog/1622684 "第四章 Controller接口控制器詳解(3)——跟著開濤學SpringMVC") ### [第四章 Controller接口控制器詳解(4)——跟著開濤學SpringMVC](http://jinnianshilongnian.iteye.com/blog/1629956 "第四章 Controller接口控制器詳解(4)——跟著開濤學SpringMVC") ### [第四章 Controller接口控制器詳解(5)——跟著開濤學SpringMVC](http://jinnianshilongnian.iteye.com/blog/1630585 "第四章 Controller接口控制器詳解(5)——跟著開濤學SpringMVC") ### [第四章 Controller接口控制器詳解(6)——跟著開濤學SpringMVC](http://www.iteye.com/blogs/subjects/records/1594 "第四章 Controller接口控制器詳解(6)——跟著開濤學SpringMVC") ## 4.16、數據類型轉換和數據驗證 ![](https://box.kancloud.cn/2016-05-15_5737edd82363e.JPG) **流程:** 1、首先創建數據綁定器,在此此會創建ServletRequestDataBinder類的對象,并設置messageCodesResolver(錯誤碼解析器); 2、提供第一個擴展點,初始化數據綁定器,在此處我們可以覆蓋該方法注冊自定義的PropertyEditor(請求參數——&gt;命令對象屬性的轉換); 3、進行數據綁定,即請求參數——&gt;命令對象的綁定; 4、提供第二個擴展點,數據綁定完成后的擴展點,此處可以實現一些自定義的綁定動作; 5、驗證器對象的驗證,驗證器通過validators注入,如果驗證失敗,需要把錯誤信息放入Errors(此處使用BindException實現); 6、提供第三個擴展點,此處可以實現自定義的綁定/驗證邏輯; 7、將errors傳入功能處理方法進行處理,功能方法應該判斷該錯誤對象是否有錯誤進行相應的處理。 ### 4.16.1、數據類型轉換 請求參數(String)——&gt;命令對象屬性(可能是任意類型)的類型轉換,即數據綁定時的類型轉換,使用PropertyEditor實現綁定時的類型轉換。 **一、Spring內建的PropertyEditor如下所示:** | **類名** | **說明** | **默認是否注冊** | | --- | --- | --- | | ByteArrayPropertyEditor | String&lt;——&gt;byte[] | √ | | ClassEditor | String&lt;——&gt;Class當類沒有發現拋出`IllegalArgumentException` | √ | | CustomBooleanEditor | String&lt;——&gt;Booleantrue/yes/on/1轉換為true,false/no/off/0轉換為false | √ | | CustomCollectionEditor | 數組/Collection——&gt;Collection普通值——&gt;Collection(只包含一個對象)如String——&gt;Collection不允許Collection——&gt;String(單方向轉換) | √ | | CustomNumberEditor | String&lt;——&gt;Number(Integer、Long、Double) | √ | | FileEditor | String&lt;——&gt;File | √ | | InputStreamEditor | String——&gt;InputStream單向的,不能InputStream——&gt;String | √ | | LocaleEditor | String&lt;——&gt;Locale,(String的形式為[語言]_[國家]_[變量],這與Local對象的toString()方法得到的結果相同) | √ | | PatternEditor | String&lt;——&gt;Pattern | √ | | PropertiesEditor | String&lt;——&gt;java.lang.Properties | √ | | URLEditor | String&lt;——&gt;URL | √ | | StringTrimmerEditor | 一個用于trim 的 String類型的屬性編輯器如默認刪除兩邊的空格,charsToDelete屬性:可以設置為其他字符emptyAsNull屬性:將一個空字符串轉化為null值的選項。 | × | | CustomDateEditor | String&lt;——&gt;java.util.Date | × | **二、Spring內建的PropertyEditor支持的屬性(符合JavaBean規范)操作:** | **表達式** | **設值/取值說明** | | --- | --- | --- | | username | 屬性username設值方法setUsername()/取值方法getUsername() 或 isUsername() | | schooInfo.schoolType | 屬性schooInfo的嵌套屬性schoolType設值方法getSchooInfo().setSchoolType()/取值方法getSchooInfo().getSchoolType() | | hobbyList[0] | 屬性hobbyList的第一個元素索引屬性可能是一個數組、列表、其它天然有序的容器。 | | map[key] | 屬性map(java.util.Map類型)map中key對應的值 | **三、示例:** 接下來我們寫自定義的屬性編輯器進行數據綁定: **(1、模型對象:** ``` package cn.javass.chapter4.model; //省略import public class DataBinderTestModel { private String username; private boolean bool;//Boolean值測試 private SchoolInfoModel schooInfo; private List hobbyList;//集合測試,此處可以改為數組/Set進行測試 private Map map;//Map測試 private PhoneNumberModel phoneNumber;//String->自定義對象的轉換測試 private Date date;//日期類型測試 private UserState state;//String——>Enum類型轉換測試 //省略getter/setter } package cn.javass.chapter4.model; //如格式010-12345678 public class PhoneNumberModel { private String areaCode;//區號 private String phoneNumber;//電話號碼 //省略getter/setter } ``` **(2、PhoneNumber屬性編輯器** 前臺輸入如010-12345678自動轉換為PhoneNumberModel。 ``` package cn.javass.chapter4.web.controller.support.editor; //省略import public class PhoneNumberEditor extends PropertyEditorSupport { Pattern pattern = Pattern.compile("^(\\d{3,4})-(\\d{7,8})$"); @Override public void setAsText(String text) throws IllegalArgumentException { if(text == null || !StringUtils.hasLength(text)) { setValue(null); //如果沒值,設值為null } Matcher matcher = pattern.matcher(text); if(matcher.matches()) { PhoneNumberModel phoneNumber = new PhoneNumberModel(); phoneNumber.setAreaCode(matcher.group(1)); phoneNumber.setPhoneNumber(matcher.group(2)); setValue(phoneNumber); } else { throw new IllegalArgumentException(String.format("類型轉換失敗,需要格式[010-12345678],但格式是[%s]", text)); } } @Override public String getAsText() { PhoneNumberModel phoneNumber = ((PhoneNumberModel)getValue()); return phoneNumber == null ? "" : phoneNumber.getAreaCode() + "-" + phoneNumber.getPhoneNumber(); } } ``` **PropertyEditorSupport:**一個PropertyEditor的支持類; **setAsText:**表示將String——&gt;PhoneNumberModel,根據正則表達式進行轉換,如果轉換失敗拋出異常,則接下來的驗證器會進行驗證處理; **getAsText:**表示將PhoneNumberModel——&gt;String。 **(3、控制器** 需要在控制器注冊我們自定義的屬性編輯器。 此處我們使用AbstractCommandController,因為它繼承了BaseCommandController,擁有綁定流程。 ``` package cn.javass.chapter4.web.controller; //省略import public class DataBinderTestController extends AbstractCommandController { public DataBinderTestController() { setCommandClass(DataBinderTestModel.class); //設置命令對象 setCommandName("dataBinderTest");//設置命令對象的名字 } @Override protected ModelAndView handle(HttpServletRequest req, HttpServletResponse resp, Object command, BindException errors) throws Exception { //輸出command對象看看是否綁定正確 System.out.println(command); return new ModelAndView("bindAndValidate/success").addObject("dataBinderTest", command); } @Override protected void initBinder(HttpServletRequest request, ServletRequestDataBinder binder) throws Exception { super.initBinder(request, binder); //注冊自定義的屬性編輯器 //1、日期 DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); CustomDateEditor dateEditor = new CustomDateEditor(df, true); //表示如果命令對象有Date類型的屬性,將使用該屬性編輯器進行類型轉換 binder.registerCustomEditor(Date.class, dateEditor); //自定義的電話號碼編輯器 binder.registerCustomEditor(PhoneNumberModel.class, new PhoneNumberEditor()); } } ``` **initBinder:**第一個擴展點,初始化數據綁定器,在此處我們注冊了兩個屬性編輯器; **CustomDateEditor:**自定義的日期編輯器,用于在String&lt;——&gt;日期之間轉換; binder.registerCustomEditor(Date.**class**, dateEditor):表示如果命令對象是Date類型,則使用dateEditor進行類型轉換; **PhoneNumberEditor:**自定義的電話號碼屬性編輯器用于在String&lt;——&gt; PhoneNumberModel之間轉換; binder.registerCustomEditor(PhoneNumberModel.**class**,?**new**PhoneNumberEditor()):表示如果命令對象是PhoneNumberModel類型,則使用PhoneNumberEditor進行類型轉換; `**(4、spring配置文件chapter4-servlet.xml**` ``` <bean name="/dataBind" class="cn.javass.chapter4.web.controller.DataBinderTestController"/> ``` **(5、視圖頁面(WEB-INF/jsp/bindAndValidate/success.jsp)** ``` EL phoneNumber:${dataBinderTest.phoneNumber}<br/> EL state:${dataBinderTest.state}<br/> EL date:${dataBinderTest.date}<br/> ``` 視圖頁面的數據沒有預期被格式化,如何進行格式化顯示呢?請參考【第七章? 注解式控制器的數據驗證、類型轉換及格式化】。 **(6、測試:** **1、在瀏覽器地址欄輸入請求的URL,如** http://localhost:9080/springmvc-chapter4/dataBind?username=zhang&bool=yes&schooInfo.specialty=computer&hobbyList[0]=program&hobbyList[1]=music&map[key1]=value1&map[key2]=value2&phoneNumber=010-12345678&date=2012-3-18 16:48:48&state=blocked **2、控制器輸出的內容:** DataBinderTestModel [username=zhang, bool=true, schooInfo=SchoolInfoModel [schoolType=null, schoolName=null, specialty=computer], hobbyList=[program, music], map={key1=value1, key2=value2}, phoneNumber=PhoneNumberModel [areaCode=010, phoneNumber=12345678], date=Sun Mar 18 16:48:48 CST 2012, state=鎖定] 類型轉換如圖所示: ![](https://box.kancloud.cn/2016-05-15_5737edd8424b3.JPG) **四、注冊PropertyEditor** **1、使用WebDataBinder進行控制器級別注冊PropertyEditor(控制器獨享)** 如“【三、示例】”中所使用的方式,使用WebDataBinder注冊控制器級別的PropertyEditor,這種方式注冊的PropertyEditor只對當前控制器獨享,即其他的控制器不會自動注冊這個PropertyEditor,如果需要還需要再注冊一下。 **2、使用**`**WebBindingInitializer批量注冊**`**PropertyEditor** 如果想在多個控制器同時注冊多個相同的PropertyEditor時,可以考慮使用WebBindingInitializer。 示例: (1、實現WebBindingInitializer ``` package cn.javass.chapter4.web.controller.support.initializer; //省略import public class MyWebBindingInitializer implements WebBindingInitializer { @Override public void initBinder(WebDataBinder binder, WebRequest request) { //注冊自定義的屬性編輯器 //1、日期 DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); CustomDateEditor dateEditor = new CustomDateEditor(df, true); //表示如果命令對象有Date類型的屬性,將使用該屬性編輯器進行類型轉換 binder.registerCustomEditor(Date.class, dateEditor); //自定義的電話號碼編輯器 binder.registerCustomEditor(PhoneNumberModel.class, new PhoneNumberEditor()); } } ``` 通過實現WebBindingInitializer并通過binder注冊多個PropertyEditor。 (2、修改【三、示例】中的DataBinderTestController,注釋掉initBinder方法; (3、修改chapter4-servlet.xml配置文件: ``` <!-- 注冊WebBindingInitializer實現 --> <bean id="myWebBindingInitializer" class="cn.javass.chapter4.web.controller.support.initializer.MyWebBindingInitializer"/> <bean name="/dataBind" class="cn.javass.chapter4.web.controller.DataBinderTestController"> <!-- 注入WebBindingInitializer實現 --> <property name="webBindingInitializer" ref="myWebBindingInitializer"/> </bean> ``` (4、嘗試訪問“【三、示例】”中的測試URL即可成功。 使用WebBindingInitializer的好處是當你需要在多個控制器中需要同時使用多個相同的PropertyEditor可以在WebBindingInitializer實現中注冊,這樣只需要在控制器中注入WebBindingInitializer即可注入多個PropertyEditor。 **3、全局級別注冊PropertyEditor(全局共享)** 只需要將我們自定義的PropertyEditor放在和你的模型類同包下即可,且你的Editor命名規則必須是“模型類名Editor”,這樣Spring會自動使用標準JavaBean架構進行自動識別,如圖所示: ![](https://box.kancloud.cn/2016-05-15_5737edd85a7d3.JPG) 此時我們把“DataBinderTestController”的“binder.registerCustomEditor(PhoneNumberModel.class, new PhoneNumberEditor());”注釋掉,再嘗試訪問“【三、示例】”中的測試URL即可成功。 這種方式不僅僅在使用Spring時可用,在標準的JavaBean等環境都是可用的,可以認為是全局共享的(不僅僅是Spring環境)。 **PropertyEditor被限制為只能String&lt;——&gt;Object之間轉換,不能Object&lt;——&gt;Object,Spring3提供了更強大的類型轉換(Type**`**Conversion)支持,它可以在任意對象之間進行類型轉換,不僅僅是String**`**&lt;**`**——&gt;Object。**` 如果我在地址欄輸入錯誤的數據,即數據綁定失敗,Spring Web MVC該如何處理呢?如果我輸入的數據不合法呢?如用戶名輸入100個字符(超長了)那又該怎么處理呢?出錯了需要錯誤消息,那錯誤消息應該是硬編碼?還是可配置呢? 接下來我們來學習一下數據驗證器進行數據驗證吧。 [私塾在線學習網](http://sishuok.com/)原創內容([http://sishuok.com](http://sishuok.com/)) 原創內容,轉載請注明私塾在線【[http://sishuok.com/forum/blogPost/list/5677.html](http://sishuok.com/forum/blogPost/list/0/5514.html)】
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看