18.5.4ContentNegotiatingViewResolver

ContentNegotiatingViewResolver不会自己解析视图,而是委托给其他视图解析器,选择类似于客户端请求的视图。 有两种策略可以让客户从服务器请求表示:

  • 对每个资源使用不同的URI,通常在URI中使用不同的文件扩展名。 例如,URI http://www.example.com/users/fred.pdf请求用户fred的PDF表示,而http://www.example.com/users/fred.xml请求XML表示。

  • 为客户端使用相同的URI来定位资源,但是设置Accept HTTP请求头来列出它理解的媒体类型。 例如,http://www.example.com/users/fred的一个HTTP请求的Accept标头设置为application/pdf,请求用户fred的PDF表示,同时http://www.example.com/users/fred使用Accept头设置来text/xml请求XML表示。 这个策略被称为内容谈判

Accept头的一个问题是,不可能在HTML中的Web浏览器中设置它。 例如,在Firefox中,它被固定为:Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8因此,通常会看到使用 开发基于浏览器的Web应用程序时,每个表示的URI都是不同的。

为了支持资源的多重表示,Spring提供了ContentNegotiatingViewResolver来根据HTTP请求的文件扩展名或者Accept头来解析一个视图。ContentNegotiatingViewResolver本身并不执行视图解析,而是委托给你指定的视图解析器列表 bean属性ViewResolvers

ContentNegotiatingViewResolver通过将请求媒体类型与ViewResolver关联的View所支持的媒体类型(也称为Content-Type)进行比较来选择适当的View来处理请求。 具有兼容的Content-Type的列表中的第一个View将表示返回给客户端。 如果ViewResolver链无法提供兼容的视图,则会查看通过DefaultViews属性指定的视图列表。 后面的选项适用于可以呈现当前资源的适当表示的单例视图,而不管逻辑视图的名称如何。 Accept头可能包含通配符,例如text/*,在这种情况下,Content-Type为text/xmlView是兼容的匹配。

要支持基于文件扩展名的视图的自定义分辨率,请使用ContentNegotiationManager:请参见第18.16.6节“内容协商”

以下是ContentNegotiatingViewResolver的配置示例:

<bean class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver">
    <property name="viewResolvers">
        <list>
            <bean class="org.springframework.web.servlet.view.BeanNameViewResolver"/>
            <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
                <property name="prefix" value="/WEB-INF/jsp/"/>
                <property name="suffix" value=".jsp"/>
            </bean>
        </list>
    </property>
    <property name="defaultViews">
        <list>
            <bean class="org.springframework.web.servlet.view.json.MappingJackson2JsonView"/>
        </list>
    </property>
</bean>

<bean id="content" class="com.foo.samples.rest.SampleContentAtomView"/>

InternalResourceViewResolver处理视图名称和JSP页面的翻译,而BeanNameViewResolver则根据bean的名称返回一个视图。 (有关Spring如何查找和实例化视图的更多详细信息,请参阅“使用ViewResolver界面解析视图”。)在本例中,内容bean是从AbstractAtomFeedView继承的类,它返回Atom RSS提要。 有关创建Atom Feed表示的更多信息,请参阅Atom Views部分。

In the above configuration, if a request is made with an.htmlextension, the view resolver looks for a view that matches thetext/htmlmedia type. TheInternalResourceViewResolverprovides the matching view fortext/html. If the request is made with the file extension.atom, the view resolver looks for a view that matches theapplication/atom+xmlmedia type. This view is provided by theBeanNameViewResolverthat maps to theSampleContentAtomViewif the view name returned iscontent. If the request is made with the file extension.json, theMappingJackson2JsonViewinstance from theDefaultViewslist will be selected regardless of the view name. Alternatively, client requests can be made without a file extension but with theAcceptheader set to the preferred media-type, and the same resolution of request to views would occur.

在上面的配置中,如果使用.html扩展名进行请求,则视图解析器将查找与text/html媒体类型相匹配的视图。 InternalResourceViewResolver提供了匹配的视图fortext/html。 如果请求是使用文件扩展名.atom创建的,则视图解析器会查找与application/atom+xml媒体类型相匹配的视图。 如果返回的视图名称是内容,则此视图由映射到SampleContentAtomViewBeanNameViewResolver提供。 如果请求是使用文件扩展名.json创建的,则无论视图名称如何,都会选择DefaultViews列表中的MappingJackson2JsonView实例。 或者,客户端请求可以在没有文件扩展名的情况下进行,但将Accept头设置为首选的媒体类型,并且对视图的请求的分辨率也会发生。

如果“ContentNegotiatingViewResolver”的ViewResolver列表未被明确配置,它会自动使用应用程序上下文中定义的任何ViewResolvers。

下面显示了相应的控制器代码,该代码返回Atom RSS提要,其格式为http://localhost/content.atomhttp://localhost/content,并带有application/atom+xml的Accept头。

@Controller
public class ContentController {

    private List<SampleContent> contentList = new ArrayList<SampleContent>();

    @GetMapping("/content")
    public ModelAndView getContent() {
        ModelAndView mav = new ModelAndView();
        mav.setViewName("content");
        mav.addObject("sampleContentList", contentList);
        return mav;
    }

}

results matching ""

    No results matching ""