文章目录
- 1.Spring Web MVC
- 1.1.Introduction
- 1.2.DispatcherServlet
该文档参考自Spring Framework 5.0.9
1.Spring Web MVC
1.1.Introduction
Spring Web MVC是构建在Servlet API上的原始Web框架,从一开始就包含在Spring Framework中。 正式名称“Spring Web MVC”
来自其源模块spring-webmvc的名称,但它通常被称为“Spring MVC”
。
与Spring Web MVC并行,Spring Framework 5.0引入了一个反应式堆栈(reactive stack),Web框架,其名称Spring WebFlux也基于其源模块spring-webflux。 本节介绍Spring Web MVC。 下一节将介绍Spring WebFlux。
Spring Web MVC是一种基于 Java的实现了Web MVC设计模式的请求驱动类型的轻量级Web框架,即使用了MVC架构模式的思想,将web层进行职责解耦,基于请求驱动指的就是使用请求-响应模型,框架的目的就是帮助我们简化开发,Spring Web MVC也是要简化我们日常Web 开发的。
Spring Web MVC也是服务到工作者模式的实现,但可进行优化。
1.2.DispatcherServlet
-
前端控制器是
DispatcherServlet
; -
应用控制器其实拆为处理器映射器(
Handler Mapping
)进行处理器管理和视图解析器(View Resolver
)进行视图管理; -
页面控制器/动作/处理器为
Controller
接口(仅包含ModelAndView handleRequest(request, response)
方法)的实现(也可以是任何的POJO
类);支持本地化(Locale)
解析、主题(Theme)
解析及文件上传等;提供了非常灵活的数据验证、格式化和数据绑定机制; -
提供了强大的约定大于配置(惯例优先原则)的契约式编程支持。
-
SpringMVC
提供了一个功能强大的,通用的DispatcherServlet
,也叫前端控制器,可以接收整个项目的所有请求; -
DispatcherServlet
是SpringMVC
为我们写好的Servlet
,所有的请求都经过它来调用控制器中的方法并处理; -
DispatcherServlet
由SpringMVC
定义,由SpringIOC
容器管理;
像许多其他Web框架一样,Spring MVC围绕前端控制器模式进行设计,其中中央Servlet DispatcherServlet
为请求与处理提供共享算法,而实际工作则委托给可配置的组件执行。 该模型非常灵活,支持多种工作流程。
作为任意的Servlet
,DispatcherServlet
需要根据Servlet的规范,使用Java配置或在web.xml
中进行声明和映射。DispatcherServlet
根据Spring规范的配置来确认它在请求映射,查看解析,异常处理等方面所需的委托组件,and more。
因为Servlet要被SpringIOC容器管理,所以要在产生Servlet实例的时候就要产生SpringIOC容器的实例。以下是注册和初始化DispatcherServlet
的Java Config示例。 该类由Servlet容器自动检测(请参阅Servlet Config):
public class MyWebApplicationInitializer implements WebApplicationInitializer {
@Override
public void onStartup(ServletContext servletCxt) {
// Load Spring web application configuration
AnnotationConfigWebApplicationContext ac = new AnnotationConfigWebApplicationContext();
ac.register(AppConfig.class);
ac.refresh();
// Create and register the DispatcherServlet
DispatcherServlet servlet = new DispatcherServlet(ac);
ServletRegistration.Dynamic registration = servletCxt.addServlet("app", servlet);
registration.setLoadOnStartup(1);
registration.addMapping("/app/*");
}
}
除了直接使用ServletContext API
之外,您还可以扩展AbstractAnnotationConfigDispatcherServletInitializer
并覆盖特定方法(请参阅Context Hierarchy下的示例)。
在web.xml
中配置该Servlet的启动时机与初始化参数:
<web-app>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/app-context.xml</param-value>
</context-param>
<servlet>
<servlet-name>app</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value></param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>app</servlet-name>
<url-pattern>/app/*</url-pattern>
</servlet-mapping>
</web-app>
- 启动时机:
<load-on-startup>
配置DispatcherServlet
在Web
服务器已启动就将该Servlet
实例化; - 初始化参数:在
<init-param>
中定义SpringIOC
的配置文件路径,这样在Servlet
被实例化的时候,该路径就会被Servlet
通过ServletConfig
参数获取到,获取到之后就可以获取该文件并解析实例化bean
,那么Spring
容器就也被实例化了; - 此处也可以不使用
<init-param>
配置,但是要求Spring
配置文件必须放在WEB-INF
下,并且文件名与servlet-name
一致; DispatcherServlet
可能要让控制器调用任意的实体类,所以必须一开始就初始化Spring
容器;
Spring Boot
遵循不同的初始化顺序。Spring Boot
使用Spring
配置来引导自身和嵌入的Servlet
容器,而不是hook到Servlet
容器的生命周期。 在Spring
配置中检测到Filter
和Servlet
声明,并在Servlet
容器中注册。 有关更多详细信息,请查阅Spring Boot
文档。
1.2.1Context Hierarchy - 上下文层次结构
DispatcherServlet
需要一个WebApplicationContext
(一个普通的ApplicationContext
的扩展)用于其自己的配置。WebApplicationContext
有一个指向它所关联的ServletContext
和Servlet
的链接。它也绑定到ServletContext
,以便应用程序可以在需要访问它的时候使用RequestContextUtils
上的静态方法访问WebApplicationContext
。
对于许多应用程序来说具有单个WebApplicationContext
更为简洁。当然也可以有一个上下文层次结构(Context Hierarchy),其中一个根WebApplicationContext
通过多个DispatcherServlet
(或其他Servlet
)实例共享,每个实例都有其自己的子WebApplicationContext
配置。有关上下文层次结构功能的更多信息,请参阅 Additional Capabilities of the ApplicationContext的其他功能。
根WebApplicationContext
通常包含需要跨多个Servlet
实例共享的基础架构bean,例如数据存储库和业务服务。这些bean被有效地继承,并且可以在特定的Servlet
的子WebApplicationContext
中被重写(即重新声明),子WebApplicationContext
通常包含给定的Servlet
本地的bean:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Xmfw1zdy-1572859654839)(https://docs.spring.io/spring/docs/5.0.7.BUILD-SNAPSHOT/spring-framework-reference/images/mvc-context-hierarchy.png)]
以下是使用WebApplicationContext
层次结构的示例配置:
public class MyWebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
@Override
protected Class<?>[] getRootConfigClasses() {
return new Class<?>[] { RootConfig.class };
}
@Override
protected Class<?>[] getServletConfigClasses() {
return new Class<?>[] { App1Config.class };
}
@Override
protected String[] getServletMappings() {
return new String[] { "/app1/*" };
}
}
如果不需要应用程序上下文层(context hierarchy)次结构,则应用程序可以通过getRootConfigClasses()
返回所有配置,并且可以从getServletConfigClasses()
返回null
。
等效于在web.xml
中:
<web-app>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/root-context.xml</param-value>
</context-param>
<servlet>
<servlet-name>app1</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/app1-context.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>app1</servlet-name>
<url-pattern>/app1/*</url-pattern>
</servlet-mapping>
</web-app>
如果不需要应用程序上下文层次结构(context hierarchy),则应用程序可以仅配置“root”
上下文,并将contextConfigLocation
Servlet参数留空。
1.2.2.Special Bean Types - 特殊Bean类型
DispatcherServlet
委托特殊的bean来处理请求并呈现适当的响应。“special bean”是指实现WebFlux框架协议的Spring管理的对象实例。这些bean通常带有内置了一些规则,但您可以自定义其属性,扩展或替换它们。
下表列出了DispatcherHandler
检测到的特殊bean
:
Bean type | 说明 |
---|---|
HandlerMapping | 将请求映射到处理程序(handler)以及预处理和后处理的 interceptors 列表。 该映射基于一些标准,其细节因HandlerMapping 实现而不同。 两个主要的HandlerMapping 实现是RequestMappingHandlerMapping ,它支持@RequestMapping 注解方法,SimpleUrlHandlerMapping , 它为URI处理程序显式注册URI 路径模式。 |
HandlerAdapter | 帮助DispatcherServlet 调用请求映射到的处理程序(handler), 而不管实际如何调用处理程序(handler)。 例如,调用带注解的控制器需要解析注解。 HandlerAdapter 的主要目的是屏蔽DispatcherServlet 的细节。 |
HandlerExceptionResolver | 它是异常解决机制, 可能将异常映射到处理程序或HTML 错误视图或其他。 参考 Exceptions. |
ViewResolver | 将从处理程序返回的基于字符串的逻辑视图名称解析为实际视图,以便使用返回的响应。 参考 View Resolution 和 View Technologies. |
LocaleResolver, LocaleContextResolver | 解析Locale 客户端正在使用以及可能的时区,以便能够提供国际化的视图。 参考Locale. |
ThemeResolver | 解析您的Web 应用程序可以使用的主题,例如提供个性化布局。参考 Themes. |
MultipartResolver | 在multipart 解析库的帮助下解析multi-part 请求的抽象(例如,浏览器表单文件上载)。 参考 Multipart resolver. |
FlashMapManager | 存储和检索可用于将属性从一个请求传递到另一个请求的“input” 和“output” 的FlashMap ,通常通过重定向。 参考Flash attributes. |
1.2.3.Web MVC Config
应用程序可以声明Special Bean Types中的基础架构Bean列表,用于处理请求所需。DispatcherServlet
检查每个特殊bean
的WebApplicationContext
。如果没有匹配的bean
类型,则它就是DispatcherServlet.properties中列出的默认类型。
最好使用MVC Config,它用Java或XML声明所需的bean,并提供更高级别的配置回调API来自定义它。可查看MVC Config。
Spring Boot
依靠MVC Java Config
来配置Spring MVC
,并且还提供了许多额外的方便选项。
1.2.4.Servlet Config - Servlet配置
在Servlet 3.0+环境中,您可以选择以编程方式将Servlet容器配置作为替代方式或与web.xml
文件组合使用。 以下是注册DispatcherServlet
的示例:
import org.springframework.web.WebApplicationInitializer;
public class MyWebApplicationInitializer implements WebApplicationInitializer {
@Override
public void onStartup(ServletContext container) {
XmlWebApplicationContext appContext = new XmlWebApplicationContext();
appContext.setConfigLocation("/WEB-INF/spring/dispatcher-config.xml");
ServletRegistration.Dynamic registration = container.addServlet("dispatcher", new DispatcherServlet(appContext));
registration.setLoadOnStartup(1);
registration.addMapping("/");
}
}
WebApplicationInitializer
是Spring MVC提供的一个接口,它确保您的实现被检测到并自动用于初始化任何Servlet 3容器。还有一个名为AbstractDispatcherServletInitializer
的WebApplicationInitializer
的抽象基类实现更容易注册DispatcherServlet
,通过简单重写方法来指定Servlet映射和DispatcherServlet
配置的位置。
建议使用基于Java的Spring配置的应用程序:
public class MyWebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
@Override
protected Class<?>[] getRootConfigClasses() {
return null;
}
@Override
protected Class<?>[] getServletConfigClasses() {
return new Class<?>[] { MyWebConfig.class };
}
@Override
protected String[] getServletMappings() {
return new String[] { "/" };
}
}
如果使用基于XML的Spring配置,则应该直接从AbstractDispatcherServletInitializer
扩展:
public class MyWebAppInitializer extends AbstractDispatcherServletInitializer {
@Override
protected WebApplicationContext createRootApplicationContext() {
return null;
}
@Override
protected WebApplicationContext createServletApplicationContext() {
XmlWebApplicationContext cxt = new XmlWebApplicationContext();
cxt.setConfigLocation("/WEB-INF/spring/dispatcher-config.xml");
return cxt;
}
@Override
protected String[] getServletMappings() {
return new String[] { "/" };
}
}
AbstractDispatcherServletInitializer
还提供了一种便捷方式,用于添加Filter
实例并将其自动映射到DispatcherServlet
:
public class MyWebAppInitializer extends AbstractDispatcherServletInitializer {
// ...
@Override
protected Filter[] getServletFilters() {
return new Filter[] {
new HiddenHttpMethodFilter(), new CharacterEncodingFilter() };
}
}
每个filter都会根据其具体类型添加一个默认名称,并自动映射到DispatcherServlet
。
AbstractDispatcherServletInitializer
的isAsyncSupported
提供了一个标志来启用DispatcherServlet
上的异步支持以及映射到它的所有过滤器。 默认情况下,该标志被设置为true
。
最后,如果您需要进一步自定义DispatcherServlet
本身,则可以覆盖createDispatcherServlet
方法。
1.2.5.Processing - 处理过程
DispatcherServlet
按如下方式处理请求:
WebApplicationContext
在请求中被搜索并绑定,作为控制器和进程中其他元素可以使用的属性。WebApplicationContext
在DispatcherServlet.WEB_APPLICATION_CONTEXT_ATTRIBUTE
关键字下被默认绑定。- locale resolver绑定到请求以启用进程中的元素来resolve(解析)处理请求(呈现视图,准备数据等)时要使用的locale(区域)。如果你不需要locale resolving(区域解析),那就不需要locale resolver。
- theme resolver`被绑定到请求,让请求等元素去决定该使用哪个theme(主题),如果不需要可以忽略theme resolver。
- 如果你指定了multipart file resolver,则会检查请求中的multiparts,如果找到multiparts,则将请求封装在
MultipartHttpServletRequest
中,以供进程中的其他元素进一步处理。See Multipart resolver for further information about multipart handling. - 搜索适当的处理程序(handler)。如果找到处理程序(handler),则会执行与该处理程序(handler)(预处理程序,后处理程序和控制器)关联的执行链以准备模型(model)或渲染。
- 如果返回模型(model),则呈现视图(view)。如果没有返回model(可能是由于预处理程序或后处理程序拦截了请求,可能出于安全原因),则不会呈现视图,因为请求可能已经被满足。
WebApplicationContext
中声明的HandlerExceptionResolver
bean用于解决请求处理期间抛出的异常。这些exception resolver
允许定制逻辑来解决异常。参考Exceptions
Spring DispatcherServlet
支持返回最后修改日期,正如Servlet API
所指定的那样。确定特定请求的最后修改日期的过程很简单:DispatcherServlet
查找适当的处理程序映射(handler mapping)并测试找到的处理程序(handler)是否实现LastModified接口。如果是,则LastModified
接口的long getLastModified(request)
方法的值将返回给客户端。
您可以通过将Servlet初始化参数(init-param元素
)添加到web.xml
文件中的Servlet声明来自定义单个DispatcherServlet
实例。请参阅下表以获取支持的参数列表。
Parameter | 说明 |
---|---|
contextClass | 实现WebApplicationContext 的类,它实例化此Servlet 使用的上下文。 默认情况下,使用XmlWebApplicationContext 。 |
contextConfigLocation | 传递给上下文实例(由contextClass 指定)的字符串,用于指示可以找到上下文的位置。 该字符串可能包含多个字符串(使用逗号作为分隔符)以支持多个上下文。如果多个上下文位置中定义了两次bean ,最新的位置优先。 |
namespace | WebApplicationContext 的命名空间。 默认为[servlet-name] -servlet 。 |
throwExceptionIfNoHandlerFound | 当找不到处理请求的handler 时是否抛出NoHandlerFoundException 。 然后可以用HandlerExceptionResolver 捕获异常,例如:通过@ExceptionHandler 控制器方法,并像其他handler 一样进行处理。 默认情况下,它被设置为“false” ,在这种情况下,DispatcherServlet 将响应状态设置为404(NOT_FOUND) 而不引发异常。 请注意:如果还配置了default servlet 处理,则未解析的请求将始终转发到default servlet ,并且永远不会引发404 。 |
1.2.6.Interception - 拦截器
所有的HandlerMapping
实现都支持处理程序拦截器,当你想要将特定功能应用于某些请求时,例如,检查委托人。拦截器(Interceptor)必须使用三种方法来实现org.springframework.web.servlet
包中的HandlerInterceptor
,这些方法应该提供足够的灵活性来执行各种预处理(pre-processing)和后处理(post-processing):
preHandle(..)
— 在实际的处理程序(handler)执行之前postHandle(..)
— 在实际的处理程序(handler)执行之后afterCompletion(..)
— 在完成请求完成后
preHandl()
方法返回一个布尔值。您可以使用此方法来中断或继续处理程序执行链。当此方法返回true
时,处理程序执行链将继续; 当它返回false
时,DispatcherServlet
假定拦截器本身已经处理请求(并且例如呈现适当的视图)并且不继续执行执行链中的其他拦截器和实际处理器。
有关如何配置拦截器的示例,请参阅MVC Config一节中的Interceptors。 您也可以通过单个HandlerMapping
实现上的setters直接注册它们。
注意:postHandle
对于@ResponseBody
和ResponseEntity
方法不太管用(因为在HandlerAdapter
和postHandle
之前就已经写入和提交response
)。这意味着对response
进行任何更改都为时已晚,例如添加额外的header
。对于这种场景,你可以实现ResponseBodyAdvice
,并将其声明为Controller Advice bean
或直接在RequestMappingHandlerAdapter
上进行配置。
1.2.7.Exceptions - 异常
如果在请求映射期间发生异常或从请求处理程序handler(如@Controller
)抛出异常,DispatcherServlet
委托HandlerExceptionResolver
bean链来解决异常并提供替代处理,这通常是错误响应。
下表列出了可用的HandlerExceptionResolver
实现:
HandlerExceptionResolver | 描述 |
---|---|
SimpleMappingExceptionResolver | 异常类名称和错误视图名称之间的映射。 用于在浏览器应用程序中呈现错误页面。 |
DefaultHandlerExceptionResolver | 解决Spring MVC 引发的异常并将它们映射到HTTP状态代码。 另请参阅其他ResponseEntityExceptionHandler 和 REST API exceptions |
ResponseStatusExceptionResolver | 使用@ResponseStatus 注解解决异常,并根据注解中的值将它们映射到HTTP 状态代码。 |
ExceptionHandlerExceptionResolver | 通过在@Controller 或@ControllerAdvice 类中调用@ExceptionHandler 方法来解决异常。 请参阅 @ExceptionHandler methods. |
Chain of resolvers - 异常解析器链
你可以通过在Spring配置中声明多个HandlerExceptionResolver
bean并根据需要设置它们的顺序属性来形成异常解析链(exception resolver chain)。 order
属性越高,异常解析器位置越靠后。
HandlerExceptionResolver
的约定指定它可以返回:
ModelAndView
:指向错误视图的ModelAndView
。- 如果在解析器中已经处理过异常,则返回empty的
ModelAndView
。 - 如果异常未解决,则返回
null
,供后续解析器尝试解决;如果异常在最后仍然为处理,它可以冒泡到Servlet容器。
MVC Config 自动为默认的Spring MVC异常,为@ResponseStatus
注解修饰的异常,为支持@ExceptionHandler
方法 声明了内置的解析器(resolver)。你可以自定义该列表或将其替换。
Container error page - 容器错误页面
如果一个异常未被任何HandlerExceptionResolver
解决并因此传播,或者响应状态(response status)设置为错误状态(即4xx,5xx
),则Servlet容器可能会在HTML中呈现默认错误页面。要自定义容器的默认错误页面,可以在web.xml
中声明错误页面映射:
<error-page>
<location>/error</location>
</error-page>
鉴于上述情况,当异常冒泡时,或者响应具有错误状态时,Servlet容器在容器内将ERROR分派(dispatch)到配置的URL(例如“/ error”)。然后由DispatcherServlet
进行处理,将其映射到一个@Controller
,该实现可以通过model返回错误视图名称或呈现JSON响应,如下所示:
@RestController
public class ErrorController {
@RequestMapping(path = "/error")
public Map<String, Object> handle(HttpServletRequest request) {
Map<String, Object> map = new HashMap<String, Object>();
map.put("status", request.getAttribute("javax.servlet.error.status_code"));
map.put("reason", request.getAttribute("javax.servlet.error.message"));
return map;
}
}
Servlet API
不提供在Java
中创建错误页面映射的方法。 但是,您可以同时使用WebApplicationInitializer
和minimal
的web.xml
。
1.2.8. View Resolution - 视图解析器
Spring MVC定义了ViewResolver
和View
接口,使您可以在浏览器中呈现模型(视图),而无需绑定到特定的视图技术。 ViewResolver
提供了视图名称和实际视图之间的映射。View
负责在交付给特定视图技术之前准备好处理数据。
下表是ViewResolver
的层次结构:
ViewResolver | 说明 |
---|---|
AbstractCachingViewResolver | AbstractCachingViewResolver 的子类可以缓存它们所解析的视图实例。这种缓存机制提高了某些视图技术的性能。 如果我们不想使用缓存机制,可以将缓存属性设置为false来关闭缓存。此外,如果想在运行时刷新某些视图(例如,在修改FreeMarker 模板时),则可以使用removeFromCache(String viewName,Locale loc) 方法清除缓存。 |
XmlViewResolver | XmlViewResolver 是ViewResolver 接口的实现类,它可以用XML 文件配置,配置文件的限定与Spring 的bean 文件使用相同的DTD 。 默认的配置文件是/WEB-INF/views.xml 。 |
ResourceBundleViewResolver | ResourceBundleViewResolver 是 ViewResolver 接口的实现类,它使用ResourceBundle 中的 bean 定义,由 bundle 的base name 指定,对于它应该解析的每个视图,它使用属性[viewname] 的值。(class) 作为视图类,并将property [viewname] .url 的值作为视图url 。参考View Technologies |
UrlBasedViewResolver | ViewResolver 接口的简单实现类,在没有明确映射的情况下,该接口起着逻辑视图名称到 URL 的直接解析的作用。 如果逻辑名称以直观的方式与视图资源的名称匹配,则不需要任何映射。 |
InternalResourceViewResolver | UrlBasedViewResolver 的便捷子类,支持InternalResourceView (对 Servlet 和JSP 有效)及其子类(如JstlView 和TilesView )。你可以使用setViewClass() 方法为由此解析器生成的所有视图指定视图类。 |
FreeMarkerViewResolver | UrlBasedViewResolver 的便捷子类,支持FreeMarkerView 和它们的自定义子类。 |
ContentNegotiatingViewResolver | ViewResolver 接口的实现类,可实现基于请求文件名或 Accept 头解析视图。参考 Content negotiation. |
Handing - 处理规则
声明多个解析器的bean实例会产生一个视图解析器链(view resolver chain),可以设置order
属性来指定排序。优先级属性越高,该视图解析器在链中的位置越靠后(也就是解析顺序靠后)。
根据ViewResolver
所遵守的约定:如果ViewResolver
无法找到视图(view)会返回null。但是,对于JSP和InternalResourceViewResolver
,确定JSP是否存在的唯一方法是通过RequestDispatcher
执行分派(dispatch)。因此,必须始终将InternalResourceViewResolver
配置为视图解析器链中的最后一个。
配置视图解析器和把ViewResolver
的 bean添加到Spring的配置一样。 MVC Config为View Resolvers提供了一套专用的配置API,并且还可用于添加无逻辑的View Resolvers,这些View Controller
无需控制器逻辑即可用于HTML模板渲染。
Redirecting - 重定向
redirect
:视图名称中加前缀redirect则允许执行重定向。UrlBasedViewResolver
(和子类)将此识别为需要重定向的指令。视图名称的其余部分是重定向URL。
实际效果与控制器返回一个RedirectView
的效果相同,但现在控制器本身可以简单地按逻辑视图名称操作。 一个逻辑视图名称(如redirect:/ myapp / some / resource)
将相对于当前的Servlet context上下文重定向,而名称(如redirect:http://myhost.com/some/arbitrary/path)
将重定向到绝对URL。
注意,如果控制器方法使用@ResponseStatus
进行注解,则注解值对与响应状态(response status)的设置优先于RedirectView
的设置。
Forwarding - 转发规则
forward
:在逻辑视图名称中加此前缀也能实现转发。拥有forward前缀的视图名称将被UrlBasedViewResolver
和子类解析。这样的话会创建一个执行RequestDispatcher.forward()
方法的InternalResourceView
。因此,对于InternalResourceViewResolver
和InternalResourceView(对于JSP)
,此前缀不起作用(因为如果是InternalResourceViewResolver
或JSP
,根据handing
中的约定,会由RequestDispatcher
执行dispatch),但如果使用其他视图技术,但仍希望强制转发资源被Servlet / JSP引擎所处理,可以使用forward:前缀。注意:这种情况也支持链接多个视图解析器。
Content negotiation
ContentNegotiatingViewResolver不会自行解析视图,而是委托给其他视图解析器,并选择视图,该视图类似于由客户端请求的representation(表示)。该representation(表示)从Accept
header或查询参数确定,例如:"/path?format=pdf"
。
ContentNegotiatingViewResolver
会选择适当的View
来处理请求,通过将请求的media type(s)与ViewResolvers
关联的View
所支持的media type(s)(也称为Content-Type
)进行比较。 具有兼容性的Content-Type
视图列表中的第一个视图(view)把representation(表示)
返回给客户端。如果ViewResolver
链无法提供兼容性视图,则会查看通过DefaultViews
属性指定的视图列表。这种选项适用于单例视图,该视图可以呈现当前资源的适当representation(表示),而不管逻辑视图名称如何。什么是兼容性的Content-Type
: Accept header
可能包含通配符,例如text / *
,在这种情况下,其Content-Type
为text / xml
的View
是兼容性匹配。
See View Resolvers under MVC Config for configuration details.