Spring 4 MVC ContentNegotiatingViewResolver Example

一直对ContentNegotiatingViewResolver(协商资源表述)一知半解,今天花了点时写了个小例子间彻底弄明白

这个其实是一个中间代理,本身不解析视图,它只会根据请求的信息调用对应的视图解析器处理请求,返回如jsp,json,xml,pdf,excel等,它会首先查看URL的文件扩展名。如果URL在结尾处有文件扩展名的话,ContentNegotiatingViewResolver将会基于该扩展名确定所需的类型。如果扩展名是“.json”的话,那么所需的内容类型必须是“application/json”。如果扩展名是“.xml”,那么客户端请求的就是“application/xml”。当然,“.html”扩展名表明客户端所需的资源表述为HTML(text/html)。如果没有Accept头部信息,并且扩展名也无法提供帮助的话,将会使用“/”作为默认的内容类型,这就意味着客户端必须要接收服务器发送的任何形式的表述(翻译自Spring In Action 第四版)。

其实这个类现在用的很少,基本上都是用@RestController和Http消息转换来做的

本例用到的工具和主要jar包如下:
Spring 4.3.11.RELEASE
jackson-databind 2.9.1
jackson-annotations 2.9.1
lowagie itext 4.2.1
Apache POI 3.17
Maven 3
JDK 1.8
Tomcat 8.5.20
Eclipse Oxygen

Step 1: 创建项目目录结构如下
这里写图片描述

Step 2: pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.lyl</groupId>
    <artifactId>springmvc-rest</artifactId>
    <packaging>war</packaging>
    <version>0.0.1-SNAPSHOT</version>

    <name>springmvc-rest</name>
    <description>Demo REST API Webapp Project for Spring Annotation</description>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
        <junit.version>4.12</junit.version>
        <spring.version>4.3.11.RELEASE</spring.version>
        <jstl.version>1.2</jstl.version>
        <servlet.version>3.1.0</servlet.version>
        <log4j2.version>2.9.0</log4j2.version>
        <slf4j.version>1.7.25</slf4j.version>
        <lombok.version>1.16.12</lombok.version>
        <jackson.version>2.9.1</jackson.version>
    </properties>

    <dependencies>
        <!-- lombok -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>${lombok.version}</version>
            <scope>provided</scope>
        </dependency>
        <!-- junit config -->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>${junit.version}</version>
            <scope>test</scope>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.apache.commons/commons-lang3 -->
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-lang3</artifactId>
            <version>3.6</version>
        </dependency>
        <!-- spring context -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <!-- spring web -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-web</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <!-- spring webmvc -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <!-- spring-oxm -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-oxm</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <!-- spring test -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-core</artifactId>
            <version>${log4j2.version}</version>
        </dependency>
        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-jcl</artifactId>
            <version>${log4j2.version}</version>
        </dependency>
        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-slf4j-impl</artifactId>
            <version>${log4j2.version}</version>
        </dependency>
        <!-- servlet -->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>${servlet.version}</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>jstl</groupId>
            <artifactId>jstl</artifactId>
            <version>${jstl.version}</version>
        </dependency>
        <!-- jackson-core -->
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-core</artifactId>
            <version>${jackson.version}</version>
        </dependency>
        <!-- jackson-databind -->
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>${jackson.version}</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.apache.poi/poi -->
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi</artifactId>
            <version>3.17</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.apache.poi/poi-ooxml -->
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-ooxml</artifactId>
            <version>3.17</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/com.lowagie/itext -->
        <dependency>
            <groupId>com.lowagie</groupId>
            <artifactId>itext</artifactId>
            <version>2.1.7</version>
        </dependency>
    </dependencies>

    <build>
        <finalName>springmvc-rest</finalName>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>${java.version}</source>
                    <target>${java.version}</target>
                    <fork>true</fork>
                    <verbose>true</verbose>
                    <encoding>UTF-8</encoding>
                    <compilerArguments>
                        <sourcepath>${project.basedir}/src/main/java</sourcepath>
                    </compilerArguments>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-war-plugin</artifactId>
                <configuration>
                    <failOnMissingWebXml>false</failOnMissingWebXml>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

Step 3: 配置类
1.WebAppInitializer

package com.lyl.springmvc.config;

import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;

public class WebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {

    @Override
    protected Class<?>[] getRootConfigClasses() {
        return new Class[] { RootConfig.class };
    }

    @Override
    protected Class<?>[] getServletConfigClasses() {
        return new Class[] { WebConfig.class };
    }

    @Override
    protected String[] getServletMappings() {
        return new String[] { "/" };
    }

}

2.WebConfig

package com.lyl.springmvc.config;

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.DefaultServletHandlerConfigurer;
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.lyl.springmvc.config.viewresolver.ExcelViewResolver;
import com.lyl.springmvc.config.viewresolver.Jaxb2MarshallingXmlViewResolver;
import com.lyl.springmvc.config.viewresolver.JsonViewResolver;
import com.lyl.springmvc.config.viewresolver.PdfViewResolver;
import com.lyl.springmvc.model.Person;

@Configuration
@EnableWebMvc
@ComponentScan(basePackages = "com.lyl.springmvc.controller")
public class WebConfig extends WebMvcConfigurerAdapter {

    @Override
    public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
        configurer.enable();
    }

    /*
     * 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(jspViewResolver());
        resolvers.add(jsonViewResolver());
        resolvers.add(jaxb2MarshallingXmlViewResolver());
        resolvers.add(excelViewResolver());
        resolvers.add(pdfViewResolver());

        resolver.setViewResolvers(resolvers);
        return resolver;
    }

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

    /*
     * 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(Person.class);
        return new Jaxb2MarshallingXmlViewResolver(marshaller);
    }

    /*
     * 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 PDF output using lowagie pdf library to generate PDF output for an object content
     */
    @Bean
    public ViewResolver pdfViewResolver() {
        return new PdfViewResolver();
    }

}

