ServletContextInitializer添加 servlet filter listener

https://www.cnblogs.com/pomer-huang/p/9639322.html

关于springboot中添加Filter的方法

https://www.jianshu.com/p/3d421fbce734

———————————————————————————————————————————————————————————————

Spring Boot Servlet : ServletContextInitializer

概述

功能介绍

Spring Boot提供的在Servlet 3.0+环境中用于程序化配置ServletContext的接口。该接口ServletContextInitializer主要被RegistrationBean实现用于往ServletContext容器中注册Servlet,Filter或者EventListener。这些ServletContextInitializer的设计目的主要是用于这些实例被Spring IoC容器管理。这些ServletContextInitializer实例不会被SpringServletContainerInitializer检测,因此不会被Servlet容器自动启动。

该接口ServletContextInitializerSpring Web的另外一个接口WebApplicationInitializer看起来几乎一模一样。但二者使用目的不同。Spring Web中,WebApplicationInitializer也是针对Servlet 3.0+环境,设计用于程序化配置ServletContext,跟传统的web.xml相对或者配合使用。WebApplicationInitializer实现类会被SpringServletContainerInitializer自动检测和启动。

继承关系

使用

关于ServletContextInitializer的应用可以参考下面的例子。TomcatStarterSpring Boot Web Servlet应用结合Tomcat使用时的一个ServletContainerInitializer实现。从下面代码不难看出,一组ServletContextInitializer会被设置到ServletContainerInitializer TomcatStarter上,而TomcatStarterServlet容器启动过程中调用自己的方法#onStartup,会逐一调用这些ServletContextInitializer的方法#onStartup初始化ServletContext

package org.springframework.boot.web.embedded.tomcat;

import java.util.Set;

import javax.servlet.ServletContainerInitializer;
import javax.servlet.ServletContext;
import javax.servlet.ServletException; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.springframework.boot.web.servlet.ServletContextInitializer; class TomcatStarter implements ServletContainerInitializer { private static final Log logger = LogFactory.getLog(TomcatStarter.class); // 使用者会指定一组 ServletContextInitializer 给 TomcatStarter
private final ServletContextInitializer[] initializers; private volatile Exception startUpException; TomcatStarter(ServletContextInitializer[] initializers) {
this.initializers = initializers;
} // Servlet 容器启动时回会用该方法,该方法会逐一调用每个 ServletContextInitializer 的方法
// #onStartup 会指定 ServletContext 进行初始化。这些 ServletContextInitializer 的目的
// 通常会是 注册 Servlet, Filter 或者 EventListener 。
@Override
public void onStartup(Set<Class<?>> classes, ServletContext servletContext)
throws ServletException {
try {
for (ServletContextInitializer initializer : this.initializers) {
initializer.onStartup(servletContext);
}
}
catch (Exception ex) {
this.startUpException = ex;
// Prevent Tomcat from logging and re-throwing when we know we can
// deal with it in the main thread, but log for information here.
if (logger.isErrorEnabled()) {
logger.error("Error starting Tomcat context. Exception: "
+ ex.getClass().getName() + ". Message: " + ex.getMessage());
}
}
} public Exception getStartUpException() {
return this.startUpException;
} }

源代码

源代码版本 : 2.1.3.RELEASE

package org.springframework.boot.web.servlet;

import javax.servlet.ServletContext;
import javax.servlet.ServletException; import org.springframework.web.SpringServletContainerInitializer;
import org.springframework.web.WebApplicationInitializer; @FunctionalInterface
public interface ServletContextInitializer { /**
* Configure the given ServletContext with any servlets, filters, listeners
* context-params and attributes necessary for initialization.
* @param servletContext the ServletContext to initialize
* @throws ServletException if any call against the given ServletContext
* throws a ServletException
*/
void onStartup(ServletContext servletContext) throws ServletException; }

参考文章

——————————————————————————————————————————————————————————————————

springboot 2.1.3.RELEASE添加filter,servlet源码学习

 

Servlet规范中,通过ServeltContext来注册Filter、Servlet,这里分析Filter,Servlet是相同逻辑

springboot2.0中,我们通过

FilterRegistrationBean将指定得filter来实现ServeltContext注册filter

1
2
3
4
5
6
7
8
9
10
11
12
13
FilterRegistrationBean的实例化过程
 
