免费在线a视频-免费在线观看a视频-免费在线观看大片影视大全-免费在线观看的视频-色播丁香-色播基地

你竟然知道SpringMVC是如何完成類型轉換和數據綁定的嗎?

:2020年03月28日 Java面試那些事兒
分享到:

Http請求傳遞的數據都是字符串String類型的,上面這個方法在Controller中定義,如果該方法對應的地址接收到到瀏覽器的請求的話,并且請求中含有num和birth參數,那么num會被自動轉換成Integer對象;birt...

# 前言

SpringMVC是目前主流的Web MVC框架之一。 

public String method(Integer num, Date birth) {

...

}

Http請求傳遞的數據都是字符串String類型的,上面這個方法在Controller中定義,如果該方法對應的地址接收到到瀏覽器的請求的話,并且請求中含有num和birth參數,那么num會被自動轉換成Integer對象;birth會被自動轉為Date對象(Date轉換需要配置屬性編輯器)。

本文將分析這一原理,解釋SpringMVC是如何實現數據類型的轉換。

# 屬性編輯器介紹

在講解核心內容之前,我們先來了解一下Java中定義的屬性編輯器。

sun設計屬性編輯器主要是為IDE服務的,讓IDE能夠以可視化的方式設置JavaBean的屬性。

PropertyEditor是屬性編輯器的接口。

我們使用屬性編輯器一般都是將String對象轉換成我們需要的java對象而使用的。

有個方法setAsText很重要。比如String對象"1"要使用屬性編輯器轉換成Integer對象,通過setAsText里Integer.parseInt(text)得到Integer對象,然后將Integer對象保存到屬性中。

它的基本實現類是PropertyEditorSupport,一般我們要編寫自定義的屬性編輯器只需要繼承這個類即可。

Spring中有很多自定義的屬性編輯器,都在spring-beans jar包下的org.springframework.beans.propertyeditors包里。

CustomBooleanEditor繼承PropertyEditorSupport并重寫setAsText方法。

# 重要接口和類介紹

 剛剛分析了sun設計的屬性編輯器。下面我們來看下Spring對這方面的設計。

1.PropertyEditorRegistry接口

封裝方法來給JavaBean注冊對應的屬性編輯器。

2.PropertyEditorRegistrySupport:PropertyEditorRegistry接口的基礎實現類

PropertyEditorRegistrySupport類有個createDefaultEditors方法,會創建默認的屬性編輯器。

3.TypeConverter接口

類型轉換接口。通過該接口,可以將value轉換為requiredType類型的對象。

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對象。

關于其他屬性的設置,讀者自行測試吧。

# 源碼分析

本文所使用的Spring版本是4.0.2

在分析RequestParamMethodArgumentResolver處理請求參數之前,我們簡單回顧一下SpringMVC是如何對http請求進行處理的。

HandlerAdapter會對每個請求實例化一個ServletInvocableHandlerMethod對象進行處理,我們僅看下WebDataBinderFactory的構造過程。

WebDataBinderFactory接口是一個創建WebDataBinder的工廠接口。

以如下方法為例:

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;

}

boolean類型的參數會被RequestParamMethodArgumentResolver這個HandlerMethodArgumentResolver處理。

下面我們進入RequestParamMethodArgumentResolver看看是如何處理的。

RequestParamMethodArgumentResolver的resolveArgument方法是由它的父類AbstractNamedValueMethodArgumentResolver中定義的:

ServletRequestDataBinderFactory創建ExtendedServletRequestDataBinder。

ExtendedServletRequestDataBinder屬于DataBinder的子類。

我們在介紹重要接口的時候說過DataBinder進行類型轉換的時候內部會使用SimpleTypeConverter進行數據轉換。

下面看看測試:

CustomBooleanEditor處理ohmygod會拋出IllegalArgumentException。最終被截獲處理成http 400錯誤。

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中定義的:

 這里WebDataBinder方法bind中會使用BeanWrapper構造對象,然后設置對應的屬性。BeanWrapper本文已介紹過。

# 編寫自定義的屬性編輯器

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需要掃描到這個類。

最終結果:

# 總結

分析了Spring的數據轉換功能,并解釋這個神奇的轉換功能是如何實現的,之后編寫了自定義的屬性編輯器。

大致講解了下Spring類型轉換中重要的類及接口。

文章難免會出現錯誤,希望讀者能夠指出。

# 參考資料

  • http://jinnianshilongnian.iteye.com/blog/1866350

  • http://jinnianshilongnian.iteye.com/blog/1723270

  • http://www.iteye.com/topic/1123628

[我要糾錯]
文:王振袢&發表于江蘇
關鍵詞: 前言 SpringMVC 目前 流的 框架

來源:本文內容搜集或轉自各大網絡平臺,并已注明來源、出處,如果轉載侵犯您的版權或非授權發布,請聯系小編,我們會及時審核處理。
聲明:江蘇教育黃頁對文中觀點保持中立,對所包含內容的準確性、可靠性或者完整性不提供任何明示或暗示的保證,不對文章觀點負責,僅作分享之用,文章版權及插圖屬于原作者。

點個贊
0
踩一腳
0

您在閱讀:你竟然知道SpringMVC是如何完成類型轉換和數據綁定的嗎?

Copyright?2013-2024 JSedu114 All Rights Reserved. 江蘇教育信息綜合發布查詢平臺保留所有權利

蘇公網安備32010402000125 蘇ICP備14051488號-3技術支持:南京博盛藍睿網絡科技有限公司

南京思必達教育科技有限公司版權所有   百度統計

主站蜘蛛池模板: 天天射日日操 | 黄色小视频免费 | 欧美一卡二卡科技有限公司 | 国产粉嫩嫩00在线正在播放 | 中文字幕亚洲一区二区va在线 | 久久精品视屏 | 日韩美aaa特级毛片 日韩毛片免费在线观看 | 色www 永久免费网站 | 情人边吃奶边做好爽嗷嗷叫 | 欧美性天堂| 黄污视频在线 | 一区二区高清在线观看 | 国产免费黄视频 | 天天干天天操天天干 | 亚洲综合精品一区二区三区中文 | 亚洲欧洲免费视频 | 国产一级做a爱免费观看 | 欧美不卡视频在线 | 国产精品久久久久久久免费 | 最近免费字幕高清在线观看 | 手机在线一区二区三区 | 性欧美暴力猛交xxxxx高清 | 欧美另类jizzhd | 色婷婷影院在线视频免费播放 | 国产成人综合亚洲亚洲欧美 | 亚洲欧洲精品国产区 | 国产在线欧美日韩一区二区 | 蝌蚪网在线视频 | 欧美一区永久视频免费观看 | 最近2019中文字幕无吗 | 欧美日本一区 | 欧美中文字幕一区二区三区 | 黄色香蕉网 | 狠狠色狠狠色综合系列 | 色综合激情 | 久热re这里只有精品视频 | 亚洲色图图片 | 又黄又免费的网站 | 日本a一级片 | 欧美亚洲中日韩中文字幕在线 | 日韩精品免费视频 |
最熱文章
最新文章
  • 阿里云上云鉅惠,云產品享最低成本,有需要聯系,
  • 卡爾蔡司鏡片優惠店,鏡片價格低
  • 蘋果原裝手機殼