<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>

                合規國際互聯網加速 OSASE為企業客戶提供高速穩定SD-WAN國際加速解決方案。 廣告
                # 前言 public String method(Integer num, Date birth) { ... } Http請求傳遞的數據都是字符串String類型的,上面這個方法在Controller中定義,如果該方法對應的地址接收到到瀏覽器的請求的話,并且請求中含有num和birth參數,那么num會被自動轉換成Integer對象;birth會被自動轉為Date對象(Date轉換需要配置屬性編輯器)。 ![](http://7x2wh6.com1.z0.glb.clouddn.com/springmvc-databind-typeconvert01.jpg) 本章將分析這一原理,解釋SpringMVC是如何實現數據類型的轉換。 # 屬性編輯器介紹 在講解核心內容之前,我們先來了解一下Java中定義的屬性編輯器。 sun設計屬性編輯器主要是為IDE服務的,讓IDE能夠以可視化的方式設置JavaBean的屬性。 PropertyEditor是屬性編輯器的接口。 ![](http://7x2wh6.com1.z0.glb.clouddn.com/springmvc-databind-typeconvert02.png) 我們使用屬性編輯器一般都是將String對象轉換成我們需要的java對象而使用的。 有個方法setAsText很重要。 比如String對象"1"要使用屬性編輯器轉換成Integer對象,通過setAsText里Integer.parseInt(text)得到Integer對象,然后將Integer對象保存到屬性中。 它的基本實現類是PropertyEditorSupport,一般我們要編寫自定義的屬性編輯器只需要繼承這個類即可。 Spring中有很多自定義的屬性編輯器,都在spring-beans jar包下的org.springframework.beans.propertyeditors包里。 ![](http://7x2wh6.com1.z0.glb.clouddn.com/springmvc-databind-typeconvert03.png) CustomBooleanEditor繼承PropertyEditorSupport并重寫setAsText方法。 ![](http://7x2wh6.com1.z0.glb.clouddn.com/springmvc-databind-typeconvert04.png) # 重要接口和類介紹 剛剛分析了sun設計的屬性編輯器。 下面我們來看下Spring對這方面的設計。 1.**PropertyEditorRegistry接口** 封裝方法來給JavaBean注冊對應的屬性編輯器。 ![](http://7x2wh6.com1.z0.glb.clouddn.com/springmvc-databind-typeconvert05.png) 2.**PropertyEditorRegistrySupport:PropertyEditorRegistry接口的基礎實現類** ![](http://7x2wh6.com1.z0.glb.clouddn.com/springmvc-databind-typeconvert06.png) PropertyEditorRegistrySupport類有個createDefaultEditors方法,會創建默認的屬性編輯器。 ![](http://7x2wh6.com1.z0.glb.clouddn.com/springmvc-databind-typeconvert07.png) ![](http://7x2wh6.com1.z0.glb.clouddn.com/springmvc-databind-typeconvert08.png) 3.**TypeConverter接口** ![](http://7x2wh6.com1.z0.glb.clouddn.com/springmvc-databind-typeconvert09.png) 4.**TypeConverterSupport:TypeConverter基礎實現類,并繼承了PropertyEditorRegistrySupport** 有個屬性typeConverterDelegate,類型為TypeConverterDelegate,TypeConverterSupport將類型轉換委托給typeConverterDelegate操作。 5.**TypeConverterDelegate** 類型轉換委托類。具體的類型轉換操作由此類完成。 6.**SimpleTypeConverter** TypeConverterSupport的子類,使用了PropertyEditorRegistrySupport(父類TypeConverterSupport的父類PropertyEditorRegistrySupport)中定義的默認屬性編輯器。 7.**PropertyAccessor接口** 對類中屬性操作的接口。 8.**BeanWrapper接口** 繼承ConfigurablePropertyAccessor(繼承PropertyAccessor、PropertyEditorRegistry、TypeConverter接口)接口的操作Spring中JavaBean的核心接口。 9.**BeanWrapperImpl類** BeanWrapper接口的默認實現類,TypeConverterSupport是它的父類,可以進行類型轉換,可以進行屬性設置。 10.**DataBinder類** 實現PropertyEditorRegistry、TypeConverter的類。支持類型轉換,參數驗證,數據綁定等功能。 有個屬性SimpleTypeConverter,用來進行類型轉換操作。 11.**WebDataBinder** DataBinder的子類,主要是針對Web請求的數據綁定。 # 部分類和接口測試 由于BeanWrapper支持類型轉換,屬性設置。以BeanWrapper接口為例,做幾個測試,讓讀者對它們有更清晰的認識: 以TestModel這個JavaBean為例,屬性: private int age; private Date birth; private String name; private boolean good; private long times; 測試方法1: TestModel tm = new TestModel(); BeanWrapper bw = new BeanWrapperImpl(tm); bw.setPropertyValue("good", "on"); //bw.setPropertyValue("good", "1"); //bw.setPropertyValue("good", "true"); //bw.setPropertyValue("good", "yes"); System.out.println(tm); good是boolean屬性,使用BeanWrapperImpl設置屬性的時候,內部會使用類型轉換(父類TypeConverterSupport提供),將String類型轉換為boolean,CustomBooleanEditor對于String值是on,1,true,yes都會轉換為true,本章介紹PropertyEditorRegistrySupport的時候說明過,CustomBooleanEditor屬于默認的屬性編輯器。 測試方法2: TestModel tm = new TestModel(); BeanWrapperImpl bw = new BeanWrapperImpl(false); bw.setWrappedInstance(tm); bw.setPropertyValue("good", "1"); System.out.println(tm); 不使用默認的屬性編輯器進行類型轉換。 很明顯,這段代碼報錯了,沒有找到合適的屬性編輯,String類型不能作為boolean類型的值。 **錯誤信息:Failed to convert property value of type 'java.lang.String' to required type 'boolean' for property 'good'; ** 測試方法3: TestModel tm = new TestModel(); BeanWrapper bw = new BeanWrapperImpl(tm); bw.registerCustomEditor(Date.class, new CustomDateEditor(new SimpleDateFormat("yyyy-MM-dd"), true)); bw.setPropertyValue("birth", "1990-01-01"); System.out.println(tm); 默認屬性編輯器中并沒有日期類型的屬性編輯器,我們注冊一個Spring提供的CustomDateEditor屬性編輯器,對應Date對象,并且為空。有了CustomDateEditor,設置birth的時候會通過類型轉換自動轉化成Date對象。 關于其他屬性的設置,讀者自行測試吧。 # 源碼分析 在分析RequestParamMethodArgumentResolver處理請求參數之前,我們簡單回顧一下SpringMVC是如何對http請求進行處理的。 HandlerAdapter會對每個請求實例化一個ServletInvocableHandlerMethod對象進行處理,我們僅看下WebDataBinderFactory的構造過程。 WebDataBinderFactory接口是一個創建WebDataBinder的工廠接口。 ![](http://7x2wh6.com1.z0.glb.clouddn.com/springmvc-databind-typeconvert10.png) ![](http://7x2wh6.com1.z0.glb.clouddn.com/springmvc-databind-typeconvert11.png) ![](http://7x2wh6.com1.z0.glb.clouddn.com/springmvc-databind-typeconvert12.png) 以如下方法為例: public ModelAndView test(boolean b, ModelAndView view) { view.setViewName("test/test"); if(b) { view.addObject("attr", "b is true"); } else { view.addObject("attr", "b is false"); } return view; } 在[解析SpringMVC中Controller的方法中參數的工作原理](333548)中已經分析,boolean類型的參數會被RequestParamMethodArgumentResolver這個HandlerMethodArgumentResolver處理。 下面我們進入RequestParamMethodArgumentResolver看看是如何處理的。 RequestParamMethodArgumentResolver的resolveArgument方法是由它的父類AbstractNamedValueMethodArgumentResolver中定義的: ![](http://7x2wh6.com1.z0.glb.clouddn.com/springmvc-databind-typeconvert13.png) ServletRequestDataBinderFactory創建ExtendedServletRequestDataBinder。 ![](http://7x2wh6.com1.z0.glb.clouddn.com/springmvc-databind-typeconvert14.png) ExtendedServletRequestDataBinder屬于DataBinder的子類。 ![](http://7x2wh6.com1.z0.glb.clouddn.com/springmvc-databind-typeconvert15.png) 我們在介紹重要接口的時候說過DataBinder進行類型轉換的時候內部會使用SimpleTypeConverter進行數據轉換。 下面看看測試: ![](http://7x2wh6.com1.z0.glb.clouddn.com/springmvc-databind-typeconvert16.png) ![](http://7x2wh6.com1.z0.glb.clouddn.com/springmvc-databind-typeconvert17.png) ![](http://7x2wh6.com1.z0.glb.clouddn.com/springmvc-databind-typeconvert18.png) ![](http://7x2wh6.com1.z0.glb.clouddn.com/springmvc-databind-typeconvert19.png) CustomBooleanEditor處理ohmygod會拋出IllegalArgumentException。 最終被截獲處理成http 400錯誤。 ![](http://7x2wh6.com1.z0.glb.clouddn.com/springmvc-databind-typeconvert20.png) PS:以上例子boolean類型改成Boolean類型的話,不傳參數的話b就是null,我們解釋默認屬性編輯器的時候Boolean類型的參數是允許空的。但是boolean類型不傳參數的話,默認會是false,而不會拋出異常。 原因就是resolveArgument方法中handleNullValue處理null值,spring進行了特殊的處理,如果參數類型是boolean的話,取false。 讀者可以試試。 再看看個例子: public ModelAndView testObj(Employee e, ModelAndView view) { view.setViewName("test/test"); view.addObject("attr", e.toString()); return view; } 該方法會被ServletModelAttributeMethodProcessorr這個HandlerMethodArgumentResolver處理。 ServletModelAttributeMethodProcessorr的resolveArgument方法是由它的父類ModelAttributeMethodProcessor中定義的: ![](http://7x2wh6.com1.z0.glb.clouddn.com/springmvc-databind-typeconvert21.png) 這里WebDataBinder方法bind中會使用BeanWrapper構造對象,然后設置對應的屬性。BeanWrapper本章已介紹過。 ![](http://7x2wh6.com1.z0.glb.clouddn.com/springmvc-databind-typeconvert22.png) # 編寫自定義的屬性編輯器 Spring提供的編輯器肯定不會滿足我們日常開發的功能,因此開發自定義的屬性編輯器也是很有必要的。 下面我們就寫1個自定義的屬性編輯器。 public class CustomDeptEditor extends PropertyEditorSupport { @Override public void setAsText(String text) throws IllegalArgumentException { if(text.indexOf(",") > 0) { Dept dept = new Dept(); String[] arr = text.split(","); dept.setId(Integer.parseInt(arr[0])); dept.setName(arr[1]); setValue(dept); } else { throw new IllegalArgumentException("dept param is error"); } } } SpringMVC中使用自定義的屬性編輯器有3種方法: 1.Controller方法中添加@InitBinder注解的方法 @InitBinder public void initBinder(WebDataBinder binder) { binder.registerCustomEditor(Dept.class, new CustomDeptEditor()); } 2.實現WebBindingInitializer接口 public class MyWebBindingInitializer implements WebBindingInitializer { @Override public void initBinder(WebDataBinder binder, WebRequest request) { binder.registerCustomEditor(Dept.class, new CustomDeptEditor()); } } 之前分析源碼的時候,HandlerAdapter構造WebDataBinderFactory的時候,會傳遞HandlerAdapter的屬性webBindingInitializer。 因此,我們在配置文件中構造RequestMappingHandlerAdapter的時候傳入參數webBindingInitializer。 3.@ControllerAdvice注解 @ControllerAdvice public class InitBinderControllerAdvice { @InitBinder public void initBinder(WebDataBinder binder) { binder.registerCustomEditor(Dept.class, new CustomDeptEditor()); } } 加上ControllerAdvice別忘記配置文件component-scan需要掃描到這個類。 最終結果: ![](http://7x2wh6.com1.z0.glb.clouddn.com/springmvc-databind-typeconvert23.png) # 總結 分析了Spring的數據轉換功能,并解釋這個神奇的轉換功能是如何實現的,之后編寫了自定義的屬性編輯器。 大致講解了下Spring類型轉換中重要的類及接口。 # 參考資料 [http://jinnianshilongnian.iteye.com/blog/1866350](http://jinnianshilongnian.iteye.com/blog/1866350) [http://jinnianshilongnian.iteye.com/blog/1723270](http://jinnianshilongnian.iteye.com/blog/1723270) [http://www.iteye.com/topic/1123628](http://www.iteye.com/topic/1123628)
                  <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>

                              哎呀哎呀视频在线观看