public FilterRegistrationBean(T filter, ServletRegistrationBean... servletRegistrationBeans) {
        super(servletRegistrationBeans);
        Assert.notNull(filter, "Filter must not be null");
        this.filter = filter;
}
 
super的实例化
AbstractFilterRegistrationBean(ServletRegistrationBean... servletRegistrationBeans) {
        Assert.notNull(servletRegistrationBeans, "ServletRegistrationBeans must not be null");
        Collections.addAll(this.servletRegistrationBeans, servletRegistrationBeans);
}

可知FilterRegistrationBean得实例化过程就是将Filter保存到servletRegistrationBeans(一个set)中

再分析FilterRegistrationBean类

FilterRegistrationBean的父类是一个ServletContextInitializer,他有一个方法onStartup(ServletContext servletContext)
其结果最终会调用
servletContext.addFilter(this.getOrDeduceName(filter), filter)
现在看看ServletContextInitializer.onStartup的调用地方
1
2
3
4
5
6
7
8
9
10
11
12
springboot启动
new SpringApplication(XXApplication.class).run(XXApplication.class,args)
调用
refreshContext(context); -> refresh(context); -> ((AbstractApplicationContext) applicationContext).refresh();
-> ServletWebServerApplicationContext.onRefresh(); -> createWebServer();
 
WebServer webServer = this.webServer;
ServletContext servletContext = getServletContext();
if (webServer == null && servletContext == null) {
    ServletWebServerFactory factory = getWebServerFactory();
    this.webServer = factory.getWebServer(getSelfInitializer());
}

再分析getSelfInitializer方法

1
2
3
4
prepareWebApplicationContext(servletContext);
        registerApplicationScope(servletContext);
        WebApplicationContextUtils.registerEnvironmentBeans(getBeanFactory(),servletContext);
        for (ServletContextInitializer beans :getServletContextInitializerBeans()) {              
       //调用ServletContextInitializer的onStartup方法
1
beans.onStartup(servletContext);
}
-> getServletContextInitializerBeans()
1
2
-> new ServletContextInitializerBeans(getBeanFactory())
-> addAdaptableBeans(beanFactory)

 

1
2
3
4
5
6
7
8
addAdaptableBeans(ListableBeanFactory beanFactory) 代码如下:
MultipartConfigElement multipartConfig = getMultipartConfig(beanFactory);
//将servlet类的bean包装为ServletRegistrationBean
addAsRegistrationBean(beanFactory, Servlet.class,new ServletRegistrationBeanAdapter(multipartConfig));
//将Filter的bean包装为FilterRegistrationBean
addAsRegistrationBean(beanFactory, Filter.class,new FilterRegistrationBeanAdapter());
for (Class<?> listenerType : ServletListenerRegistrationBean.getSupportedTypes())
{         
addAsRegistrationBean(beanFactory, EventListener.class,(Class<EventListener>) listenerType,new ServletListenerRegistrationBeanAdapter());
}

这里提一下,如果Servlet的bean实例名为dispatcherServlet,且该实例在seen集合中(seen集合为自定义配置的实例,通过ServletContextInitializerBeans.addServletContextInitializerBean入口可以查看源码),则设置默认值为  /

1
2
3
4
5
6
7
String url = (totalNumberOfSourceBeans != 1) ? "/" + name + "/" "/";
if (name.equals(DISPATCHER_SERVLET_NAME)) {
    url = "/"// always map the main dispatcherServlet to "/"
}
ServletRegistrationBean<Servlet> bean = new ServletRegistrationBean<>(source,url); 
bean.setName(name);
bean.setMultipartConfig(this.multipartConfig);
return bean;

 

总结:springboot启动时,会将所有的 FilterRegistrationBean、ServletRegistrationBean以及被spring管理的Servlet和Filter的实例,通过          ServletContext注册Servlet以及Filter

