暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

SpringBoot:RegistrationBean 子类方式实现 Filter、Servlet、Listener

原创 wpp 2023-04-09
456

原文地址blog.csdn.net/u010922732/…

关键技术

之前我们介绍了 Springboot 如何通过注解方式实现 Filter、Servlet、Listener 组件的功能,除此之外还有另一种通过创建RegistrationBean相应子类,借助@Bean注解将自定义组件注册到容器中的方法,一起来看下。

Springboot 提供了三个RegistrationBean的子类用于注册 Filter、Servlet、Listener 组件:

  • FilterRegistrationBean
  • ServletRegistrationBean
  • ServletListenerRegistrationBean

准备工作

1. 配置 POM 依赖

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>com.sdsj</groupId>
  <artifactId>springboot</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <packaging>jar</packaging>

  <name>springboot</name>
  <description>Demo project for Spring Boot</description>

  <parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.1.5.RELEASE</version>
  </parent>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
    <java.version>1.8</java.version>
  </properties>

  <!-- Add typical dependencies for a web application -->
  <dependencies>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-test</artifactId>
      <scope>test</scope>
    </dependency>
  </dependencies>

  <!-- Package as an executable jar -->
  <build>
    <plugins>
      <plugin>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-maven-plugin</artifactId>
      </plugin>
    </plugins>
  </build>
</project>
复制代码

2. 创建启动类和控制器

为了方便,我将启动类和控制器放在一起,如下:

package com.sdsj.springboot;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@SpringBootApplication
    @RestController
    public class SpringbootApplication {

        public static void main(String[] args) {
            SpringApplication.run(SpringbootApplication.class, args);
        }

        @RequestMapping("/")
        public String index() {
            System.out.println("This is index page");
            return "Welcome!";
        }

    }
复制代码

在启动类上添加了两个注解:@SpringBootApplication@RestController

创建 Filter、Servlet、Listener 类

1. 创建 Filter 类

package com.sdsj.springboot.config;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;

/** * 过滤器 * * @author zjhuang * @create 2019/6/4 15:21 **/
public class SecondFilter implements Filter {

    private Logger log = LoggerFactory.getLogger(this.getClass());

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        log.info("second filter init, filter name: " + filterConfig.getFilterName());
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        log.info("second filter uri: " + ((HttpServletRequest) servletRequest).getServletPath());
        filterChain.doFilter(servletRequest, servletResponse);
    }

    @Override
    public void destroy() {
        log.info("second filter destroy");
    }
}
复制代码

2. 创建 Servlet 类

package com.sdsj.springboot.config;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;

/** * 自定义Servlet * * @author zjhuang * @create 2019/6/4 17:13 **/
public class SecondServlet extends HttpServlet {

    private Logger log = LoggerFactory.getLogger(this.getClass());

    @Override
    public void init(ServletConfig servletConfig) throws ServletException {
        log.info("second servlet init, servlet name: " + servletConfig.getServletName());
    }

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        log.info("second servlet uri: " + req.getServletPath());
        PrintWriter out = resp.getWriter();
        out.write("second servlet is running");
        out.flush();
    }

    @Override
    public void destroy() {
        log.info("second servlet destroy");
    }
}
复制代码

3. 创建 Listener 类

package com.sdsj.springboot.config;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.servlet.ServletRequestEvent;
import javax.servlet.ServletRequestListener;
import javax.servlet.http.HttpServletRequest;

/** * 监听器 * * @author zjhuang * @create 2019/6/4 15:21 **/
public class SecondListener implements ServletRequestListener {

    private Logger log = LoggerFactory.getLogger(this.getClass());

    @Override
    public void requestDestroyed(ServletRequestEvent sre) {
        HttpServletRequest request = (HttpServletRequest) sre.getServletRequest();
        log.info("second listener has sent response, uri: " + request.getServletPath());
    }

    @Override
    public void requestInitialized(ServletRequestEvent sre) {
        HttpServletRequest request = (HttpServletRequest) sre.getServletRequest();
        log.info("second listener has received request, uri: " + request.getServletPath());
    }

}
复制代码

