首页 > 代码库 > spring mvc ContentNegotiatingViewResolver 根据路径后缀,选择不同视图

spring mvc ContentNegotiatingViewResolver 根据路径后缀,选择不同视图

理论

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.

spring mvc配置文件:

<?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=http://www.mamicode.com/"text/html"/>>
写个测试controller

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>


代码下载:https://github.com/doctorwho1986/doctor/blob/master/springmvc-practice/src/test/java/com/doctor/springframework/web/view/ContentNegotiatingViewResolverPractice2.java

spring mvc ContentNegotiatingViewResolver 根据路径后缀,选择不同视图