ServletContextInitializer添加 servlet filter listener的更多相关文章

  1. SpringBoot学习笔记(6)----SpringBoot中使用Servlet,Filter,Listener的三种方式

    在一般的运用开发中Controller已经大部分都能够实现了,但是也不排除需要自己实现Servlet,Filter,Listener的方式,SpringBoot提供了三种实现方式. 1. 使用Bean ...

  2. JavaWeb三大组件(Servlet,Filter,Listener 自己整理,初学者可以借鉴一下)

    JavaWeb三大组件(Servlet,Filter,Listener 自己整理,初学者可以借鉴一下) Reference

  3. SpringBoot---注册Servlet,Filter,Listener

    1.概述 1.1.当使用  内嵌的Servlet容器(Tomcat.Jetty等)时,将Servlet,Filter,Listener  注册到Servlet容器的方法: 1.1.1.直接注册Bean ...

  4. servlet filter listener interceptor 知识点

    这篇文章主要介绍 servlet filter listener interceptor 之 知识点.博文主要从 概念,生命周期,使命介绍其区别.详情如下:   概念 生命周期 使命 servlet ...

  5. servlet/filter/listener/interceptor区别与联系

    转自:http://www.cnblogs.com/doit8791/p/4209442.html servlet.filter.listener是配置到web.xml中(web.xml 的加载顺序是 ...

  6. 【转】servlet/filter/listener/interceptor区别与联系

    原文:https://www.cnblogs.com/doit8791/p/4209442.html 一.概念: 1.servlet:servlet是一种运行服务器端的java应用程序,具有独立于平台 ...

  7. [转]web.xml中servlet ,filter ,listener ,interceptor的作用与区别

    原文链接:https://blog.csdn.net/netdevgirl/article/details/51483273 一.概念: 1.servlet:servlet是一种运行服务器端的java ...

  8. SpringBoot整合WEB开发--(九)整合Servlet,Filter,Listener

    简介: 如果需要整合第三方框架时,可能还是不得不使用Servlet,Filter,Listener,Springboot中也有提供支持. @WebServlet("/my") pu ...

  9. Spring Boot整合Servlet,Filter,Listener,访问静态资源

    目录 Spring Boot整合Servlet(两种方式) 第一种方式(通过注解扫描方式完成Servlet组件的注册): 第二种方式(通过方法完成Servlet组件的注册) Springboot整合F ...

随机推荐

  1. Linux expect详解

    随处可见的expect第一次见expect这个命令还是我第一次参加全量上线的时候,那是公司的一个牛人用Shell脚本写的一套自动部署.MD5 比对.发布的全量上线工具,没事的时候,看了下其中的几个脚本 ...

  2. E4A碰到打开自动闪退又自动打开又闪退一直循环的问题

    E4A碰到打开自动闪退又自动打开又闪退一直循环的问题 这几天写了一个脚本,自己手机上,模拟器上,均测试没有问题,可以正常操作 发给另一个人,他那边居然没有一个设备能运行成功! 而且一直闪退,闪退后又打 ...

  3. unity EditorGUILayer绘制报错

    最近在开发一个可视化工具的时候,遇到了一个代码错误,小小的记录一下 具体的报错信息:ArgumentException: Getting control 0's position in a group ...

  4. 【转】干货篇:手机绕过BL锁9008模式强刷

    <ignore_js_op> 高通QPST线刷其实就是利用高通芯片自带的9008端口,将手机系统内的所有分区的镜像文件,直接刷写手机.这个刷机方式比REC卡刷和fastboot线刷,更底层 ...

  5. css3中的盒子模型

    1.示例一 实现左右布局,左侧宽度200px,右侧自适配 代码如下: <!DOCTYPE html> <html lang="en"> <head&g ...

  6. ipa重签名最直接的教程

    ipa 包重签名最新最简单教程 重签名的意义:ipa 重签名最大的用处是,不必重新打包,和配置其它第三方获取 appkey 等操作,直接重签名之后依然可以拥有这些功能,更快的发布测试或者灰度版本. 本 ...

  7. git冲突处理-Please move or remove them before you can merge

    参考:https://www.cnblogs.com/wenlj/p/5866356.html https://my.oschina.net/lixiaoyan/blog/1821947 #### 将 ...

  8. python开发笔记-str转字典

    后台接收到post请求数据格式为json格式的字符串,不能直接用字典的get方法 909090909090909090909090909090909 Internal Server Error: /g ...

  9. scrapy爬虫案例:用MongoDB保存数据

    用Pymongo保存数据 爬取豆瓣电影top250movie.douban.com/top250的电影数据,并保存在MongoDB中. items.py class DoubanspiderItem( ...

  10. Spark连续特征转化成离散特征

    当数据量很大的时候,分类任务通常使用[离散特征+LR]集成[连续特征+xgboost],如果把连续特征加入到LR.决策树中,容易造成overfit. 如果想用上连续型特征,使用集成学习集成多种算法是一 ...