一、组件注册方式整合Servlet

1.创建自定义Servlet类

在chapter05项目中的com.cy.servletComponent包中,我们创建一个继承了HttpServlet的类MySevlet

package com.cy.servletComponent;
import org.springframework.stereotype.Component;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/** 自定义Servlet类 */
@Component
public class MyServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        this.doPost(req, resp);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.getWriter().write("Hello MyServlet");
    }
}

2.创建Servlet组件配置类

在项目com.cy.config包中,我们可以创建一个Servlet组件配置类ServletConfig,用来对Servlet相关组件进行注册。

package com.cy.config;
import com.cy.servletComponent.MyServlet;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/** 嵌入式Servlet容器三大组件配置 */
@Configuration
public class ServletConfig {
    /** 注册Servlet组件 */
    @Bean
    public ServletRegistrationBean getServlet(MyServlet myServlet) {
        ServletRegistrationBean registrationBean = new ServletRegistrationBean(myServlet, "/myServlet");
        return registrationBean;
    }
}

3.启动项目进行测试

项目启动成功后,在浏览器上访问http://localhost:8080/myServlet查看数据显示。


SpringBoot中Servlet_自定义

二、使用组件注册方式整合Filter

1.创建自定义Filter类

我们可以在com.cy.servletComponent包下创建一个类MyFilter

package com.cy.servletComponent;
import org.springframework.stereotype.Component;
import javax.servlet.*;
import java.io.IOException;

/** 自定义Filter类 */
@Component
public class MyFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        System.out.println("Hello Filter");
        filterChain.doFilter(servletRequest, servletResponse);
    }

    @Override
    public void destroy() {
    }
}

2.向Servlet组件配置类注册自定义Filter类

打开之前创建的Servlet组件配置类ServletConfig,将该自定义Filter类使用组件注册方式进行注册。

/** 注册Filter组件 */
@Bean
public FilterRegistrationBean getFilter(MyFilter myFilter) {
    FilterRegistrationBean registrationBean = new FilterRegistrationBean(myFilter);
    registrationBean.setUrlPatterns(Arrays.asList("/myFilter", "/toLoginPage"));
    return registrationBean;
}

3.请求测试

项目启动成功后,在浏览器上访问http://localhost:8080/myFilter查看控制台打印效果(这里由于我们没有编写对应路径的请求处理方法,所以浏览器会现404错误页面,这里重点关注控制台即可)。


SpringBoot中Servlet_spring_02

控制台会输出如下结果:


SpringBoot中Servlet_java_03

三、使用组件注册方式整合Listener

1.创建自定义Listener类

我们可以在com.cy.servletComponent包下创建一个类MyListener

package com.cy.servletComponent;
import org.springframework.stereotype.Component;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;

/** 自定义Listener类 */
@Component
public class MyListener implements ServletContextListener {
    @Override
    public void contextInitialized(ServletContextEvent sce) {
        System.out.println("contextInitialized()...");
    }

    @Override
    public void contextDestroyed(ServletContextEvent sce) {
        System.out.println("contextDestroyed()...");
    }
}

2.向Servlet组件配置类注册自定义Listener类

我们可以打开之前创建的Servlet组件配置类ServletConfig,将该自定义Listener类使用组件注册方式进行注册。

/** 注册Listener组件 */
@Bean
public ServletListenerRegistrationBean getListener(MyListener myListener) {
    ServletListenerRegistrationBean registrationBean = new ServletListenerRegistrationBean(myListener);
    return registrationBean;
}

需要说明的是,Servlet容器提供了很多Listener接口,例如ServletRequestListener、HttpSessionListener、ServletContextListener 等,我们在自定义Listener类时要根据自身需求选择实现对应接口即可。

3.执行效果

完成自定义Listener组件注册后启动项目,项目启动成功后查看控制台打印效果。


SpringBoot中Servlet_java_04

单击IDEA工具控制台左侧的[Exit]按钮,就可以关闭当前项目。注意,如果我们直接单击红色按钮会强制关闭程序,浏览器就无法打印关闭监听信息,再次查看控制台打印效果。


