翻译自:https://howtodoinjava.com/spring5/webmvc/spring-dispatcherservlet-tutorial/
一、Spring DispatcherServlet 教程示例
在本教程中, 我们将学习 Spring 的DispatcherServlet类, 它的职责以及如何用示例来配置它。
二、DispatcherServlet是什么
DispatcherServlet充当基于 Spring 的 web 应用程序的前端控制器。它为请求处理提供了一种机制, 通过可配置的委托组件来执行实际工作。它是从javax.servlet.http.HttpServlet继承的, 它通常在web.xml文件中进行配置。
web 应用程序可以定义任意数量的DispatcherServlet实例。每个 servlet 都将在其自己的命名空间中运行, 并使用映射、处理程序等加载自己的应用程序上下文。只有ContextLoaderListener加载的根应用程序上下文 (如果有) 将被共享。在大多数情况下, 应用程序只具有上下文根 URL(/)的单个DispatcherServlet , 即所有进入该域的请求都将由它处理。
DispatcherServlet使用 Spring 配置类来发现它需要的委托组件, 如请求映射、视图解析、异常处理等。
三、如何使用 WebApplicationContext
在基于 Spring 的应用程序中, 我们的应用程序对象位于对象容器中。此容器在对象之间创建对象和关联, 并管理它们的完整生命周期。这些容器对象称为 spring 管理的 bean (或简单的 bean), 并且容器被称为应用程序上下文(通过类ApplicationContext) 在 spring 世界中。
WebApplicationContext是一个普通ApplicationContext的延伸。它是网络感知ApplicationContext , 它具有 Servlet 上下文信息。加载DispatcherServlet时, 它会查找WebApplicationContext的 bean 配置文件并对其进行初始化。
通过访问 Servlet 上下文, 任何实现ServletConextAware接口的 spring bean 都可以访问ServletContext实例并使用它进行许多操作。例如, 它可以获取上下文初始化参数, 获取上下文根信息, 并在 web 应用程序文件夹中获取资源位置
基于 XML 的 DispatcherServlet 配置
我们来看看一个典型的DispatcherServlet声明和初始化的样子。
web. xml
org.springframework.web.context.ContextLoaderListener
contextConfigLocation
/WEB-INF/dispatcher-servlet-context.xml
dispatcher-servlet
org.springframework.web.servlet.DispatcherServlet
contextConfigLocation
1
dispatcher-servlet
/*
在上面的代码中,dispatcher-servlet-context.xml文件将包含将可用于DispatcherServlet的所有 bean 定义和关联。这些 bean 定义将覆盖在全局范围内定义的任何 bean 的定义。例如
applicationContext.xml
/WEB-INF/views/
.jsp
DispatcherServlet 基于 Java 的配置
从 Servlet 3.0 开始, 除了web.xml文件中的声明性配置外, 还可以通过实现或扩展由 Spring 提供的这三个支持类中的任何一个来以编程方式配置 DispatcherServlet-
WebAppInitializer接口
AbstractDispatcherServletInitializer抽象类
AbstractAnnotationConfigDispatcherServletInitializer抽象类
WebAppInitializer 示例
在下面的类中, WebApplicationInitializer确保SpringServletContainerInitializer检测到类ApplicationInitializer (它本身是自动引导的) 并用于初始化任何 Servlet 3容器。
ApplicationInitializer. java
public class ApplicationInitializer implements WebApplicationInitializer
{
@Override
public void onStartup(ServletContext servletContext) throws ServletException
{
XmlWebApplicationContext appContext = new XmlWebApplicationContext();
appContext.setConfigLocation("/WEB-INF/dispatcher-servlet-context.xml");
ServletRegistration.Dynamic registration = servletContext
.addServlet("rootDispatcher", new DispatcherServlet(appContext));
registration.setLoadOnStartup(1);
registration.addMapping("/");
}
}
完整的基于 Java 的初始化
public class ApplicationInitializer implements WebApplicationInitializer
{
@Override
public void onStartup(ServletContext container)
{
// Create the 'root' Spring application context
AnnotationConfigWebApplicationContext rootContext = new AnnotationConfigWebApplicationContext();
rootContext.register(AppConfig.class);
// Manage the lifecycle of the root application context
container.addListener(new ContextLoaderListener(rootContext));
// Create the dispatcher servlet's Spring application context
AnnotationConfigWebApplicationContext dispatcherContext = new AnnotationConfigWebApplicationContext();
dispatcherContext.register(DispatcherConfig.class);
ServletRegistration.Dynamic dispatcher = container.addServlet("dispatcher",
new DispatcherServlet(dispatcherContext));
dispatcher.setLoadOnStartup(1);
dispatcher.addMapping("/");
}
}
在上面的代码中, AppConfig和DispatcherConfig类定义了将在 web 应用程序上下文中使用的 spring 托管 bean。
AbstractDispatcherServletInitializer 示例
这是在 servlet 上下文中注册DispatcherServlet的WebApplicationInitializer实现的基类。
ApplicationInitializer. java
public class ApplicationInitializer extends AbstractDispatcherServletInitializer {
@Override
protected WebApplicationContext createRootApplicationContext() {
return null;
}
@Override
protected WebApplicationContext createServletApplicationContext() {
XmlWebApplicationContext cxt = new XmlWebApplicationContext();
cxt.setConfigLocation("/WEB-INF/dispatcher-servlet-context.xml");
return cxt;
}
@Override
protected String[] getServletMappings() {
return new String[] { "/" };
}
//Register filters
@Override
protected Filter[] getServletFilters() {
return new Filter[] { new HiddenHttpMethodFilter(), new CharacterEncodingFilter() };
}
}
请注意, 如果需要自定义DispatcherServlet, 可以重写createDispatcherServlet()方法。
AbstractAnnotationConfigDispatcherServletInitializer 示例
这个类扩展了AbstractDispatcherServletInitializer , 并做了一些隐含的事情, 否则你可以做自己。一个额外的优点是您现在可以使用 Spring 提供的方便类, 而不是手动配置DispatcherServlet和/或ContextLoaderListener.
它是使用基于 Java 的 Spring 配置的应用程序的首选方法。它使您可以启动 servlet 应用程序上下文和根应用程序上下文。
AppInitializer. java
public class AppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
@Override
protected Class>[] getRootConfigClasses() {
return new Class[] { RootConfig.class };
}
@Override
protected Class>[] getServletConfigClasses() {
return new Class[] { WebMvcConfig.class };
}
@Override
protected String[] getServletMappings() {
return new String[] { "/" };
}
}
AbstractAnnotationConfigDispatcherServletInitializer会同时创建DispatcherServlet和ContextLoaderListener。
GetServlet-ConfigClasses()方法返回的带有@Configuration注解的类将会用来定义DispatcherServlet应用上下文中的bean。 getRootConfigClasses()方法返回的带有@Configuration注解的类将会用来配置ContextLoaderListener创建的应用上下文中的bean。
Upon receiving a web request, DispatcherServlet
performs a set of operations for request processing. It used a set of supporting beans for this. This table lists these default configured beans and their responsibilities –
Bean | Responsibilities |
---|---|
HandlerMapping |
Maps incoming web requests to handlers and pre- and post-processors |
HandlerAdapter |
Invokes the handler which resolves arguments and dependencies, such as annotated arguments for URL-mapped controller method endpoints |
HandlerExceptionResolver |
Allows programmatic handling of exceptions and maps exceptions to views |
ViewResolver |
Resolves logical view names to view instances |
LocaleResolver |
Resolves the client’s locale in order to enable internationalization |
LocaleContextResolver |
A richer extension of LocaleResolver , with timezone information |
ThemeResolver |
Resolves themes configured in your app for enhanced user experience |
MultipartResolver |
Handles multipart file uploads as part of HTTP requests |
FlashMapManager |
Manages FlashMap instances that store temporary Flash attributes between requests redirected from one another |
DispatcherServlet 演示
为了演示DispatcherServlet的使用, 我编写了一个非常最低的应用程序, 它只配置调度程序 servlet 并重写视图解析器 bean。
项目结构
Spring5 MVC 项目结构
AppInitializer. java
package com.howtodoinjava.demo.spring.config;
public class AppInitializer extends
AbstractAnnotationConfigDispatcherServletInitializer {
@Override
protected Class>[] getRootConfigClasses() {
return new Class[] { };
}
@Override
protected Class>[] getServletConfigClasses() {
return new Class[] { WebMvcConfig.class };
}
@Override
protected String[] getServletMappings() {
return new String[] { "/" };
}
}
WebMvcConfig. java
@Configuration
@EnableWebMvc
@ComponentScan(basePackages = { "com.howtodoinjava.demo.spring"})
public class WebMvcConfig implements WebMvcConfigurer {
@Bean
public InternalResourceViewResolver resolver() {
InternalResourceViewResolver resolver = new InternalResourceViewResolver();
resolver.setViewClass(JstlView.class);
resolver.setPrefix("/WEB-INF/views/");
resolver.setSuffix(".jsp");
return resolver;
}
}
HomeController.java
@Controller
public class HomeController
{
@GetMapping("/")
public String homeInit(Locale locale, Model model) {
return "home";
}
}
home. jsp
Spring 5 Web MVC Example
HowToDoInJava.com
Spring 5 Web MVC DispatcherServlet Example
pom.xml
4.0.0
com.howtodoinjava.spring5.mvc
spring5-webmvc-demo
war
0.0.1-SNAPSHOT
spring5-webmvc-demo Maven Webapp
http://maven.apache.org
false
5.0.0.RELEASE
1.2.1
1.1.2
3.1.0
2.3.1
org.springframework
spring-webmvc
${spring.version}
javax.servlet.jsp.jstl
javax.servlet.jsp.jstl-api
${jstl.version}
taglibs
standard
${tld.version}
javax.servlet
javax.servlet-api
${servlets.version}
provided
javax.servlet.jsp
javax.servlet.jsp-api
${jsp.version}
provided
src/main/java
src/main/resources
maven-compiler-plugin
3.5.1
1.8
org.apache.tomcat.maven
tomcat7-maven-plugin
2.2
/
Run the application
To run the application execute maven goal : tomcat7:run. Now open http://localhost:8080
in browser.