Spring MVC 混合使用多种视图技术

1.ContentNegotiatingViewResolver

Spring 最重要的一个新功能就是对 REST 编程风格的支持。REST 风格的应用对资源的 URL 定义有严格的要求:一个资源对象对应唯一的 URL。在前面的例子中,我们使用不同的视图显示用户列表,如果把“用户列表”看作一个资源,那么我们希望通过一个相同的 URL 访问这个资源,而不是使用不同的 URL 访问该资源的不同视图。

前面介绍了使用 HttpMessageConverter 对标注了 @ResponseBody 或返回值为 ResponseEntity 的处理器方法进行响应信息转换的内容,Spring MVC 可以根据请求报文头的 Accept 属性选择适合的 HttpMessageConverter 将处理方法的返回值以 XML、JSON 等不同形式输出响应。也就是说,调用者可以通过设置请求报文头的 Accept 值控制服务器端返回的数据格式,从而实现对同一资源采用相同 URL 的 REST 编程风格。

但是基于 HttpMessageConverter 的实现方式存在以下限制。

1)只能通过请求报文头的 Accept 值控制服务器端返回的数据格式。如果客户端是浏览器,那么,除非使用 AJAX,否则很难控制 Accept 报文头的值。一般情况下,该值是由浏览器自己决定的。

2)无法通过 URL 扩展名或请求参数控制服务器端的资源输出形式,因此无法将其对应一个 URL 发布出去。

3)如果希望使用 XML、JSON、一个网页等形式输出资源,则 HttpMessageConverter 很难达到要求。因为  HttpMessageConverter 很难调用一个视图对象渲染模型,它直接负责将资源输出为某一内容形式。

所以,如果希望将资源以 XML、JSON 等纯数据的格式输出,且不在意使用报文头控制资源输出,那么适合选择 HttpMessageConverter 实现方式。否则,建议采用 Spring MVC 的 ContentNegotiatingViewResolver 视图解析器,虽然它和 HttpMessageConverter 在功能上有一些重叠,但在使用上更加灵活。

ContentNegotiatmgViewResolver 名为“视图解析器”,但它并不是一个传统意义上的视图解析器,它像一个仲裁机构或一个代理人,根据请求信息从上下文中选择一个适合的视图解析器负责解析。因此,一般将 ContentNegotiatingViewResolver 的优先级设为最高,以保证优先调用 ContentNegotiatingViewResolver。

ContentNegotiatingViewResolver 根据请求所要求的 MIME 类型决定由哪个视图解析器负责处理,它按照如下方式工作。

1)如果其 favorPathExtension 属性设置为 true(默认为 true),则根据 URL 中的文件扩展名确定 MIME 类型(如 userList.xml,userList.json 等)。

2)如果其 favorParameter 属性设置为 true(默认为 false),则根据请求参数的值确定 MIME 类型。默认的请求参数是 format,可以通过 parameterName 属性指定一个自定义的参数。

3)如果还没有找到对应的 MIME 类型,且 Java Activation Framework(JAF)位于类路径下,则通过 JAF 的  FileTypeMap.geContentType(url) 方法对 URL 进行判断,以获取对应的 MIME 类型。

4)如果以上步骤都失败,且 ignoreAcceptHeader 属性设置为 false(默认为 false),则采用 Accept 请求报文头的值确定 MIME 类型。由于不同浏览器产生的 Accept 头都是不一样的,所以一般不建议采用 Accept 确定 MIME 类型。

 

2.使用同一 URL 获取不同形式的返回内容

假设希望使用以下 REST 风格的 URL 以不同的 MIME 格式获取相同的资源(用户列表)。

1)/user/showUserListMix.html:返回一个 HTML 页面显示的用户列表。

2)/user/showUserListMix.html?content=xml:返回 XML 格式的用户列表。

3)/user/showUserListMix.html?content=json:返回 JSON 格式的用户列表。

首先,在 UserController 中添加一个处理方法。

@RequestMapping(value = "/showUserListMix")
public String showUserListMix(ModelMap mm) {
    List<User> userList = new ArrayList<User>();
    //...
    mm.addAttribute("userList", userList);
    return "userListMix";
}

接着,在 smart-servlet.xml 中添加以下配置片段,配置一个 ContentNegotiafingVrewResolver。采用请求参数指定内容资源的返回类型,如下面代码所示。

<bean id="contentNegotiationManager"
    class="org.springframework.web.accept.ContentNegotiationManagerFactoryBean"
    p:ignoreAcceptHeader="true"
    p:favorPathExtension="false"
    p:favorParameter="true"
    p:parameterName="format"
    p:defaultContentType="text/html"><!-- ① 不支持扩展文件名,不支持Accept报文头,指定MIME类型 -->
    <property name="mediaTypes"><!-- 通过请求指定MIME类型,参数名为content,请求类型的参数值和MIME类型的映射列表-->
        <value>
            html=text/html
            xml=application/xml
            json=application/json
        </value>
    </property>
</bean>
<!-- 协商多种视图解析器 -->
<bean class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver" 
    p:order="0"><!-- ② -->
    <property name="contentNegotiationManager" ref="contentNegotiationManager"/>
    <property name="defaultViews">
        <list>
            <bean class="org.springframework.web.servlet.view.json.MappingJackson2JsonView"
                  p:modelKeys="userList"/><!-- ③ -->
            <bean class="org.springframework.web.servlet.view.xml.MarshallingView"
                  p:modelKey="userList" p:marshaller-ref="xmlMarshaller"/><!-- ④ -->
        </list>
    </property>
</bean>

<!-- 以下是上下文中已经配置的视图解析器 -->
<bean class="org.springframework.web.servlet.view.BeanNameViewResolver"
    p:order="10"/>
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"<!-- ⑤ -->
    p:order="100" p:viewClass="org.springframework.web.servlet.view.JstlView"
    p:prefix="/WEB-INF/views/" p:suffix=".jsp"/>

ContentNegotiatingViewResolver 会在上下文中查找和 MIME 类型匹配的视图解析器,并委托它们进行视图解析。这样通过 content 请求参数就可以控制资源的输出格式。

③处配置的是 JSON 视图对象,而④处配置的是 XML 视图对象,它们都是默认的候选视图对象,会覆盖对应视图解析器返回的视图对象。换句话说,当资源 URL 带 content=json 参数时,直接返回③处对应的视图对象:当资源 URL 带 content=xml 参数时,直接返回④处对应的视图对象;当资源 URL 带 content=html 参数时,由⑤处的

InternalResourceViewResolver 解析;当资源 URL 不带 content 参数时,由于已经通过 defaultContentType="text/html',指定了默认的 MIME 类型,因此也由⑤处的 InternalResourceViewResolver 解析。

转载于:https://www.cnblogs.com/jwen1994/p/11182837.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值