3.RootConfig

package com.lyl.springmvc.config;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.ComponentScan.Filter;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Controller;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;

@Configuration
@ComponentScan(basePackages = "com.lyl.springmvc", excludeFilters = { @Filter({ Controller.class, EnableWebMvc.class }) })
public class RootConfig {

}

Step 4: 创建ViewResolver类
1.XML

package com.lyl.springmvc.config.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;
    }

}

2.JSON

package com.lyl.springmvc.config.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;
    }

}

3.PDF

package com.lyl.springmvc.config.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.lyl.springmvc.model.Person;

public class PdfView extends AbstractPdfView {
    @Override
    protected void buildPdfDocument(Map<String, Object> model, Document document, PdfWriter writer, HttpServletRequest request,
            HttpServletResponse response) throws Exception {

        Person p = (Person) model.get("p");

        PdfPTable table = new PdfPTable(3);
        table.getDefaultCell().setHorizontalAlignment(Element.ALIGN_CENTER);
        table.getDefaultCell().setVerticalAlignment(Element.ALIGN_MIDDLE);
        table.getDefaultCell().setBackgroundColor(Color.lightGray);

        table.addCell("ID");
        table.addCell("NAME");
        table.addCell("AGE");

        table.addCell(String.valueOf(p.getId()));
        table.addCell(p.getName());
        table.addCell(String.valueOf(p.getAge()));

        document.add(table);
    }
}
package com.lyl.springmvc.config.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;
    }

}

3.EXCEL

package com.lyl.springmvc.config.viewresolver;

import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.FillPatternType;
import org.apache.poi.ss.usermodel.HorizontalAlignment;
import org.apache.poi.ss.usermodel.IndexedColors;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Workbook;
import org.springframework.web.servlet.view.document.AbstractXlsxView;

import com.lyl.springmvc.model.Person;

public class ExcelView extends AbstractXlsxView {

    @Override
    protected void buildExcelDocument(Map<String, Object> model, Workbook workbook, HttpServletRequest request, HttpServletResponse response)
            throws Exception {
        Person p = (Person) model.get("p");

        Sheet sheet = workbook.createSheet("sheet 1");
        CellStyle style = workbook.createCellStyle();
        style.setFillForegroundColor(IndexedColors.GREY_40_PERCENT.index);
        style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
        style.setAlignment(HorizontalAlignment.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("ID");

        cell = row.createCell(colCount++);
        cell.setCellStyle(style);
        cell.setCellValue("NAME");

        cell = row.createCell(colCount++);
        cell.setCellStyle(style);
        cell.setCellValue("AGE");

        // Create data cells
        row = sheet.createRow(rowCount++);
        colCount = 0;
        row.createCell(colCount++).setCellValue(p.getId());
        row.createCell(colCount++).setCellValue(p.getName());
        row.createCell(colCount++).setCellValue(p.getAge());

    }

}
package com.lyl.springmvc.config.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;
    }
}

Step 5: 控制器类

package com.lyl.springmvc.controller;

import java.util.List;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;

import com.lyl.springmvc.model.Person;
import com.lyl.springmvc.service.PersonService;

@Controller
@RequestMapping("/person")
public class PersonController {

    @Autowired
    private PersonService pService;

    @RequestMapping("/{id}")
    public String findPerson(@PathVariable Integer id, Map<String, Person> model) {
        model.put("p", pService.getById(id));
        return "/person/details";
    }

    @RequestMapping(value = {"/", "/list"})
    public String findPersonList(Map<String, List<Person>> model) {
        model.put("ps", pService.getAll());
        return "/person/list";
    }
}

Step 6: Service 和 Model类

package com.lyl.springmvc.service;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.springframework.stereotype.Service;

import com.lyl.springmvc.model.Person;

@Service
public class PersonService {

    private Map<Integer, Person> personMap = new HashMap<Integer, Person>();

    public PersonService() {
        personMap.put(1, new Person(1, "Tom", 18));
        personMap.put(2, new Person(2, "Jack", 20));
        personMap.put(3, new Person(3, "Andy", 17));
    }

    public Person getById(Integer id) {
        return personMap.get(id);
    }

    public List<Person> getAll() {
        return new ArrayList<Person>(personMap.values());
    }
}
package com.lyl.springmvc.model;

import javax.xml.bind.annotation.XmlRootElement;

import lombok.Getter;
import lombok.Setter;

@Getter
@Setter
@XmlRootElement(name = "person")
public class Person {

    private Integer id;
    private String name;
    private int age;

    public Person() {

    }

    public Person(Integer id, String name, int age) {
        super();
        this.id = id;
        this.name = name;
        this.age = age;
    }

}

Step 7: 部署测试
1.http://localhost:8080/springmvc-rest/person/list
默认请求不带后缀直接返回jsp页面
2.http://localhost:8080/springmvc-rest/person/list.json
返回JSON格式
2.http://localhost:8080/springmvc-rest/person/list.xml
返回xml格式
3.http://localhost:8080/springmvc-rest/person/list.pdf
返回PDF
4.http://localhost:8080/springmvc-rest/person/list.xlsx
返回EXCEL

本文参考资料
1.Spring In Action 第四版第16章
2.https://websystique.com/springmvc/spring-4-mvc-contentnegotiatingviewresolver-example/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值