SpringBoot2.x系列教程:整合SpringMVC之內容協商視圖解析器

我們在上一章節中,講解了ContentNegotiating內容協商的使用及簡單原理分析,上一章節主要是講解內容協商在HttpMessage上的作用。

其實內容協商不僅僅可以作用在HttpMessage上,還可以作用在View視圖上,本章節我講解該內容。

一.內容協商視圖解析器

1.概述

ContentNegotiatingViewResolver自己並不解析視圖,而是委派給其他的視圖處理器。

爲了使這個解析器正常工作,order序號需要設置成比其他的視圖處理器高的優先級(默認就是最高的)。

2. ContentNegotiatingViewResolver細節:

  • ContentNegotiationManager用於內容協商的策略可以手動設置指定,也可以通過FactoryBean自動生成;
  • viewResolvers默認是去容器內找到所有的,當然你也可以手動set進來;
  • 使用request的媒體類型,根據擴展名選擇不同的view輸出不同的格式;
  • 不是自己處理view,而是代理給不同的ViewResolver來處理不同的view;
  • 默認是支持Accept和後綴的協商方式的。並且還支持 邏輯視圖名.後綴的視圖解析方式;
  • 依據View.getContentType匹配MediaType來完成的最佳匹配。

二.ContentNegotiatingViewResolver使用

在默認情況下,Spring MVC並沒有開啓ContentNegotiatingViewResolver內容協商視圖解析器,因此如果有同一接口資源,要用多視圖展示的需求,我們是需要自己手動配置來實現的。

所以接下來我帶大家,對同一個接口資源,返回多個View。

1. 需求介紹

我們要對同一個RESTful風格的URL,根據請求的不同,可以得到一個PDF視圖,一個JSON視圖,一個Html視圖。

2. 創建web項目(略)

參照之前的案例,我們創建一個新的web項目,過程略去。

3. 創建View視圖

3.1 創建PdfViewResolver類

package com.yyg.boot.resolver;

import org.springframework.http.MediaType;
import org.springframework.web.servlet.View;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.view.ContentNegotiatingViewResolver;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Map;

/**
 * @Description Description
 * @Author 一一哥Sun
 * @Date Created in 2020/3/22
 */
public class PdfViewResolver implements View {

    @Override
    public String getContentType() {
        return MediaType.APPLICATION_PDF_VALUE;
    }

    @Override
    public void render(Map<String, ?> model, HttpServletRequest request, HttpServletResponse response) throws Exception {
        response.getWriter().write("<html><body style='color:red'>This is [PDF] view</body></html>");
    }

}

3.2 創建ExcelViewResolver類

package com.yyg.boot.resolver;

import org.springframework.http.MediaType;
import org.springframework.web.servlet.View;
import org.springframework.web.servlet.view.ContentNegotiatingViewResolver;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Map;

/**
 * @Description Description
 * @Author 一一哥Sun
 * @Date Created in 2020/3/22
 */
public class ExcelViewResolver implements View {

    @Override
    public String getContentType() {
        return MediaType.APPLICATION_JSON_UTF8_VALUE;
    }

    @Override
    public void render(Map<String, ?> model, HttpServletRequest request, HttpServletResponse response) throws Exception {
        response.getWriter()
                .write("<html><body style='color:blue'>This is [JSON] view!</body></html>");
    }

}

3.3 創建HtmlViewResolver類

package com.yyg.boot.resolver;

import org.springframework.http.MediaType;
import org.springframework.web.servlet.View;
import org.springframework.web.servlet.view.ContentNegotiatingViewResolver;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Map;

/**
 * @Description Description
 * @Author 一一哥Sun
 * @Date Created in 2020/3/22
 */
public class HtmlViewResolver implements View {

    @Override
    public String getContentType() {
        return MediaType.TEXT_HTML_VALUE;
    }

    @Override
    public void render(Map<String, ?> model, HttpServletRequest request, HttpServletResponse response) throws Exception {
        response.getWriter()
                .write("<html><body style='color:green'>This is [HTML] view!</body></html>");
    }

}

4. 進行視圖配置

將上面創建的視圖註冊到內容協調視圖解析器中,開啓Spring MVC在視圖上對ContentNegotiation內容協商的支持。

package com.yyg.boot.config;

import com.yyg.boot.resolver.ExcelViewResolver;
import com.yyg.boot.resolver.HtmlViewResolver;
import com.yyg.boot.resolver.PdfViewResolver;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.MediaType;
import org.springframework.web.servlet.View;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.config.annotation.ViewResolverRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import org.springframework.web.servlet.view.ContentNegotiatingViewResolver;
import org.springframework.web.servlet.view.InternalResourceViewResolver;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Locale;
import java.util.Map;

/**
 * @Description Description
 * @Author 一一哥Sun
 * @Date Created in 2020/3/22
 */
@Configuration
public class WebMvcConfig extends WebMvcConfigurationSupport {

    @Override
    public void configureViewResolvers(ViewResolverRegistry registry) {
        registry.enableContentNegotiation(new PdfViewResolver());
        registry.enableContentNegotiation(new ExcelViewResolver());
        registry.enableContentNegotiation(new HtmlViewResolver());

        // 上面三個註冊方法必須在此方法之上執行
        registry.enableContentNegotiation(false);
    }

}

5. 創建Controller測試接口

package com.yyg.boot.web;

import lombok.extern.slf4j.Slf4j;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Controller;
import org.springframework.util.MimeType;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.ResponseBody;

/**
 * @Description 內容協商視圖解析器
 * @Author 一一哥Sun
 * @Date Created in 2020/3/21
 */
@Slf4j
@Controller
public class NegotiationController {

    @GetMapping(value = "/show/{type}")
    public String showUser(@PathVariable("type") String type) {
        log.warn("type={}", type);
        return "跟一一哥學習ContentNegotiatingViewResolver!";
    }

}

6. 啓動程序,運行測試

我們在瀏覽器中輸入地址:
http://localhost:8080/show/a.pdf
可以看到如下效果:

我們在瀏覽器中輸入地址:
http://localhost:8080/show/a.json
可以看到如下效果:

我們在瀏覽器中輸入地址:
http://localhost:8080/show/a.html
可以看到如下效果:

而在沒有後綴名的情況下,以Accept的規則爲準。

所以可見擴展名的規則優先級高於Accept,符合我們上一章節中的理論知識。若沒有指定請求的擴展名,則Accept就會生效!

三.內容協調視圖解析器工作原理圖

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章