我们在上一章节中,讲解了ContentNegotiating内容协商的使用及简单原理分析,上一章节主要是讲解内容协商在HttpMessage上的作用。
其实内容协商不仅仅可以作用在HttpMessage上,还可以作用在View视图上,本章节我讲解该内容。
ContentNegotiatingViewResolver自己并不解析视图,而是委派给其他的视图处理器。
为了使这个解析器正常工作,order序号需要设置成比其他的视图处理器高的优先级(默认就是最高的)。
在默认情况下,Spring MVC并没有开启ContentNegotiatingViewResolver内容协商视图解析器,因此如果有同一接口资源,要用多视图展示的需求,我们是需要自己手动配置来实现的。
所以接下来我带大家,对同一个接口资源,返回多个View。
我们要对同一个RESTful风格的URL,根据请求的不同,可以得到一个PDF视图,一个JSON视图,一个Html视图。
参照之前的案例,我们创建一个新的web项目,过程略去。
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 model, HttpServletRequest request, HttpServletResponse response) throws Exception {
response.getWriter().write("This is [PDF] view");
}
}
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 model, HttpServletRequest request, HttpServletResponse response) throws Exception {
response.getWriter()
.write("This is [JSON] view!");
}
}
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 model, HttpServletRequest request, HttpServletResponse response) throws Exception {
response.getWriter()
.write("This is [HTML] view!");
}
}
将上面创建的视图注册到内容协调视图解析器中,开启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);
}
}
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!";
}
}
我们在浏览器中输入地址:
http://localhost:8080/show/a.pdf
可以看到如下效果:
我们在浏览器中输入地址:
http://localhost:8080/show/a.json
可以看到如下效果:
我们在浏览器中输入地址:
http://localhost:8080/show/a.html
可以看到如下效果:
而在没有后缀名的情况下,以Accept的规则为准。
所以可见扩展名的规则优先级高于Accept,符合我们上一章节中的理论知识。若没有指定请求的扩展名,则Accept就会生效!