SpringBoot中Servlet_自定义_05

将自定义的Servlet组件配置类ServletConfig全部注释并重启项目后,自定义的Servlet、Filter、Listener组件仍然生效。出现这种情况的主要原因是:嵌入式Servlet容器对Servlet、Filter、Listener组件进行了自动化识别和配置,而自定义的Servlet、Filter、Listener都继承/实现了对应的类/接口,同时自定义的Servlet、Filter、Listener组件都使用了@Component注解,这些组件会被自动扫描Spring组件

使用ServletRegistrationBean、FilterRegistrationBean、ServletListenerRegistrationBean组件组装配置的根本目的是对一些请求路径和参数进行初始化设置和组装。假设没有组件注册类,那么自定义Servlet虽然生效,但无法确定是哪个访问路径生效。自定义的Filter会对所有的请求都进行过滤,不会出现选择性过滤的情况。而自定义的Listener则没有太大影响,因为定制该组件基本不需要设置什么参数。

四、路径扫描整合Servlet三大组件

在Spring Boot中,使用路径扫描的方式整合内嵌式Servlet 容器的Seviet Fiter 、Lste三大组件时,首先需要在自定义组件上分别添加WebSevle. @WebFiter和Weblistene注解进行声明,并配置相关注解属性,然后在项目主程序启动类上使用@SerletComponentScan 注解开启组件扫描即可。

1.使用路径扫描方式整合Servlet、Filter、Listener。

为了简化操作,在上小节自定义组件的基础上,我们使用路径扫描的方式来实现Servlet容器的Servlet、Filter、Listener三大组件的整合。

为了避免与之前编写的使用组件注册的方式相互干扰,先将之前自定义的Servlet组件配置类ServletConfig全部注释掉,同时注释掉自定义Servlet、Filter、Listener三大组件类上的@Component注解。

注释掉自定义MyServlet组件类上的@Component注解,在MyServlet组件中使用@WebServlet注解声明并配置相关属性。

/** 自定义Servlet类 */
//@Component
@WebServlet("/annotationServlet")
public class MyServlet extends HttpServlet {
    // ...
}

然后注释掉自定义MyFilter组件类上的@Component注解,在MyFilter组件中使用@WebFilter注解声明并配置相关属性。

/** 自定义Filter类 */
//@Component
@WebFilter(value = {"/annotationLogin", "/annotationMyFilter"})
public class MyFilter implements Filter {
    // ...
}

注释掉自定义MyListener组件类上的@Component注解,在MyListener组件中使用@WebListener注解声明并配置相关属性。

/** 自定义Listener类 */
//@Component
@WebListener
public class MyListener implements ServletContextListener {
    // ...
}

使用相关注解配置好自定义三大组件后,需在项目主程序启动类上添加@ServletComponentScan注解,开启基于注解方式的Servlet组件扫描支持。

package com.cy;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.ServletComponentScan;

@ServletComponentScan // 开启基于注解方式的Servlet组件扫描支持
@SpringBootApplication
public class Chapter05Application {
    public static void main(String[] args) {
        SpringApplication.run(Chapter05Application.class, args);
    }
}

2.效果测试

启动项目,项目启动成功后查看控制台打印效果。


SpringBoot中Servlet_自定义_06

然后我们在浏览器上访问http://localhost:8080/annotationServlet进行测试。


SpringBoot中Servlet_java_07

接着在浏览器上访问http://localhost:8080/annotationMyFilter查看控制台打印效果。


SpringBoot中Servlet_java_08

单击IDEA工具控制台左侧的[Exit]按钮关闭当前项目,再次查看控制台打印效果。


SpringBoot中Servlet_自定义_09

回顾总结

关于Spring Boot整合Servlet三大组件,袁老师就给大家分享完了。首先,袁老师给大家介绍了SpringBoot框架整合Servlet、Filter和Listener三大核心组件;然后介绍了通过SpringBoot路径扫描整合Servlet三大组件的实现方式;最后我们通过功能测试验证是否整合成功。