首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > VC/MFC >

Spring3.X @MVC - (7)Spring中强大的内容协商视图解析器

2013-07-01 
Spring3.X @MVC - (七)Spring中强大的内容协商视图解析器?? ? /bean??!-- ? ? Views mapped in views.p

Spring3.X @MVC - (七)Spring中强大的内容协商视图解析器

?

? ? </bean>?

?

<!-- ? ? Views mapped in views.properties (PDF, XLS classes, and others) ?-->

? ? <bean id="contentNegotiatingResolver"

? ? ? ? ? ? ? />

? ? ? ? ?<property name="mediaTypes">

? ? ? ? ? ? <map>

? ? ? ? ? ? ? ? ? <entry key="html" value="text/html"/>

? ? ? ? ? ? ? ? ? <entry key="pdf" value="application/pdf"/>

? ? ? ? ? ? ? ? ? <entry key="xsl" value="application/vnd.ms-excel"/>

? ? ? ? ? ? ? ? ? <entry key="xml" value="application/xml"/>

? ? ? ? ? ? ? ? ? <entry key="json" value="application/json"/>

? ? ? ? ? ? </map>

? ? ? ? </property>

? ? ?</bean>

?

? ? <bean id="resourceBundleResolver"

? ? ? ? value="views" />

? ? ? ? <property name="order" value="#{contentNegotiatingResolver.order+1}" />

? ? </bean>

?

? ? <bean id="secondaryResourceBundleResolver"

? ? ? ? value="secondaryviews" />

? ? ? ? <property name="order" value="#{resourceBundleResolver.order+1}" />

? ? </bean>

?

? ? <!-- Views mapped in JSPs under /WEB-INF/jsp -->?

?

? ? <bean id="internalResourceResolver"

? ? ? ? value="/WEB-INF/jsp/" />

? ? ? ? <property name="suffix" value=".jsp" />

? ? <property name="order" value="#{secondaryResourceBundleResolver.order+1}" />

?

? ? </bean>

?

1) 你可能发现了,这个程序清单中的解析器声明和前面的看到的不太相同,因为这里面使用Spring的EL表达式SpEL来指定视图解析器的优先顺序。在这个例子中,ContentNegotiatingViewResolver解析器得到了最高的优先权,它的order根据SpEL申明

#{T(org.springframework.core.Ordered).HIGHEST_PRECEDENCE赋值。后续的解析器Bean使用相似的SpEL声明决定order值----#{bean_name.order+1}.这使你可以使用相对的解析器order权重,代替硬编码值。

? ? ? ?

2) 观察ContentNegotiatingViewResolver解析器的配置,这个配置设置该解析器为所有解析器中的最高优先级别,这种设置其实是有必要的,也就是说,基本上来说,内容协商解析器的优先级应该是最高的。那么为什么内容协商解析器ContentNegotiatinViewResolver要具有最高的优先级呢?原因是该解析器其实不会解析视图,而是将它们委派给其他的视图解析器。看一个例子:

? ? ? ? ?我们假定Sping MVC的控制器接受/reserverationSummary.xml的请求,一旦处理器方法结束,它将控制器发送给名为reservation的逻辑视图。根据前面学的内容可知,当控制器处理结束后,将控制器发送给reservation的逻辑视图后,Spring MVC的解析器开始起作用,因为内容协商处理器的优先级最高,所以开始作用的就是ContentNegotiationViewResolver解析器。

? ? ? ? ContentNegotiatingViewResolver解析器首先根据如下原则确定请求的媒体类型

A)检查请求扩展名:根据ContentNegotiationViewResolver bean的MediaType段中指定的默认媒体类型(例如text/html)检查请求路径的扩展名(例如.html, .xml或.pdf)

B)进一步确定请求扩展名: 如果请求路径具有扩展名,但是在ContentNegotiatingViewResolver bean默认的mediaTypes段中找不到,就试图使用属于Java Activation Framework的FileTypeMap确定扩展名的媒体类型。

