Spring 4 MVC 视图解析器(XML JSON PDF等) 纯注解(带源码)【推荐】

来源:互联网 发布:阿里云过户域名流程 编辑:程序博客网 时间:2024/04/30 11:55

原文地址:http://websystique.com/springmvc/spring-4-mvc-contentnegotiatingviewresolver-example/

【本系列其他教程正在陆续翻译中,点击分类:spring 4 mvc 进行查看。源码下载地址在文章末尾。

【翻译 by 明明如月 QQ 605283073】

下一篇:Spring 4 MVC @RestController 注解实现REST Service

上一篇:Spring 4 MVC 表单校验资源处理(带源码)

本文讲述Spring 4 MVC应用中通过Spring的 ContentNegotiatingViewResolver来支持多种形式的输出。




我们将输出 XML, JSON, PDF, XLS 和HTML格式的文件,基于纯注解的方式。

ContentNegotiatingViewResolver 是一个实现了 ViewResolver接口的类, 使用了请求媒体类型 (根据文件拓展吗 URL 指定输出类型参数或者accept 头)来选择合适的视图. 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.websystique.springmvc</groupId>    <artifactId>Spring4MVCContentNegotiatingViewResolverExample</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-compiler-plugin</artifactId>                    <version>3.2</version>                    <configuration>                        <source>1.6</source>                        <target>1.6</target>                    </configuration>                </plugin>                <plugin>                    <groupId>org.apache.maven.plugins</groupId>                    <artifactId>maven-war-plugin</artifactId>                    <version>2.4</version>                    <configuration>                        <warSourceDirectory>src/main/webapp</warSourceDirectory>                        <warName>Spring4MVCContentNegotiatingViewResolverExample</warName>                        <failOnMissingWebXml>false</failOnMissingWebXml>                    </configuration>                </plugin>            </plugins>        </pluginManagement>         <finalName>Spring4MVCContentNegotiatingViewResolverExample</finalName>    </build></project>


spring-oxm 支持 XML 格式的输出 (使用 JAXB2).jackson-databind & jackson-annotations 提供JSON格式的输出. itext提供PDF 创建库支持PDF 的输出. Apache POI 帮助创建 XLS 格式的输出

第3步:创建Spring配置类

com.websystique.springmvc.configuration.AppConfig
package com.websystique.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.websystique.springmvc.model.Pizza;import com.websystique.springmvc.viewresolver.ExcelViewResolver;import com.websystique.springmvc.viewresolver.JsonViewResolver;import com.websystique.springmvc.viewresolver.Jaxb2MarshallingXmlViewResolver;import com.websystique.springmvc.viewresolver.PdfViewResolver; @Configuration@EnableWebMvc@ComponentScan(basePackages = "com.websystique.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's (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用来决定请求的media代理到ContentNegotiationStrategy实例集合.默认PathExtensionContentNegotiationStrategy 被请求 (使用url拓展名 e.g. .xls, .pdf,.json..) ,然后是ParameterContentNegotiationStrategy (使用的请求参数 ‘format=xls’ e.g.), 然后是HeaderContentNegotiationStrategy (使用HTTP Accept Headers)。


public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {    configurer.ignoreAcceptHeader(true).defaultContentType(            MediaType.TEXT_HTML);}

在我们的例子中我们将使用基于URL拓展名来决定 媒体类型。

如果没有拓展名我们默认用TEXT_HTML 类处理。

也就是说 未知的拓展名类型我们使用jsp 视图解析器处理。


pizza.jsp 将用来做默认的jsp视图解析器

<%@ page language="java" contentType="text/html; charset=ISO-8859-1"  pageEncoding="ISO-8859-1"%><%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <html><head>    <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">    <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}"/>                  </c:forEach>            </td>        </tr>    </table></body></html>

下一步配置:ContentNegotaionViewResolver

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;}


我们需要设置ContentNegotiationManager 并注入到spring中,不同的解析器响应不同格式的请求。

第4步: 创建不同的视图解析器

XML 视图解析器:

com.websystique.springmvc.viewresolver.Jaxb2MarshallingXmlViewResolver

package com.websystique.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;    } }

产生XML的注解

com.websystique.springmvc.model.Pizza

package com.websystique.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视图解析器


使用 Spring MappingJackson2JsonView 获取视图将POJO转换为JSON


com.websystique.springmvc.viewresolver.JsonViewResolver

package com.websystique.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视图解析器

此视图解析器是使用 lowagie itext 库来实际输出PDF的。

实际视图拓展自Spring AbstractPdfView,它使用的就是itext库。

com.websystique.springmvc.viewresolver.PdfView

package com.websystique.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.websystique.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.websystique.springmvc.viewresolver.PdfViewResolver

package com.websystique.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视图解析器:

使用 Apache POI库产生XLS输出。拓展自Spring AbstractExcelView ,它本身内部使用的就是  Apache POI库。


com.websystique.springmvc.viewresolver.ExcelView

package com.websystique.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.websystique.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.websystique.springmvc.viewresolver.ExcelViewResolver
package com.websystique.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.websystique.springmvc.controller.AppController
package com.websystique.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.websystique.springmvc.model.Pizza; @Controllerpublic 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步:创建初始化类


com.websystique.springmvc.configuration.AppInitializer

package com.websystique.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("/");    } }

可简化为下面的类:
package com.websystique.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[] { "/" };    } }

Step 7:创建和发布

在tomcat中发布

下面截图是根据url拓展名来作不同的响应









[源码下载地址:http://websystique.com/?smd_process_download=1&download_id=772]


特别说明:此系列教程有的童鞋下载下来运行 经常404 或者改成xml方式以后
缺少org.springframework.web.context.ContextLoaderServlet等
参见:http://blog.csdn.net/w605283073/article/details/52126347

2 0
原创粉丝点击