一.SpringMVC表單標簽He處理靜態資源
1.Spring的表單標簽
通過SpringMVC的表單標簽可以實現將模型數據中的屬性和HTML表單元素相綁定,以實現表單數據更便捷編輯和表單值的回顯。
1.form標簽
- 一般情況下,通過GET請求獲取表單頁面,而通過POST請求提交表單頁面,因此獲取表單頁面和提交表單頁面的URL是相同的。只要滿足該最佳條件的契約,<form:form>標簽就無需通過action屬性指定表單提交的URL。
- 可以通過modelAttribute屬性指定綁定的模型屬性,若沒有指定該屬性,則默認從request域對象中獲取command的表單bean。如果該屬性值也不存在,則會發生錯誤。
- SpringMVC提供了多個表單組件標簽,如<form:input/>、<form:select/>等,用以 綁定表單字段的屬性值,它們的共有屬性如下:
- path:表單字段,對應html元素的name屬性,支持級聯屬性。
- htmlEscape:是否對表單值的HTML特殊字符進行轉換,默認值為true。
- CSSClass:表單組件對應的CSS樣式類名。
- cssErrorClass:表單組件的數據存在錯誤時,采取的CSS樣式。
- form:input、form:password、form:hidden、form:textarea:對應HTML表單的text、password、hidden、textarea標簽。
- from:radiobutton:單選框組件標簽,當表單bean對應的屬性值和value值相等時,單選框被選中。
- form:radiobuttons:單選框組標簽,用于構造多個單選框。
- items:可以是一個List、String[]或Map。
- itemValue:指定radio的value值。可以是集合中bean的一個屬性值。
- itemLabel:指定radio的label值。
- delimiter:多個單選框可以通過delimiter指定分隔符。
- form:checkbox:復選框組件,用于構造單個復選框。
- form:checkboxs:用于構造多個復選框。
- form:errors:顯示表單組件或數據校驗所對應的錯誤
2.處理靜態資源
- 優雅的Rest風格的資源URL不希望帶.html或.do等后綴。
- 若將DispatcherServlet請求映射配置為 /,則SpringMVC將捕獲WEB容器的所有請求,包括靜態資源的請求,SpringMVC會將它們當初一個普通請求處理,因找不到對應處理器將導致錯誤。
- 可以在SpringMVC的配置文件中配置<mvc:default-servlet-handler />的方式解決靜態資源的問題:
- <mvc:default-servlet-handler />將在SpringMVC上下文中定義一個DefaultServletHttpRequestHandler,它會對進入DispatcherServlet的請求進行篩查,如果發現是沒有經過映射的請求,就將該請求交由WEB應用服務器默認的Servlet處理。如果不是靜態資源的請求,才由DispatcherServlet繼續處理。
- 一般WEB應用服務器默認的Servlet的名稱都是default。若所使用的WEB服務器的默認Servlet名稱不對default,則需要通過default-servlet-name屬性顯示指定。
二.數據轉換
1.數據綁定流程
- SpringMVC主框架將ServletRequest對象及目標方法的入參實例傳遞給WebDataBinderFactory實例,以創建DataBinder實例對象。
- DataBinder調用裝配在SpringMVC上下文的ConversionService組件進行數據類型轉換、數據格式化工作。將Servlet中的請求信息填充到入參對象中。
- 進行Validator組件對已經綁定了請求消息的入參對象進行數據合法性校驗,并最終生成數據綁定結果BindingData對象。
- SpringMVC抽取BindingResult中的入參對象和校驗錯誤對象,將它們賦給處理方法的響應入參。
- SpringMVC通過反射機制對目標處理方法進行解析,將請求消息綁定到處理方法的入參中,數據綁定的核心部件是DataBinder。
2.數據轉換
- springMVC上下文內建了很多轉換器,可完成大多數Java類型的轉換工作。
- SpringMVC自帶的轉換器都在org.springframework.core.convert.support路徑下面。
3.自定義類型轉換器
- ConversionService是Spring類型轉換體系的核心接口。
- 可以利用ConversionServiceFactoryBean在Spring的IOC容器中定義一個ConversionService。Spring將自動識別出IOC容器中的ConversionService,并在Bean屬性配置及SpringMVC處理方法入參綁定等場合使用它進行數據的轉換。
- 可以通過ConversionServiceFactoryBean的converters屬性注冊自定義的類型轉換器。
<bean id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean">
<property name="converters">
<list>
<bean class="com.desperado.UserConverter"></bean>
</list>
</property>
</bean>
4.Spring支持的轉換器
- Spring定義了3種類型的轉換器接口,實現任意一個轉換器接口都可以作為自定義轉換器注冊到ConversionServiceFactoryBean中:
- Converter<S,T>:將S類型對象轉為T類型對象。
- ConverterFactory:將相同系列多個“同質”Converter封裝在一起。如果希望將一種類型的對象轉換為另一種類型及其子類的休息可使用該轉換器工廠類。
- GenericConverter:會根據源類對象及目標類對象所在的宿主類中的上下文信息進行類型轉換。
- <mvc:annotation-driver conversion-service="conversionService" />會將自定義的ConversionService注冊到SpringMVC上下文中。
<mvc:annotation-driver conversion-service="conversionService" />
<bean id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean">
<property name="converters">
<list>
<bean class="com.desperado.UserConverter"></bean>
</list>
</property>
</bean>
5.關于mvc:annotation-driver
- <mvc:annotation-driver />會自動注冊RequestMappingHandlerMapping、RequestMappingHandlerAdapter與ExceptionHandlerExceptionResolver這三個Bean。
- 還提供一下支持:
- 支持使用ConversionService實例對表單參數進行類型轉換。
- 支持完成@NumberFormat、@DateTimeFormat注解完成數據類型的格式化。
- 支持使用@Valid注解對JavaBean實例進行JSR303驗證。
- 支持使用@RequestBody和@ResponseBody注解。
6.@InitBinder
- 由@InitBinder標識的方法,可以對WebDataBinder對象進行初始化。WebDataBinder是DataBinder的子類,用于完成由表單字段到JavaBean屬性的綁定。
- @InitBinder方法不能有返回值,它必須聲明為void。
- @InitBinder方法的參數通常是WebDataBinder。
三.數據格式化
1.數據格式化
- 對屬性對象的輸入/輸出進行格式化。
- Spring在格式化模塊定義了一個實現ConversionService接口的FormattingConversionService實現類,因此它既具有類型轉換的功能,又擁有格式化的功能。
- FormattingConversionService擁有一個FormattingConversionServiceFactoryBean工廠類,后者用于在Spring上下文構造前者。
- FormattingConversionServiceFactoryBean內部注冊了:
- NumberFormatAnnotationFormatterFactory:支持對數字類型的屬性使用@NumberFormat注冊。
- JodaDataTimeFormatAnnotationFormatterFactory:支持對日期類型的屬性使用@DateTimeFormat注解。
- 裝配了FormattigConversionServiceFactoryBean后,就可以在SpringMVC入參綁定及模型數據輸出時使用注解驅動了。
- <mvn:annotation-driver />默認創建的ConversionService實例為FormattingConversionServiceFactoryBean。
2.日期轉換器
@DateTimeFormat注解可對java.util.Date
java.util.Calendar、java.long.Long時間類型進行標注。
- pattern屬性:類型為字符串。指定解析/格式化字段數據的模式,如“yyyy-MM-dd hh:mm:ss”
- iso屬性:類型為DateTimeFormat.ISO。指定解析/格式化字段數據的ISO模式,包括四種模式:ISO.NONE(默認,不使用),ISO.DATE(yyyy-MM-dd)、ISO.TIME(hh:mm:ss.SSSZ)、ISO.DATE_TIME(yyyy-MM-dd hh:mm:ss.SSSZ)
- style屬性:字符串類中。通過樣式指定日期時間的格式,由兩位字符組成,第一位表示日期的格式,第二位表示時間的格式:S:短日期/時間格式、M:中日期/時間格式、L:長日期/時間格式、F:完整日期/時間格式、-:忽略日期或事件格式。
3.數組格式化
@NumberFormat可對類似數字類型的屬性進行標注,它擁有兩個互斥的屬性:
- style:類型為NumberFormat.Style。用于指定樣式類型,包括三種:Style.NUMBER(正常數字類型)、Style.CURRENCY(貨幣類型)、Style.PERCENT(百分比類型)
- pattern:類型為String,自定義樣式,如pattern="#,###"
四.數據校驗
1.JSR 303
- JSR303是Java為Bean數據合法性校驗提供的標準框架,它已經包含在JavaEE6.0中。
- JSR303通過在Bean屬性上標注類似于@NotNull、@Max等標準的注解指定校驗標準,并通過標準的驗證接口對Bean進行驗證。
2.SpringMVC數據校驗
- Spring4.0擁有自己獨立的數據校驗框架,同時支持JSR303標準的校驗框架。
- Spring在進行數據綁定時,可同時調用校驗框架完成數據校驗工作。在SpringMVC中,可直接通過注解驅動的方式進行數據校驗。
- Spring的LocalValidatorFactoryBean,即可將其注入到需要數據校驗的Bean中,
- Spring本身并沒有提供JSR303的實現,索引必須將JSR303的實現者的jar包放到類路徑下。
- <mvc:annotation-driver />會默認裝配好一個LocalValidatorFactoryBean,通過在處理方法的入參上標注@Valid注解即可讓SpringMVC在完成數據綁定后執行數據校驗的工作。
- SpringMVC是通過對處理方法簽名的規約來保持校驗結果的:前一個表單/命令對象的校驗結果保存到稅后的入參中,這個保存校驗結果的入參必須是BindingResult或者Errors類型。
3.提示消息的國際化
每個屬性在數據綁定和數據校驗發送錯誤時,都會生成一個對應的FieldError對象。
當一個屬性檢驗失敗后,校驗框架會為該屬性生成4個消息代碼,這些代碼以校驗注解類名為前綴,結婚ModelAttribute、屬性名及屬性類型名生成多個對應的消息代碼。
當時用SpringMVC標簽顯示錯誤消息時,SpringMVC會查看WEB上下文是否裝配了對應的國際化消息,如果沒有,則顯示默認的錯誤消息,否則使用國際化消息。
若數據類型轉換或數據格式轉換時發生錯誤,或該有的參數不存在,或調用處理方法時發生錯誤,都會在隱含模型中創建錯誤消息。其錯誤代碼前綴說明如下:
-required:必要的參數不存在。
-typeMismatch:在數據綁定時,發生數據類型不匹配的問題。
-methodInvocation:SpringMVC在調用處理方法時發生了錯誤。注冊國際化資源文件
<bean id="messageSource"
class="org.springframework.context.support.ResourceBundleMessageSource">
<property name="basename" value="i18n"></property>
</bean>
五.處理JSON
- HttpMessageConverter<T>是Spring3.0新添加的一個接口,負責將請求信息轉換為一個對象(類型為T),將對象(類型為T)輸出為響應信息。
- HttpMessageConverter<T>接口定義的方法:
-Boolean canRead(Class<?> clazz,MediaType mediaType):指定轉換器可以讀取的對象類型,即轉換器是否可將請求信息轉換為clazz類型的對象,同時指定支持MIME類型。
-Boolean canWrite(Class<?> clazz,MediaType mediaType):指定轉換器是否可以clazz類型的對象寫到響應流中,響應流支持的媒體類型在MediaType中定義。
-List<MediaType> getSupportMediaType():該轉換器支持的媒體類型。
-T read(Class<? extends T> clazz,HttpInputMessage inputMessage):將請求信息流轉換為T類型的對象。
-void write(T t,MediaType contentType,HttpOutputMessage):將T類型的對象寫到響應流中,同時指定相應的媒體類型為contentType。
- HttpMessageConverter<T>的實現類
實現類 | 功能說明 |
---|---|
StringHttpMessageConverter | 將請求信息轉換為字符串 |
FormatHttpMessageConverter | 將表單數據讀取到MutilValueMap中 |
XmlAwardFormHttpMessageConverter | 擴展于FormHttpMessageConverter,如果部分表單屬性是XML數據,可用該轉換器進行讀取 |
ResourceHttpMessageConverter | 讀寫org.springframework.core.io.Resource對象 |
BufferedImageHttpMessageConverter | 讀寫BufferedImage對象 |
ByteArrayHttpMessageConverter | 讀取二進制數據 |
SourceHttpMessageConverter | 讀寫java.xml.transform.Source類型的數據 |
MarshallingHttpMessageConverter | 通過Spring的Marshaller和Unmarshaller讀寫XML消息 |
Jaxb2RootElementHttpMessageConverter | 通過JAXB2讀寫XML消息,將請求消息轉換到標注XmlRootElement和XmlType的類中 |
MappingJacksonHttpMessageConverter | 利用Jackson開源包的ObjectMapper讀寫JSON數據 |
RssChannelHttpMessageConverter | 能夠讀寫RSS種子消息 |
AtomFeedHttpMessageConverter | 和RssChannelMessageConverter能夠讀寫RSS種子消息 |
-
DispatcherServlet默認裝配RequestMappingHandlerAdapter,而RequestMappingHandlerAdapter默認裝配如下HttpMessageConverter:
- ByteArrayHttpMessageConnverter
- StringHttpMessageConverter
- ResourceHttpMessageConverter
- SourceHttpMessageConverter<T>
- AllEncompassingFormHttpMessageConverter
- Jaxb2RootElementHttpMessageConverter
-
加入Jackson jar包后,RequestMappingHandlerAdapter裝配的HttpMessageConverter如下:
- ByteArrayHttpMessageConnverter
- StringHttpMessageConverter
- ResourceHttpMessageConverter
- SourceHttpMessageConverter<T>
- AllEncompassingFormHttpMessageConverter
- Jaxb2RootElementHttpMessageConverter
- MappingJackson2HttpMessageConverter
使用HttpMessageConverter<T> 將請求信息轉化并綁定到處理方法的入參中或將響應結果轉為對應類型的響應信息,Spring提供了兩種途徑:
- 使用@RequestBody或@ResponseBody對處理方法進行標注。
- 使用HttpEntity<T>或ResponseEntity<T>作為處理方法的入參或返回值。當控制器處理方法使用到@RequestBody或@ResponseBody或者HttpEntity<T>或ResponseEntity<T>時,Spring首先根據請求頭或響應頭的Accept屬性選擇匹配的HttpMessageConverter,進而根據參數類型或泛型類型的過濾得到匹配的HttpMessageConverter,若找不到可用的HttpMessageConverter將報錯。
@RequestBody和@ResponseBody不需要成對出現。
六.國際化
1.國際化概述
- 默認情況下,SpringMVC根據Accept-Language參數判斷客戶端的本地化類型。
- 當接收到請求時,SpringMVC會在上下文中查找一個本地化解析器(LocalResolver),找到后使用它獲取請求所對應的本地化類型信息。
- SpringMVC還允許裝配一個動態更改本地化類型的攔截器,這樣通過指定一個請求參數就可以控制單個請求的本地化類型。
2.本地化解析器和本地化攔截器
AcceptHeaderLocalResolver:根據HTTP請求頭的Accept-Language參數確定本地化類型,如果沒有顯式定義本地化解析器,SpringMVC使用該解析器。
CookieLocalResolver:根據指定的Cookie值確定本地化類型。
SessionLocalResolver:根據Session中特定的屬性確定本地化類型。
LocalChangeInterceptor:從請求參數中獲取本次請求對應的本地化類型
<bean id="localeResolver"
class="org.springframework.web.servlet.i18n.SessionLocaleResolver">
</bean>
<mvc:interceptors>
<bean class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor"></bean>
</mvc:interceptors>