ContentNegotiatingViewResolver是 ViewResolver 使用所请求的媒体类型的一个实现(基于文件类型扩展,输出格式URL参数指定类型或接受报头)来选择一个合适的视图一个请求。ContentNegotiatingViewResolver本身并不解决视图,只不表示为其他的 ViewResolver,您可以配置来处理特定的视图(XML,JSON,PDF,XLS,HTML,..)。
这里需要使用到以下技术:
- Spring 4.0.6.RELEASE
- jackson-databind 2.4.1.3
- jackson-annotations 2.4.1
- lowagie itext 4.2.1
- Apache POI 3.10-beta2
- Maven 3
- JDK 1.6
- Tomcat 7.0.54
- Eclipse JUNO Service Release 2
我们现在就开始!
第1步:创建目录结构
第2步:用所需的依赖更新 pom.xml
<?xml version="1.0"?> <project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <modelVersion>4.0.0</modelVersion> <groupId>com.yiibai.springmvc</groupId> <artifactId>ContentNegotiatingViewResolver</artifactId> <packaging>war</packaging> <version>1.0.0</version> <name>Spring4MVCContentNegotiatingViewResolverExample</name> <properties> <springframework.version>4.0.6.RELEASE</springframework.version> </properties> <dependencies> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> <version>${springframework.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-web</artifactId> <version>${springframework.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>${springframework.version}</version> </dependency> <!-- Needed for XML View (with JAXB2) --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-oxm</artifactId> <version>${springframework.version}</version> </dependency> <!-- Needed for JSON View --> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>2.4.1.3</version> </dependency> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-annotations</artifactId> <version>2.4.1</version> </dependency> <!-- Needed for PDF View --> <dependency> <groupId>com.lowagie</groupId> <artifactId>itext</artifactId> <version>4.2.1</version> </dependency> <!-- Needed for XLS View --> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi</artifactId> <version>3.10-beta2</version> </dependency> <!-- Servlet dependencies --> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>3.1.0</version> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>jstl</artifactId> <version>1.2</version> </dependency> <dependency> <groupId>javax.servlet.jsp</groupId> <artifactId>javax.servlet.jsp-api</artifactId> <version>2.3.1</version> </dependency> </dependencies> <build> <pluginManagement> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-war-plugin</artifactId> <version>2.4</version> <configuration> <warSourceDirectory>src/main/webapp</warSourceDirectory> <warName>ContentNegotiatingViewResolver</warName> <failOnMissingWebXml>false</failOnMissingWebXml> </configuration> </plugin> </plugins> </pluginManagement> <finalName>ContentNegotiatingViewResolver</finalName> </build> </project> %uA0
上面解析 PDF 的依赖库有点问题,可修改为以下测试构建就没有问题:
<dependency> <groupId>com.lowagie</groupId> <artifactId>itext</artifactId> <version>2.1.7</version> <scope>compile</scope> </dependency>
spring-oxm是为了支持XML输出生成(使用JAXB2)。%uA0jackson-databind%uA0&jackson-annotations%uA0提供JSON输出支持。iText的提供PDF生成库,支持PDF输出。%uA0Apache%uA0POI将有助于产生XLS输出格式。
第3步:创建Spring配置文件类
com.yiibai.springmvc.configuration.AppConfig
package com.yiibai.springmvc.configuration import java.util.ArrayList import java.util.List import org.springframework.context.annotation.Bean import org.springframework.context.annotation.ComponentScan import org.springframework.context.annotation.Configuration import org.springframework.http.MediaType import org.springframework.oxm.jaxb.Jaxb2Marshaller import org.springframework.web.accept.ContentNegotiationManager import org.springframework.web.servlet.ViewResolver import org.springframework.web.servlet.config.annotation.ContentNegotiationConfigurer import org.springframework.web.servlet.config.annotation.EnableWebMvc import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter import org.springframework.web.servlet.view.ContentNegotiatingViewResolver import org.springframework.web.servlet.view.InternalResourceViewResolver import org.springframework.web.servlet.view.JstlView import com.yiibai.springmvc.model.Pizza import com.yiibai.springmvc.viewresolver.ExcelViewResolver import com.yiibai.springmvc.viewresolver.JsonViewResolver import com.yiibai.springmvc.viewresolver.Jaxb2MarshallingXmlViewResolver import com.yiibai.springmvc.viewresolver.PdfViewResolver @Configuration @EnableWebMvc @ComponentScan(basePackages = "com.yiibai.springmvc") public class AppConfig extends WebMvcConfigurerAdapter { /* * Configure ContentNegotiationManager */ @Override public void configureContentNegotiation(ContentNegotiationConfigurer configurer) { configurer.ignoreAcceptHeader(true).defaultContentType( MediaType.TEXT_HTML) } /* * Configure ContentNegotiatingViewResolver */ @Bean public ViewResolver contentNegotiatingViewResolver(ContentNegotiationManager manager) { ContentNegotiatingViewResolver resolver = new ContentNegotiatingViewResolver() resolver.setContentNegotiationManager(manager) // Define all possible view resolvers List<ViewResolver> resolvers = new ArrayList<ViewResolver>() resolvers.add(jaxb2MarshallingXmlViewResolver()) resolvers.add(jsonViewResolver()) resolvers.add(jspViewResolver()) resolvers.add(pdfViewResolver()) resolvers.add(excelViewResolver()) resolver.setViewResolvers(resolvers) return resolver } /* * Configure View resolver to provide XML output Uses JAXB2 marshaller to * marshall/unmarshall POJO&aposs (with JAXB annotations) to XML */ @Bean public ViewResolver jaxb2MarshallingXmlViewResolver() { Jaxb2Marshaller marshaller = new Jaxb2Marshaller() marshaller.setClassesToBeBound(Pizza.class) return new Jaxb2MarshallingXmlViewResolver(marshaller) } /* * Configure View resolver to provide JSON output using JACKSON library to * convert object in JSON format. */ @Bean public ViewResolver jsonViewResolver() { return new JsonViewResolver() } /* * Configure View resolver to provide PDF output using lowagie pdf library to * generate PDF output for an object content */ @Bean public ViewResolver pdfViewResolver() { return new PdfViewResolver() } /* * Configure View resolver to provide XLS output using Apache POI library to * generate XLS output for an object content */ @Bean public ViewResolver excelViewResolver() { return new ExcelViewResolver() } /* * Configure View resolver to provide HTML output This is the default format * in absence of any type suffix. */ @Bean public ViewResolver jspViewResolver() { InternalResourceViewResolver viewResolver = new InternalResourceViewResolver() viewResolver.setViewClass(JstlView.class) viewResolver.setPrefix("/WEB-INF/views/") viewResolver.setSuffix(".jsp") return viewResolver } }
第一步是建立它用于通过委托给ContentNegotiationManager,以确定所请求的媒体类型的请求是%uA0ContentNegotiationStrategy%uA0列表的一个实例。默认情况下PathExtensionContentNegotiationStrategy被查询(使用URL扩展名,例如. .xls, .pdf,.json.),接着ParameterContentNegotiationStrategy(使用请求参数%uA0‘format=xls’,例如),其次是HeaderContentNegotiationStrategy(使用HTTP接受头)。
public void configureContentNegotiation(ContentNegotiationConfigurer configurer) { configurer.ignoreAcceptHeader(true).defaultContentType( MediaType.TEXT_HTML) } %uA0
在我们的例子中,我们将使用URL扩展名来帮助确定媒体类型。此外,我们还设置默认介质类型TEXT_HTML在没有文件扩展名或当文件类型是未知时,这意味着JSP视图解析器将被用于在没有[known]%uA0URL扩展中。
<%@ page language="java" contentType="text/html charset=utf-8" pageEncoding="utf-8"%> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <html> <head> <meta http-equiv="Content-Type" content="text/html charset=utf-8"> <title>Pizza JSP View</title> </head> <body> <table border="1"> <tr> <td>NAME</td> <td>Flavor</td> <td>Toppings</td> </tr> <tr> <td>${pizza.name}</td> <td>${pizza.flavor}</td> <td> <c:forEach var="item" items="${pizza.toppings}"> <c:out value="${item}"/>&nbsp </c:forEach> </td> </tr> </table> </body> </html>
public ViewResolver contentNegotiatingViewResolver(ContentNegotiationManager manager) { ContentNegotiatingViewResolver resolver = new ContentNegotiatingViewResolver() resolver.setContentNegotiationManager(manager) // Define all possible view resolvers List<ViewResolver> resolvers = new ArrayList<ViewResolver>() resolvers.add(jaxb2MarshallingXmlViewResolver()) resolvers.add(jsonViewResolver()) resolvers.add(jspViewResolver()) resolvers.add(pdfViewResolver()) resolvers.add(excelViewResolver()) resolver.setViewResolvers(resolvers) return resolver }
第4步:创建不同的视图解析器
XML View Resolver:
com.yiibai.springmvc.viewresolver.Jaxb2MarshallingXmlViewResolver
package com.yiiibai.springmvc.viewresolver import java.util.Locale import org.springframework.oxm.Marshaller import org.springframework.web.servlet.View import org.springframework.web.servlet.ViewResolver import org.springframework.web.servlet.view.xml.MarshallingView public class Jaxb2MarshallingXmlViewResolver implements ViewResolver { private Marshaller marshaller public Jaxb2MarshallingXmlViewResolver(Marshaller marshaller) { this.marshaller = marshaller } @Override public View resolveViewName(String viewName, Locale locale) throws Exception { MarshallingView view = new MarshallingView() view.setMarshaller(marshaller) return view } }
com.yiibai.springmvc.model.Pizza
package com.yiibai.springmvc.model import java.util.ArrayList import java.util.List import javax.xml.bind.annotation.XmlElement import javax.xml.bind.annotation.XmlRootElement @XmlRootElement(name = "pizza") public class Pizza { private String name private String flavor private List<String> toppings = new ArrayList<String>() public Pizza(){ } public Pizza(String name){ this.name = name this.flavor = "spicy" this.toppings.add("Cheese") this.toppings.add("bakon") } @XmlElement public void setName(String name) { this.name = name } public String getName() { return name } @XmlElement public void setFlavor(String flavor) { this.flavor = flavor } public String getFlavor() { return flavor } public List<String> getToppings() { return toppings } @XmlElement public void setToppings(List<String> toppings) { this.toppings = toppings } }
JSON View Resolver:
com.yiibai.springmvc.viewresolver.JsonViewResolver
package com.yiibai.springmvc.viewresolver import java.util.Locale import org.springframework.web.servlet.View import org.springframework.web.servlet.ViewResolver import org.springframework.web.servlet.view.json.MappingJackson2JsonView public class JsonViewResolver implements ViewResolver{ @Override public View resolveViewName(String viewName, Locale locale) throws Exception { MappingJackson2JsonView view = new MappingJackson2JsonView() view.setPrettyPrint(true) return view } }
PDF View Resolver:
com.yiibai.springmvc.viewresolver.PdfView
package com.yiibai.springmvc.viewresolver import java.awt.Color import java.util.Map import javax.servlet.http.HttpServletRequest import javax.servlet.http.HttpServletResponse import org.springframework.web.servlet.view.document.AbstractPdfView import com.lowagie.text.Document import com.lowagie.text.Element import com.lowagie.text.pdf.PdfPTable import com.lowagie.text.pdf.PdfWriter import com.yiibai.springmvc.model.Pizza public class PdfView extends AbstractPdfView { @Override protected void buildPdfDocument(Map<String, Object> model, Document document, PdfWriter writer, HttpServletRequest request, HttpServletResponse response) throws Exception { Pizza pizza = (Pizza) model.get("pizza") PdfPTable table = new PdfPTable(3) table.getDefaultCell().setHorizontalAlignment(Element.ALIGN_CENTER) table.getDefaultCell().setVerticalAlignment(Element.ALIGN_MIDDLE) table.getDefaultCell().setBackgroundColor(Color.lightGray) table.addCell("Name") table.addCell("Flavor") table.addCell("Toppings") table.addCell(pizza.getName()) table.addCell(pizza.getFlavor()) StringBuffer toppings = new StringBuffer("") for (String topping : pizza.getToppings()) { toppings.append(topping) toppings.append(" ") } table.addCell(toppings.toString()) document.add(table) } }
com.yiibai.springmvc.viewresolver.PdfViewResolver类代码:
package com.yiibai.springmvc.viewresolver import java.util.Locale import org.springframework.web.servlet.View import org.springframework.web.servlet.ViewResolver public class PdfViewResolver implements ViewResolver{ @Override public View resolveViewName(String viewName, Locale locale) throws Exception { PdfView view = new PdfView() return view } }
XLS View Resolver:
com.yiibai.springmvc.viewresolver.ExcelView
package com.yiibai.springmvc.viewresolver import java.util.Map import javax.servlet.http.HttpServletRequest import javax.servlet.http.HttpServletResponse import org.apache.poi.hssf.usermodel.HSSFWorkbook import org.apache.poi.ss.usermodel.Cell import org.apache.poi.ss.usermodel.CellStyle import org.apache.poi.ss.usermodel.IndexedColors import org.apache.poi.ss.usermodel.Row import org.apache.poi.ss.usermodel.Sheet import org.springframework.web.servlet.view.document.AbstractExcelView import com.yiibai.springmvc.model.Pizza public class ExcelView extends AbstractExcelView { @Override protected void buildExcelDocument(Map<String, Object> model, HSSFWorkbook workbook, HttpServletRequest request, HttpServletResponse response) throws Exception { Pizza pizza = (Pizza) model.get("pizza") Sheet sheet = workbook.createSheet("sheet 1") CellStyle style = workbook.createCellStyle() style.setFillForegroundColor(IndexedColors.GREY_40_PERCENT.index) style.setFillPattern(CellStyle.SOLID_FOREGROUND) style.setAlignment(CellStyle.ALIGN_CENTER) Row row = null Cell cell = null int rowCount = 0 int colCount = 0 // Create header cells row = sheet.createRow(rowCount++) cell = row.createCell(colCount++) cell.setCellStyle(style) cell.setCellValue("Name") cell = row.createCell(colCount++) cell.setCellStyle(style) cell.setCellValue("Flavor") cell = row.createCell(colCount++) cell.setCellStyle(style) cell.setCellValue("Toppings") // Create data cells row = sheet.createRow(rowCount++) colCount = 0 row.createCell(colCount++).setCellValue(pizza.getName()) row.createCell(colCount++).setCellValue(pizza.getFlavor()) StringBuffer toppings = new StringBuffer("") for (String topping : pizza.getToppings()) { toppings.append(topping) toppings.append(" ") } row.createCell(colCount++).setCellValue(toppings.toString()) for (int i = 0 i < 3 i++) sheet.autoSizeColumn(i, true) } }
com.yiibai.springmvc.viewresolver.ExcelViewResolver
package com.yiibai.springmvc.viewresolver import java.util.Locale import org.springframework.web.servlet.View import org.springframework.web.servlet.ViewResolver public class ExcelViewResolver implements ViewResolver{ @Override public View resolveViewName(String viewName, Locale locale) throws Exception { ExcelView view = new ExcelView() return view } }
第5步:创建控制器类
com.yiibai.springmvc.controller.AppController
package com.yiibai.springmvc.controller import org.springframework.stereotype.Controller import org.springframework.ui.ModelMap import org.springframework.web.bind.annotation.PathVariable import org.springframework.web.bind.annotation.RequestMapping import org.springframework.web.bind.annotation.RequestMethod import com.yiibai.springmvc.model.Pizza @Controller public class AppController { @RequestMapping(value="/pizzavalley/{pizzaName}", method = RequestMethod.GET) public String getPizza(@PathVariable String pizzaName, ModelMap model) { Pizza pizza = new Pizza(pizzaName) model.addAttribute("pizza", pizza) return "pizza" } }
第6步:创建初始化类
添加一个初始化类实现WebApplicationInitializer如下图所示(在这种情况下,作为替代在%uA0web.xml%uA0中定义的任何 Spring%uA0配置)。在Servlet%uA03.0的容器启动时,这个类会被加载并实例及其 onStartup方法将通过servlet容器调用。
com.yiibai.springmvc.configuration.AppInitializer
package com.yiibai.springmvc.configuration import javax.servlet.ServletContext import javax.servlet.ServletException import javax.servlet.ServletRegistration import org.springframework.web.WebApplicationInitializer import org.springframework.web.context.support.AnnotationConfigWebApplicationContext import org.springframework.web.servlet.DispatcherServlet public class AppInitializer implements WebApplicationInitializer { public void onStartup(ServletContext container) throws ServletException { AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext() ctx.register(AppConfig.class) ctx.setServletContext(container) ServletRegistration.Dynamic servlet = container.addServlet( "dispatcher", new DispatcherServlet(ctx)) servlet.setLoadOnStartup(1) servlet.addMapping("/") } } %uA0
更新:请注意,上面的类可以写成更加简洁[和它的首选方式],通过扩展ꂫstractAnnotationConfigDispatcherServletInitializer%uA0基类,如下所示:
package com.yiibai.springmvc.configuration import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer public class AppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer { @Override protected Class<?>[] getRootConfigClasses() { return new Class[] { AppConfig.class } } @Override protected Class<?>[] getServletConfigClasses() { return null } @Override protected String[] getServletMappings() { return new String[] { "/" } } }
第7步:构建和部署应用程序
现在构建%uA0war(通过Eclipse或Maven%uA0[%uA0mvn%uA0clean%uA0install])。部署%uA0war%uA0到Servlet3.0容器。
到这里,所有教程讲解完毕!
代码下载:http://pan.baidu.com/s/1skqkZBf