本篇文章试图解释清楚一些我们比较模糊的springmvc概念,包括视图内容协商,restful内容协商,以及HandlerMethodReturnValueHandler,HandlerMethodReturnValueHandler也就是handler method 入参的处理和返回值得处理。谢谢大家。考虑内容篇幅过于臃肿,分为上下两篇,上篇spring mvc之视图,下篇restful及内容调停
通用资源抽象,比如文件资源: File,ClassPath资源: ClassLoader,统一资源: URL,Web资源: ServletContext
但是Spring 为我们提供了资源的抽象,我们可以通过比如"classpath://location"来制定classpath下的资源 ,"file://location"指定file下的资源等等:Resource
Context :Thyemeaf 渲染上下文
Model :Spring Web MVC 模型
Attribute :Servlet 上下文
我们通过简单的使用使用 Thymeleaf API 渲染内容:
public class ThymeleafTemplateEngineBootstrap {
public static void main(String[] args) throws IOException {
// 构建引擎
SpringTemplateEngine templateEngine = new SpringTemplateEngine();
// 创建渲染上下文
Context context = new Context();
context.setVariable("message", "Hello,World");
// 读取内容从 classpath:/thymeleaf/hello-world.html
// ResourceLoader
ResourceLoader resourceLoader = new DefaultResourceLoader();
// 通过 classpath:/templates/thymeleaf/hello-world.html Resource
Resource resource = resourceLoader.getResource("classpath:/thymeleaf/hello-world.html");
File templateFile = resource.getFile();
// 文件流
FileInputStream inputStream = new FileInputStream(templateFile);
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
// Copy
IOUtils.copy(inputStream, outputStream);
inputStream.close();
// 模板的内容
String content = outputStream.toString("UTF-8");
// 渲染(处理)结果
String result = templateEngine.process(content, context);
// 输出渲染(处理)结果
System.out.println(result);
}
}
基本组件(接口)
ViewResolver :视图解析器
View : 视图组件
DispatcherServlet :总控(实现类)
Thymeleaf 整合 Spring Web MVC,对应的实现类
ViewResolver : ThymeleafViewResolver
View : ThymeleafView
ITemplateEngine : SpringTemplateEngine
第一步:
导入内嵌式jsp servlet,和服务器依赖,以及标准标签库
org.springframework.boot
spring-boot-starter-tomcat
org.apache.tomcat.embed
tomcat-embed-jasper
第二步:
导入springboot的maven插件
第三步:
添加webapp/web-inf/jsp文件,并在application.properties中添加jsp视图解析器的前缀后缀。
关于什么是视图内容协商,其实就是springMVC自动为我们添加了一个视图解析器,且优先使用该视图解析器进行集成其他的视图解析器,并通过视图名称依次调用集成的视图解析器返回视图,并根据ContentNegotiationManager(内容调停管理器)筛选出最佳view,来进行视图的渲染工作。进而实现一个请求路径可以使用accecpt请求头实现返回不同视图内容,如xml或html。
现在介绍一下先关的调停策略:
固定 MediaType : FixedContentNegotiationStrategy
"Accept" 请求头: HeaderContentNegotiationStrategy
请求参数: ParameterContentNegotiationStrategy
路径扩展名: PathExtensionContentNegotiationStrategy
springboot默认的配置策略仅有一个HeaderContentNegotiationStrategy
//webmvc自动配置配置 内容调停视图
public ContentNegotiatingViewResolver viewResolver(BeanFactory beanFactory) {
ContentNegotiatingViewResolver resolver = new ContentNegotiatingViewResolver();
//我们看到这里从beanfactory中获取内容调停管理器 resolver.setContentNegotiationManager((ContentNegotiationManager)beanFactory.getBean(ContentNegotiationManager.class));
resolver.setOrder(-2147483648);
return resolver;
}
/*
通过setApplicationContext机制进行模板方法的回调
setApplicationContext:78, ApplicationObjectSupport
initApplicationContext:81, WebApplicationObjectSupport
initServletContext:185, ContentNegotiatingViewResolver
*/
//加载上下文中的所有视图解析器
protected void initServletContext(ServletContext servletContext) {
Collection matchingBeans = BeanFactoryUtils.beansOfTypeIncludingAncestors(this.obtainApplicationContext(), ViewResolver.class).values();
ViewResolver viewResolver;
if (this.viewResolvers == null) {
this.viewResolvers = new ArrayList(matchingBeans.size());
Iterator var3 = matchingBeans.iterator();
while(var3.hasNext()) {
viewResolver = (ViewResolver)var3.next();
if (this != viewResolver) {
this.viewResolvers.add(viewResolver);
}
}
} else {
for(int i = 0; i < this.viewResolvers.size(); ++i) {
viewResolver = (ViewResolver)this.viewResolvers.get(i);
if (!matchingBeans.contains(viewResolver)) {
String name = viewResolver.getClass().getName() + i;
this.obtainApplicationContext().getAutowireCapableBeanFactory().initializeBean(viewResolver, name);
}
}
}
if (this.viewResolvers.isEmpty()) {
this.logger.warn("Did not find any ViewResolvers to delegate to; please configure them using the 'viewResolvers' property on the ContentNegotiatingViewResolver");
}
//并进行优先级的排序
AnnotationAwareOrderComparator.sort(this.viewResolvers);
this.cnmFactoryBean.setServletContext(servletContext);
}
//webmvc 自动配置
@Bean
public ContentNegotiationManager mvcContentNegotiationManager() {
//此处调用父类的方法获取
ContentNegotiationManager manager = super.mvcContentNegotiationManager();
List strategies = manager.getStrategies();
ListIterator iterator = strategies.listIterator();
while(iterator.hasNext()) {
ContentNegotiationStrategy strategy = (ContentNegotiationStrategy)iterator.next();
if (strategy instanceof PathExtensionContentNegotiationStrategy) {
iterator.set(new WebMvcAutoConfiguration.OptionalPathExtensionContentNegotiationStrategy(strategy));
}
}
return manager;
}
//父类的方法
@Bean
public ContentNegotiationManager mvcContentNegotiationManager() {
if (this.contentNegotiationManager == null) {
ContentNegotiationConfigurer configurer = new ContentNegotiationConfigurer(this.servletContext);
configurer.mediaTypes(this.getDefaultMediaTypes());
this.configureContentNegotiation(configurer);
this.contentNegotiationManager = configurer.buildContentNegotiationManager();
}
return this.contentNegotiationManager;
}
//默认只有这摸一种策略:HeaderContentNegotiationStrategy
//ContentNegotiationConfigurer 相当于是一个build,每一步设置都是构建 ContentNegotiationManagerFactoryBean 的先关参数,然后 build时进行创建
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
@Override
public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
//内容调停策略设置
configurer.favorParameter(true).favorPathExtension(true);
}
}
好,到此内容调停策略的内容解析完毕,谢谢大家的支持。