注册 Filter、Servlet、Listener

package com.sdsj.springboot.config;

import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.boot.web.servlet.ServletListenerRegistrationBean;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.servlet.Filter;
import javax.servlet.Servlet;
import java.util.EventListener;

/** * 全局配置类 * * @author zjhuang * @create 2019/6/5 17:39 **/
@Configuration
    public class Config {

        /** * 注册一个Filter * * @return FilterRegistrationBean */
        @Bean
        public FilterRegistrationBean registerFilter() {
            // 创建Filter注册Bean
            FilterRegistrationBean<Filter> registration = new FilterRegistrationBean<>();
            // 创建自定义的Filter对象
            SecondFilter filter = new SecondFilter();
            // 注册Filter
            registration.setFilter(filter);
            // 设置Filter名称
            registration.setName("second_filter");
            // 设置Fliter匹配规则
            registration.addUrlPatterns("/*");
            // 设置排序,在存在多个Filter实例的情况下确定Filter的执行顺序
            registration.setOrder(1);
            return registration;
        }


        /** * 注册一个Servlet * * @return ServletRegistrationBean */
        @Bean
        public ServletRegistrationBean registerServlet() {
            // 创建Servlet注册Bean
            ServletRegistrationBean<Servlet> registration = new ServletRegistrationBean<>();
            // 创建自定义的Servlet对象
            SecondServlet servlet = new SecondServlet();
            // 注册Servlet
            registration.setServlet(servlet);
            // 设置Servlet名称
            registration.setName("second_servlet");
            // 设置Servlet配置规则
            registration.addUrlMappings("/second_servlet");
            // 设置加载参数
            registration.setLoadOnStartup(1);
            return registration;
        }

        /** * 注册一个Listener * * @return ServletListenerRegistrationBean */
        @Bean
        public ServletListenerRegistrationBean registerListener() {
            // 创建Listener注册Bean
            ServletListenerRegistrationBean<EventListener> registration = new ServletListenerRegistrationBean<>();
            // 创建自定义的Listener对象
            SecondListener listener = new SecondListener();
            // 注册Listener
            registration.setListener(listener);
            // 设置排序,在存在多个Listener实例的情况下确定Listener的执行顺序
            registration.setOrder(1);
            return registration;
        }

    }
复制代码

扩展

Spring Boot 为了方便大家向 Servlet 容器中注册 Servlet、Filter 以及 Listener,提供了一个 Bean 注册的抽象类RegistrationBean,如下:

public abstract class RegistrationBean implements ServletContextInitializer, Ordered {
	private int order = Ordered.LOWEST_PRECEDENCE;
	private boolean enabled = true;
	@Override
	public final void onStartup(ServletContext servletContext) throws ServletException {
		String description = getDescription();
		if (!isEnabled()) {
			logger.info(StringUtils.capitalize(description) + " was not registered (disabled)");
			return;
		}
		register(description, servletContext);
	}
	protected abstract String getDescription();
	protected abstract void register(String description, ServletContext servletContext);
	public void setEnabled(boolean enabled) {
		this.enabled = enabled;
	}
	public boolean isEnabled() {
		return this.enabled;
	}
	public void setOrder(int order) {
		this.order = order;
	}
	@Override
	public int getOrder() {
		return this.order;
	}

}
复制代码

RegistrationBean 实现了 ServletContextInitializer 接口,在 Servlet 启动时,RegistrationBean#onStartup 方法会被调用,进而完成 Filter、Servlet 以及 Listener 的注册。

SprinngBoot提供了如下所示的RegistrationBean实现类:

  • ServletListenerRegistrationBean 用来注册监听器。
  • ServletRegistrationBean 用来注册 Servlet。
  • DispatcherServletRegistrationBean 用来注册 DispatcherServlet。
  • FilterRegistrationBean 用来注册过滤器。
  • DelegatingFilterProxyRegistrationBean 则用来注册 DelegatingFilterProxy,DelegatingFilterProxy 在 Spring Security、Spring Session、Shiro 等整合时非常有用。
「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论