理论
public class ContentNegotiatingViewResolver extends WebApplicationObjectSupport implements ViewResolver, Ordered Implementation of ViewResolver that resolves a view based on the request file name or Accept header. The ContentNegotiatingViewResolver does not resolve views itself, but delegates to other ViewResolvers. By default, these other view resolvers are picked up automatically from the application context, though they can also be set explicitly by using the viewResolvers property. Note that in order for this view resolver to work properly, the order property needs to be set to a higher precedence than the others (the default is Ordered.HIGHEST_PRECEDENCE.) This view resolver uses the requested media type to select a suitable View for a request. This media type is determined by using the following criteria: If the requested path has a file extension and if the setFavorPathExtension(boolean) property is true, the mediaTypes property is inspected for a matching media type. If the request contains a parameter defining the extension and if the setFavorParameter(boolean) property is true, the mediaTypes property is inspected for a matching media type. The default name of the parameter is format and it can be configured using the parameterName property. If there is no match in the mediaTypes property and if the Java Activation Framework (JAF) is both enabled and present on the classpath, FileTypeMap.getContentType(String) is used instead. If the previous steps did not result in a media type, and ignoreAcceptHeader is false, the request Accept header is used. Once the requested media type has been determined, this resolver queries each delegate view resolver for a View and determines if the requested media type is compatible with the view's content type). The most compatible view is returned. Additionally, this view resolver exposes the defaultViews property, allowing you to override the views provided by the view resolvers. Note that these default views are offered as candicates, and still need have the content type requested (via file extension, parameter, or Accept header, described above). You can also set the default content type directly, which will be returned when the other mechanisms (Accept header, file extension or parameter) do not result in a match. For example, if the request path is /view.html, this view resolver will look for a view that has the text/html content type (based on the html file extension). A request for /view with a text/html request Accept header has the same result.
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:mvc="http://www.springframework.org/schema/mvc" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd"> <mvc:annotation-driven content-negotiation-manager="contentNegotiationManager"/> <mvc:view-controller path="/" view-name="index"/> <bean id="contentNegotiationManager" class="org.springframework.web.accept.ContentNegotiationManagerFactoryBean"> <property name="mediaTypes"> <value> html=text/html json=application/json </value> </property> <property name="defaultContentType" value="text/html"/> </bean> <bean class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver"> <property name="order" value="0"/> <property name="contentNegotiationManager" ref="contentNegotiationManager"/> <property name="viewResolvers"> <list> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/> <property name="prefix" value="/WEB-INF/jsp/"/> <property name="suffix" value=".jsp"></property> </bean> </list> </property> <property name="defaultViews"> <list> <bean class="com.alibaba.fastjson.support.spring.FastJsonJsonView"> <property name="charset" value="UTF-8"/> </bean> </list> </property> </bean> <bean class="com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter"/> </beans>
package com.doctor.springframework.web.view; import java.util.HashMap; import java.util.Map; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.servlet.ModelAndView; @Controller public class SimpleController { @RequestMapping({"/test.html","/test.json"}) public ModelAndView test() { Map<String, String> map = new HashMap<>(); map.put("test", "json"); map.put("test-html", "html"); map.put("what", "what"); ModelAndView modelAndView = new ModelAndView("/contentViewTest"); modelAndView.addObject(map); return modelAndView; } }
package com.doctor.springframework.web.view; import org.apache.http.client.fluent.Request; import org.apache.http.client.fluent.Response; import org.junit.After; import org.junit.Before; import org.junit.Test; import com.doctor.embeddedjetty.EmbeddedJettyServer3; /** * ContentNegotiatingViewResolverPractice 根据路径后缀,选择不同视图 * @author doctor * * @time 2015年1月7日 上午10:08:24 */ public class ContentNegotiatingViewResolverPractice2 { private EmbeddedJettyServer3 embeddedJettyServer; private int port; @Before public void init() throws Throwable { port = 8989; embeddedJettyServer = new EmbeddedJettyServer3(port,"/contentNegotiatingViewResolverPractice/webapp", SpringContextConfig.class, SpringMvcConfig2.class); embeddedJettyServer.start(); } @Test public void test() throws Throwable { Response response = Request.Get("http://localhost:8989/test.json").execute(); System.out.println(response.returnContent().asString()); response = Request.Get("http://localhost:8989/test.html").execute(); System.out.println(response.returnContent().asString()); response = Request.Get("http://localhost:8989").execute(); System.out.println(response.returnContent().asString()); } @After public void destroy() throws Throwable { embeddedJettyServer.stop(); } }
01-10 10:18:40.513 main INFO o.e.j.s.Server - Started @4908ms {"hashMap":{"test":"json","test-html":"html","what":"what"}} <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Insert title here</title> </head> <body> hello contentNegotiatingViewResolverTest </body> </html> <html> <body> <h2>Hello World! doctor</h2> </body> </html>