一.SpringMVC表單標(biāo)簽He處理靜態(tài)資源
1.Spring的表單標(biāo)簽
通過SpringMVC的表單標(biāo)簽可以實(shí)現(xiàn)將模型數(shù)據(jù)中的屬性和HTML表單元素相綁定痘儡,以實(shí)現(xiàn)表單數(shù)據(jù)更便捷編輯和表單值的回顯辕万。
1.form標(biāo)簽
- 一般情況下,通過GET請求獲取表單頁面谤辜,而通過POST請求提交表單頁面蓄坏,因此獲取表單頁面和提交表單頁面的URL是相同的。只要滿足該最佳條件的契約丑念,<form:form>標(biāo)簽就無需通過action屬性指定表單提交的URL涡戳。
- 可以通過modelAttribute屬性指定綁定的模型屬性,若沒有指定該屬性脯倚,則默認(rèn)從request域?qū)ο笾蝎@取command的表單bean渔彰。如果該屬性值也不存在,則會(huì)發(fā)生錯(cuò)誤推正。
- SpringMVC提供了多個(gè)表單組件標(biāo)簽恍涂,如<form:input/>、<form:select/>等植榕,用以 綁定表單字段的屬性值再沧,它們的共有屬性如下:
- path:表單字段,對應(yīng)html元素的name屬性尊残,支持級(jí)聯(lián)屬性炒瘸。
- htmlEscape:是否對表單值的HTML特殊字符進(jìn)行轉(zhuǎn)換,默認(rèn)值為true寝衫。
- CSSClass:表單組件對應(yīng)的CSS樣式類名顷扩。
- cssErrorClass:表單組件的數(shù)據(jù)存在錯(cuò)誤時(shí),采取的CSS樣式慰毅。
- form:input隘截、form:password、form:hidden、form:textarea:對應(yīng)HTML表單的text婶芭、password东臀、hidden、textarea標(biāo)簽雕擂。
- from:radiobutton:單選框組件標(biāo)簽啡邑,當(dāng)表單bean對應(yīng)的屬性值和value值相等時(shí)贱勃,單選框被選中井赌。
- form:radiobuttons:單選框組標(biāo)簽,用于構(gòu)造多個(gè)單選框贵扰。
- items:可以是一個(gè)List仇穗、String[]或Map。
- itemValue:指定radio的value值戚绕∥谱可以是集合中bean的一個(gè)屬性值。
- itemLabel:指定radio的label值舞丛。
- delimiter:多個(gè)單選框可以通過delimiter指定分隔符耘子。
- form:checkbox:復(fù)選框組件,用于構(gòu)造單個(gè)復(fù)選框球切。
- form:checkboxs:用于構(gòu)造多個(gè)復(fù)選框谷誓。
- form:errors:顯示表單組件或數(shù)據(jù)校驗(yàn)所對應(yīng)的錯(cuò)誤
2.處理靜態(tài)資源
- 優(yōu)雅的Rest風(fēng)格的資源URL不希望帶.html或.do等后綴。
- 若將DispatcherServlet請求映射配置為 /,則SpringMVC將捕獲WEB容器的所有請求吨凑,包括靜態(tài)資源的請求捍歪,SpringMVC會(huì)將它們當(dāng)初一個(gè)普通請求處理,因找不到對應(yīng)處理器將導(dǎo)致錯(cuò)誤鸵钝。
- 可以在SpringMVC的配置文件中配置<mvc:default-servlet-handler />的方式解決靜態(tài)資源的問題:
- <mvc:default-servlet-handler />將在SpringMVC上下文中定義一個(gè)DefaultServletHttpRequestHandler糙臼,它會(huì)對進(jìn)入DispatcherServlet的請求進(jìn)行篩查,如果發(fā)現(xiàn)是沒有經(jīng)過映射的請求恩商,就將該請求交由WEB應(yīng)用服務(wù)器默認(rèn)的Servlet處理变逃。如果不是靜態(tài)資源的請求,才由DispatcherServlet繼續(xù)處理怠堪。
- 一般WEB應(yīng)用服務(wù)器默認(rèn)的Servlet的名稱都是default揽乱。若所使用的WEB服務(wù)器的默認(rèn)Servlet名稱不對default,則需要通過default-servlet-name屬性顯示指定研叫。
二.數(shù)據(jù)轉(zhuǎn)換
1.數(shù)據(jù)綁定流程
- SpringMVC主框架將ServletRequest對象及目標(biāo)方法的入?yún)?shí)例傳遞給WebDataBinderFactory實(shí)例锤窑,以創(chuàng)建DataBinder實(shí)例對象盖呼。
- DataBinder調(diào)用裝配在SpringMVC上下文的ConversionService組件進(jìn)行數(shù)據(jù)類型轉(zhuǎn)換免都、數(shù)據(jù)格式化工作崩侠。將Servlet中的請求信息填充到入?yún)ο笾小?/li>
- 進(jìn)行Validator組件對已經(jīng)綁定了請求消息的入?yún)ο筮M(jìn)行數(shù)據(jù)合法性校驗(yàn)炬灭,并最終生成數(shù)據(jù)綁定結(jié)果BindingData對象码撰。
- SpringMVC抽取BindingResult中的入?yún)ο蠛托r?yàn)錯(cuò)誤對象,將它們賦給處理方法的響應(yīng)入?yún)ⅰ?/li>
- SpringMVC通過反射機(jī)制對目標(biāo)處理方法進(jìn)行解析撵割,將請求消息綁定到處理方法的入?yún)⒅械煲耍瑪?shù)據(jù)綁定的核心部件是DataBinder。
2.數(shù)據(jù)轉(zhuǎn)換
- springMVC上下文內(nèi)建了很多轉(zhuǎn)換器嚷那,可完成大多數(shù)Java類型的轉(zhuǎn)換工作胞枕。
- SpringMVC自帶的轉(zhuǎn)換器都在org.springframework.core.convert.support路徑下面。
3.自定義類型轉(zhuǎn)換器
- ConversionService是Spring類型轉(zhuǎn)換體系的核心接口魏宽。
- 可以利用ConversionServiceFactoryBean在Spring的IOC容器中定義一個(gè)ConversionService腐泻。Spring將自動(dòng)識(shí)別出IOC容器中的ConversionService,并在Bean屬性配置及SpringMVC處理方法入?yún)⒔壎ǖ葓龊鲜褂盟M(jìn)行數(shù)據(jù)的轉(zhuǎn)換队询。
- 可以通過ConversionServiceFactoryBean的converters屬性注冊自定義的類型轉(zhuǎn)換器派桩。
<bean id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean">
<property name="converters">
<list>
<bean class="com.desperado.UserConverter"></bean>
</list>
</property>
</bean>
4.Spring支持的轉(zhuǎn)換器
- Spring定義了3種類型的轉(zhuǎn)換器接口,實(shí)現(xiàn)任意一個(gè)轉(zhuǎn)換器接口都可以作為自定義轉(zhuǎn)換器注冊到ConversionServiceFactoryBean中:
- Converter<S,T>:將S類型對象轉(zhuǎn)為T類型對象蚌斩。
- ConverterFactory:將相同系列多個(gè)“同質(zhì)”Converter封裝在一起铆惑。如果希望將一種類型的對象轉(zhuǎn)換為另一種類型及其子類的休息可使用該轉(zhuǎn)換器工廠類。
- GenericConverter:會(huì)根據(jù)源類對象及目標(biāo)類對象所在的宿主類中的上下文信息進(jìn)行類型轉(zhuǎn)換送膳。
- <mvc:annotation-driver conversion-service="conversionService" />會(huì)將自定義的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.關(guān)于mvc:annotation-driver
- <mvc:annotation-driver />會(huì)自動(dòng)注冊RequestMappingHandlerMapping、RequestMappingHandlerAdapter與ExceptionHandlerExceptionResolver這三個(gè)Bean叠聋。
- 還提供一下支持:
- 支持使用ConversionService實(shí)例對表單參數(shù)進(jìn)行類型轉(zhuǎn)換撕阎。
- 支持完成@NumberFormat、@DateTimeFormat注解完成數(shù)據(jù)類型的格式化晒奕。
- 支持使用@Valid注解對JavaBean實(shí)例進(jìn)行JSR303驗(yàn)證闻书。
- 支持使用@RequestBody和@ResponseBody注解。
6.@InitBinder
- 由@InitBinder標(biāo)識(shí)的方法脑慧,可以對WebDataBinder對象進(jìn)行初始化魄眉。WebDataBinder是DataBinder的子類,用于完成由表單字段到JavaBean屬性的綁定闷袒。
- @InitBinder方法不能有返回值坑律,它必須聲明為void。
- @InitBinder方法的參數(shù)通常是WebDataBinder囊骤。
三.數(shù)據(jù)格式化
1.數(shù)據(jù)格式化
- 對屬性對象的輸入/輸出進(jìn)行格式化晃择。
- Spring在格式化模塊定義了一個(gè)實(shí)現(xiàn)ConversionService接口的FormattingConversionService實(shí)現(xiàn)類,因此它既具有類型轉(zhuǎn)換的功能也物,又擁有格式化的功能宫屠。
- FormattingConversionService擁有一個(gè)FormattingConversionServiceFactoryBean工廠類,后者用于在Spring上下文構(gòu)造前者滑蚯。
- FormattingConversionServiceFactoryBean內(nèi)部注冊了:
- NumberFormatAnnotationFormatterFactory:支持對數(shù)字類型的屬性使用@NumberFormat注冊浪蹂。
- JodaDataTimeFormatAnnotationFormatterFactory:支持對日期類型的屬性使用@DateTimeFormat注解抵栈。
- 裝配了FormattigConversionServiceFactoryBean后,就可以在SpringMVC入?yún)⒔壎澳P蛿?shù)據(jù)輸出時(shí)使用注解驅(qū)動(dòng)了坤次。
- <mvn:annotation-driver />默認(rèn)創(chuàng)建的ConversionService實(shí)例為FormattingConversionServiceFactoryBean古劲。
2.日期轉(zhuǎn)換器
@DateTimeFormat注解可對java.util.Date
java.util.Calendar、java.long.Long時(shí)間類型進(jìn)行標(biāo)注缰猴。
- pattern屬性:類型為字符串产艾。指定解析/格式化字段數(shù)據(jù)的模式,如“yyyy-MM-dd hh:mm:ss”
- iso屬性:類型為DateTimeFormat.ISO滑绒。指定解析/格式化字段數(shù)據(jù)的ISO模式闷堡,包括四種模式:ISO.NONE(默認(rèn),不使用)蹬挤,ISO.DATE(yyyy-MM-dd)缚窿、ISO.TIME(hh:mm:ss.SSSZ)棘幸、ISO.DATE_TIME(yyyy-MM-dd hh:mm:ss.SSSZ)
- style屬性:字符串類中焰扳。通過樣式指定日期時(shí)間的格式,由兩位字符組成误续,第一位表示日期的格式吨悍,第二位表示時(shí)間的格式:S:短日期/時(shí)間格式、M:中日期/時(shí)間格式蹋嵌、L:長日期/時(shí)間格式育瓜、F:完整日期/時(shí)間格式、-:忽略日期或事件格式栽烂。
3.數(shù)組格式化
@NumberFormat可對類似數(shù)字類型的屬性進(jìn)行標(biāo)注躏仇,它擁有兩個(gè)互斥的屬性:
- style:類型為NumberFormat.Style。用于指定樣式類型腺办,包括三種:Style.NUMBER(正常數(shù)字類型)焰手、Style.CURRENCY(貨幣類型)、Style.PERCENT(百分比類型)
- pattern:類型為String怀喉,自定義樣式书妻,如pattern="#,###"
四.數(shù)據(jù)校驗(yàn)
1.JSR 303
- JSR303是Java為Bean數(shù)據(jù)合法性校驗(yàn)提供的標(biāo)準(zhǔn)框架,它已經(jīng)包含在JavaEE6.0中躬拢。
- JSR303通過在Bean屬性上標(biāo)注類似于@NotNull躲履、@Max等標(biāo)準(zhǔn)的注解指定校驗(yàn)標(biāo)準(zhǔn),并通過標(biāo)準(zhǔn)的驗(yàn)證接口對Bean進(jìn)行驗(yàn)證聊闯。
2.SpringMVC數(shù)據(jù)校驗(yàn)
- Spring4.0擁有自己獨(dú)立的數(shù)據(jù)校驗(yàn)框架工猜,同時(shí)支持JSR303標(biāo)準(zhǔn)的校驗(yàn)框架。
- Spring在進(jìn)行數(shù)據(jù)綁定時(shí)菱蔬,可同時(shí)調(diào)用校驗(yàn)框架完成數(shù)據(jù)校驗(yàn)工作篷帅。在SpringMVC中,可直接通過注解驅(qū)動(dòng)的方式進(jìn)行數(shù)據(jù)校驗(yàn)。
- Spring的LocalValidatorFactoryBean犹褒,即可將其注入到需要數(shù)據(jù)校驗(yàn)的Bean中抵窒,
- Spring本身并沒有提供JSR303的實(shí)現(xiàn),索引必須將JSR303的實(shí)現(xiàn)者的jar包放到類路徑下叠骑。
- <mvc:annotation-driver />會(huì)默認(rèn)裝配好一個(gè)LocalValidatorFactoryBean李皇,通過在處理方法的入?yún)⑸蠘?biāo)注@Valid注解即可讓SpringMVC在完成數(shù)據(jù)綁定后執(zhí)行數(shù)據(jù)校驗(yàn)的工作。
- SpringMVC是通過對處理方法簽名的規(guī)約來保持校驗(yàn)結(jié)果的:前一個(gè)表單/命令對象的校驗(yàn)結(jié)果保存到稅后的入?yún)⒅兄婕希@個(gè)保存校驗(yàn)結(jié)果的入?yún)⒈仨毷荁indingResult或者Errors類型掉房。
3.提示消息的國際化
每個(gè)屬性在數(shù)據(jù)綁定和數(shù)據(jù)校驗(yàn)發(fā)送錯(cuò)誤時(shí),都會(huì)生成一個(gè)對應(yīng)的FieldError對象慰丛。
當(dāng)一個(gè)屬性檢驗(yàn)失敗后卓囚,校驗(yàn)框架會(huì)為該屬性生成4個(gè)消息代碼,這些代碼以校驗(yàn)注解類名為前綴诅病,結(jié)婚ModelAttribute哪亿、屬性名及屬性類型名生成多個(gè)對應(yīng)的消息代碼。
當(dāng)時(shí)用SpringMVC標(biāo)簽顯示錯(cuò)誤消息時(shí)贤笆,SpringMVC會(huì)查看WEB上下文是否裝配了對應(yīng)的國際化消息蝇棉,如果沒有,則顯示默認(rèn)的錯(cuò)誤消息芥永,否則使用國際化消息篡殷。
若數(shù)據(jù)類型轉(zhuǎn)換或數(shù)據(jù)格式轉(zhuǎn)換時(shí)發(fā)生錯(cuò)誤,或該有的參數(shù)不存在埋涧,或調(diào)用處理方法時(shí)發(fā)生錯(cuò)誤板辽,都會(huì)在隱含模型中創(chuàng)建錯(cuò)誤消息。其錯(cuò)誤代碼前綴說明如下:
-required:必要的參數(shù)不存在棘催。
-typeMismatch:在數(shù)據(jù)綁定時(shí)劲弦,發(fā)生數(shù)據(jù)類型不匹配的問題。
-methodInvocation:SpringMVC在調(diào)用處理方法時(shí)發(fā)生了錯(cuò)誤巧鸭。注冊國際化資源文件
<bean id="messageSource"
class="org.springframework.context.support.ResourceBundleMessageSource">
<property name="basename" value="i18n"></property>
</bean>
五.處理JSON
- HttpMessageConverter<T>是Spring3.0新添加的一個(gè)接口瓶您,負(fù)責(zé)將請求信息轉(zhuǎn)換為一個(gè)對象(類型為T),將對象(類型為T)輸出為響應(yīng)信息纲仍。
- HttpMessageConverter<T>接口定義的方法:
-Boolean canRead(Class<?> clazz,MediaType mediaType):指定轉(zhuǎn)換器可以讀取的對象類型呀袱,即轉(zhuǎn)換器是否可將請求信息轉(zhuǎn)換為clazz類型的對象,同時(shí)指定支持MIME類型郑叠。
-Boolean canWrite(Class<?> clazz,MediaType mediaType):指定轉(zhuǎn)換器是否可以clazz類型的對象寫到響應(yīng)流中夜赵,響應(yīng)流支持的媒體類型在MediaType中定義。
-List<MediaType> getSupportMediaType():該轉(zhuǎn)換器支持的媒體類型乡革。
-T read(Class<? extends T> clazz,HttpInputMessage inputMessage):將請求信息流轉(zhuǎn)換為T類型的對象寇僧。
-void write(T t,MediaType contentType,HttpOutputMessage):將T類型的對象寫到響應(yīng)流中摊腋,同時(shí)指定相應(yīng)的媒體類型為contentType。
- HttpMessageConverter<T>的實(shí)現(xiàn)類
實(shí)現(xiàn)類 | 功能說明 |
---|---|
StringHttpMessageConverter | 將請求信息轉(zhuǎn)換為字符串 |
FormatHttpMessageConverter | 將表單數(shù)據(jù)讀取到MutilValueMap中 |
XmlAwardFormHttpMessageConverter | 擴(kuò)展于FormHttpMessageConverter嘁傀,如果部分表單屬性是XML數(shù)據(jù)兴蒸,可用該轉(zhuǎn)換器進(jìn)行讀取 |
ResourceHttpMessageConverter | 讀寫org.springframework.core.io.Resource對象 |
BufferedImageHttpMessageConverter | 讀寫B(tài)ufferedImage對象 |
ByteArrayHttpMessageConverter | 讀取二進(jìn)制數(shù)據(jù) |
SourceHttpMessageConverter | 讀寫java.xml.transform.Source類型的數(shù)據(jù) |
MarshallingHttpMessageConverter | 通過Spring的Marshaller和Unmarshaller讀寫XML消息 |
Jaxb2RootElementHttpMessageConverter | 通過JAXB2讀寫XML消息,將請求消息轉(zhuǎn)換到標(biāo)注XmlRootElement和XmlType的類中 |
MappingJacksonHttpMessageConverter | 利用Jackson開源包的ObjectMapper讀寫JSON數(shù)據(jù) |
RssChannelHttpMessageConverter | 能夠讀寫RSS種子消息 |
AtomFeedHttpMessageConverter | 和RssChannelMessageConverter能夠讀寫RSS種子消息 |
-
DispatcherServlet默認(rèn)裝配RequestMappingHandlerAdapter细办,而RequestMappingHandlerAdapter默認(rèn)裝配如下HttpMessageConverter:
- ByteArrayHttpMessageConnverter
- StringHttpMessageConverter
- ResourceHttpMessageConverter
- SourceHttpMessageConverter<T>
- AllEncompassingFormHttpMessageConverter
- Jaxb2RootElementHttpMessageConverter
-
加入Jackson jar包后橙凳,RequestMappingHandlerAdapter裝配的HttpMessageConverter如下:
- ByteArrayHttpMessageConnverter
- StringHttpMessageConverter
- ResourceHttpMessageConverter
- SourceHttpMessageConverter<T>
- AllEncompassingFormHttpMessageConverter
- Jaxb2RootElementHttpMessageConverter
- MappingJackson2HttpMessageConverter
使用HttpMessageConverter<T> 將請求信息轉(zhuǎn)化并綁定到處理方法的入?yún)⒅谢驅(qū)㈨憫?yīng)結(jié)果轉(zhuǎn)為對應(yīng)類型的響應(yīng)信息,Spring提供了兩種途徑:
- 使用@RequestBody或@ResponseBody對處理方法進(jìn)行標(biāo)注笑撞。
- 使用HttpEntity<T>或ResponseEntity<T>作為處理方法的入?yún)⒒蚍祷刂怠?/p>當(dāng)控制器處理方法使用到@RequestBody或@ResponseBody或者HttpEntity<T>或ResponseEntity<T>時(shí)岛啸,Spring首先根據(jù)請求頭或響應(yīng)頭的Accept屬性選擇匹配的HttpMessageConverter,進(jìn)而根據(jù)參數(shù)類型或泛型類型的過濾得到匹配的HttpMessageConverter茴肥,若找不到可用的HttpMessageConverter將報(bào)錯(cuò)坚踩。
@RequestBody和@ResponseBody不需要成對出現(xiàn)。
六.國際化
1.國際化概述
- 默認(rèn)情況下瓤狐,SpringMVC根據(jù)Accept-Language參數(shù)判斷客戶端的本地化類型瞬铸。
- 當(dāng)接收到請求時(shí),SpringMVC會(huì)在上下文中查找一個(gè)本地化解析器(LocalResolver)芬首,找到后使用它獲取請求所對應(yīng)的本地化類型信息赴捞。
- SpringMVC還允許裝配一個(gè)動(dòng)態(tài)更改本地化類型的攔截器,這樣通過指定一個(gè)請求參數(shù)就可以控制單個(gè)請求的本地化類型郁稍。
2.本地化解析器和本地化攔截器
AcceptHeaderLocalResolver:根據(jù)HTTP請求頭的Accept-Language參數(shù)確定本地化類型,如果沒有顯式定義本地化解析器胜宇,SpringMVC使用該解析器耀怜。
CookieLocalResolver:根據(jù)指定的Cookie值確定本地化類型。
SessionLocalResolver:根據(jù)Session中特定的屬性確定本地化類型桐愉。
LocalChangeInterceptor:從請求參數(shù)中獲取本次請求對應(yīng)的本地化類型
<bean id="localeResolver"
class="org.springframework.web.servlet.i18n.SessionLocaleResolver">
</bean>
<mvc:interceptors>
<bean class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor"></bean>
</mvc:interceptors>