C)如果没有扩展名:如果请求路径中没有扩展名,使用请求的HTTP Accept头标。

? ? ? 根据上面的A)B) C)的阐述,对于/reservationSummary.xml上的请求,A)中可看出媒体类型为application/xml。但是,对于类似/reservationSummary这样的URL请求,媒体类型在C)之前还没有被确定。其实,HTTP Accept头标中包含类似Accept:text/html或者Accept:application/pdf这样的值,假如请求的URL中不存在扩展名,这些值帮助解析器确定请求者预期的媒体类型。

? ? ? 此时,ContentNegotiatingViewResolver解析器得到一个媒体类型application/xml和reservation的逻辑视图。根据这两个重要的信息,再其他解析器上进行一次循环(根据解析器的顺序),根据检测到的媒体类型(此处为application.xml)确定哪个视图与逻辑名称最为匹配。

? ? ? ?这个过程可以允许你拥有多个同名的逻辑视图,每个视图支持一种不同的媒体类型(例如HTML,PDF,XLS),然后由ContentNegotiatingViewResolver来解析最佳匹配。

? ? ? ?这就是ContentNegotiatingViewResolver的好处,它会使控制器的设计进一步简化了,因为再也没有必要用硬编码为某个媒体类型创建特定的逻辑视图(例如pdfReservation, xlsReservation, htmlReservation),而代之以单一的视图(reservation),让ContentNegotiatingViewResolver解析器确定最佳匹配。要么匹配reservation.pdf, reservation.html,reservation.xls,reservation.json,reserveration.jsp等。

即可以省掉很多代码:

model.addAttribute("reservations",reservations);

// Check request extension

/**

if(request.getServletPath().endsWith(".pdf")) {?

? ?// PDF extension

? ?// Return view pdfSummary. Via resolver the view

? ?// is mapped to the class PdfReservationSummary

? ?// as defined in views.properties

? ?return "pdfSummary";

} else if(request.getServletPath().endsWith(".xls")) {?

? ?// Excel extension

? ?// Return view xlsSummary. Via resolver the view

? ?// is mapped to the class ExcelReservationSummary

? ?// as defined in views.properties

? ?return "excelSummary";

} else {?

? ?// Any other extension return the file system view reservationSummary

? ?// Via resolver it will be mapped to /WEB-INF/jsp/reservationSummary.jsp

? ?return "reservationSummary";

? ?}*/

return "reservationSummary"; // 只需要这句代码就可。

?

? ? ? ?这个处理过程中,可能的处理过程如下:

A)如果确定媒体类型为application/pdf。如果具有最高优先级的解析器包含有逻辑视图reservation的映射,但是不支持application/pdf类型。那么也就不存在匹配,会继续在剩余的解析器上进心查询匹配。

B)如果确定媒体类型为application/pdf。如果具有最高优先级的解析器包含有逻辑视图reservation的映射,并且这个视图支持application/pdf类型,则匹配该解析器。

C)如果媒体类型确定为text/html,而此时如果有4个名为reservation的逻辑视图,但是如果此时映射到两个具有最高优先级的解析器的视图都不支持text/html。那么就会和剩下的包含reservation视图映射且支持text/html的解析器匹配。

?

? ? ? ? 总结:

1) 这个视图搜索过程会在应用中配置的所有解析器上进行。如果你不希望在ContentNegotiatingViewResolver解析器之外进行配置,也可以在ContentNegotiatingViewResolver bean内配置默认视图和解析器。

?

2)很明显使用视图内容协商处理器(ContentNegotiatingViewResolver)后,可以不用每个逻辑视图(a.html, b.pdf, c.xls)以及为同名的逻辑视图(a: a.html, a.pdf, a.xls, a.json)等找一个最佳的匹配。极大的简化了Spring的视图解析器的配置。

?

?

热点排行