51工具盒子

依楼听风雨
笑看云卷云舒,淡观潮起潮落

Spring Boot 中的 DispatcherServlet 和 web.xml

1、概览 {#1概览}

DispatcherServlet 是 Spring Web 应用的前端控制器(Front Controller)。它用于在 Spring MVC 中创建 Web 应用和 REST 服务。在传统的 Spring Web 应用中,该 Servlet 是在 web.xml 文件中定义的。

本文将会带你了解如何在 Spring Boot 项目中配置 DispatcherServlet,以及如何配置 web.xml 中的 FilterServletListener

2、Maven 依赖 {#2maven-依赖}

首先,在 pom.xml 文件中添加 spring-boot-starter-web Maven 依赖:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

3、DispatcherServlet {#3dispatcherservlet}

DispatcherServlet 接收所有 HTTP 请求,并将其调度给 Controller 类。

在 Servlet 3.x 规范发布之前,DispatcherServlet 会在 Spring MVC 应用的 web.xml 文件中注册。自 Servlet 3.x 规范发布后,可以使用 ServletContainerInitializer 以编程方式注册 Servlet

web.xml 文件中的 DispatcherServlet 配置示例:

<servlet>
    <servlet-name>dispatcher</servlet-name>
    <servlet-class>
        org.springframework.web.servlet.DispatcherServlet
    </servlet-class>
</servlet>

<servlet-mapping>
    <servlet-name>dispatcher</servlet-name>
    <url-pattern>/</url-pattern>
</servlet-mapping>

Spring Boot 为使用 Spring MVC 开发 Web 应用提供了开箱即用的 spring-boot-starter-web 组件。Spring Boot 的主要功能之一是自动配置。Spring Boot 自动配置会自动注册和配置 DispatcherServlet。因此,我们无需手动注册它。

默认情况下,spring-boot-starter-web Starter 会将 DispatcherServlet 的 URL Pattern 配置为 "/"。因此,无需在 web.xml 文件中为上述 DispatcherServlet 示例进行任何额外配置。不过,你可以在 application.properties 文件中使用 server.servlet.* 自定义 URL Pattern:

server.servlet.context-path=/demo
spring.mvc.servlet.path=/baeldung

如上,DispatcherServlet 的 URL Pattern 配置为 /baeldung,Root ContextPath 是 /demo。因此,DispatcherServlet 会处理 http://localhost:8080/demo/baeldung/ 下的请求。

4、应用配置 {#4应用配置}

Spring MVC Web 应用除了将 web.xml 文件用作部署描述符文件外,它还定义了 FilterServletListener 以及他们对应的 URL 映射。

在 Spring Boot 中则有所更改。当我们想从传统的 Spring MVC 迁移到现代的 Spring Boot 应用时,如何将 web.xml 中配置的组件移植到新的 Spring Boot 应用中呢?在 Spring Boot 应用中,可以通过多种方式添加这些 Servlet 组件。

4.1、注册 Filter {#41注册-filter}

通过实现 Filter 接口来创建一个 Filter

@Component
public class CustomFilter implements Filter {

    Logger logger = LoggerFactory.getLogger(CustomFilter.class);

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
      throws IOException, ServletException {
        logger.info("CustomFilter is invoked");
        chain.doFilter(request, response);
    }

    // 其他方法 
}

如果没有 Spring Boot,则需要在 web.xml 文件中配置 CustomFilter,如下:

<filter>
    <filter-name>customFilter</filter-name>
    <filter-class>CustomFilter</filter-class>
</filter>

<filter-mapping>
    <filter-name>customFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

要让 Spring Boot 加载 Filter,只需要在 Filter 类上注解 @Component,使之成为一个 Spring Bean 即可。

4.2、注册 Servlet {#42注册-servlet}

通过继承 HttpServlet 类来定义一个 servlet:

public class CustomServlet extends HttpServlet {

    Logger logger = LoggerFactory.getLogger(CustomServlet.class);

    @Override
    protected void doGet(
        HttpServletRequest req,
        HttpServletResponse resp) throws ServletException, IOException {
            logger.info("CustomServlet doGet() method is invoked");
            super.doGet(req, resp);
    }

    @Override
    protected void doPost(
        HttpServletRequest req,
        HttpServletResponse resp) throws ServletException, IOException {
            logger.info("CustomServlet doPost() method is invoked");
            super.doPost(req, resp);
    }
}

如果没有 Spring Boot,则需要在 web.xml 文件中配置 CustomServlet,如下:

<servlet>
    <servlet-name>customServlet</servlet-name>
    <servlet-class>CustomServlet</servlet-class>
</servlet>

<servlet-mapping>
    <servlet-name>customServlet</servlet-name>
    <url-pattern>/servlet</url-pattern>
</servlet-mapping>

在 Spring Boot 应用中,Servlet 可以通过以下两种方式进行注册:作为 Spring 的 @Bean 或通过扫描带有嵌入式容器 @WebServlet 注解的类来注册。

可以通过 ServletRegistrationBean 类以 Spring @Bean 的方式来注册 Servlet。

使用 ServletRegistrationBean 类把 CustomServlet 定义为一个 Bean:

@Bean
public ServletRegistrationBean customServletBean() {
    ServletRegistrationBean bean = new ServletRegistrationBean(new CustomServlet(), "/servlet");
    return bean;
}

4.3、注册 Listener {#43注册-listener}

通过继承 ServletContextListener 类来定义一个监听器:

public class CustomListener implements ServletContextListener {

    Logger logger = LoggerFactory.getLogger(CustomListener.class);

    @Override
    public void contextInitialized(ServletContextEvent sce) {
        logger.info("CustomListener is initialized");
    }

    @Override
    public void contextDestroyed(ServletContextEvent sce) {
        logger.info("CustomListener is destroyed");
    }
}

如果没有 Spring Boot,则需要在 web.xml 文件中配置 CustomListener

<listener>
    <listener-class>CustomListener</listener-class>
</listener>

可以使用 @Bean@WebListener 注解在 Spring Boot 应用中定义监听器。

可以通过 ServletListenerRegistrationBean 类以 Spring @Bean 的方式来注册 Listener

使用 ServletListenerRegistrationBean 类将 CustomListener 定义为一个 Bean:

@Bean
public ServletListenerRegistrationBean<ServletContextListener> customListenerBean() {
    ServletListenerRegistrationBean<ServletContextListener> bean = new ServletListenerRegistrationBean();
    bean.setListener(new CustomListener());
    return bean;
}

启动应用后,可以查看日志输出,确认 Listener 已成功初始化:

2020-09-28 08:50:30.872 INFO 19612 --- [main] c.baeldung.demo.listener.CustomListener: CustomListener is initialized

5、总结 {#5总结}

本文介绍了如何在 Spring Boot 应用中定义 DispatcherServletweb.xml 中的元素(包括 FilterServletListener)。


Ref:https://www.baeldung.com/spring-boot-dispatcherservlet-web-xml

赞(2)
未经允许不得转载:工具盒子 » Spring Boot 中的 DispatcherServlet 和 web.xml