Tomcat

StandardContext初始化过程

  1. //org.apache.catalina.core.StandardContext#startInternal
  2.  
  3. // 子容器启动
  4. for (Container child : findChildren()) {
  5. if (!child.getState().isAvailable()) {
  6. child.start();
  7. }
  8. }
  9.  
  10. //初始化WebappLoader
  11. if (getLoader() == null) {
  12. WebappLoader webappLoader = new WebappLoader(getParentClassLoader());
  13. webappLoader.setDelegate(getDelegate());
  14. setLoader(webappLoader);
  15. }
  16.  
  17. //实例化contextManager ,用于管理session
  18. Manager contextManager = null;
  19. try {
  20. contextManager = getCluster().createManager(getName());
  21. } catch (Exception ex) {
  22. log.error("standardContext.clusterFail", ex);
  23. ok = false;
  24. }
  25. setManager(contextManager);
  26.  
  27. //1.
  28. //初始化所有Listener实例,
  29. if (ok) {
  30. if (!listenerStart()) {
  31. log.error( "Error listenerStart");
  32. }
  33. }
  34. //2.
  35. try {
  36. // 启动StandardManager,该类管理Session信息
  37. if ((manager != null) && (manager instanceof Lifecycle)) {
  38. ((Lifecycle) getManager()).start();
  39. }
  40.  
  41. //启动后台线程, 检查seesion超时
  42. super.threadStart();
  43. }
  44.  
  45. //3. 初始化 application filters
  46. if (ok) {
  47. if (!filterStart()) {
  48. log.error("Error filterStart");
  49. ok = false;
  50. }
  51. }
  52.  
  53. //4.
  54. //加载和初始化标记"load on startup"大于1的Servelet
  55. if (ok) {
  56. loadOnStartup(findChildren());
  57. }

Tomcat初始化监听对象:

监听器分两种LifeCycleListener, EventListener ,如图所示,

参考资料:

https://blog.csdn.net/yangsnow_rain_wind/article/details/80118321


serveltContext

serveltContext标示Tomcat存储当前Web程序的上下文信息,

  1. 每个Engine有多个war包, 每个war包就是一个web应用程序, 每个web应用程序只有一个Context上下文,这就是servletContext.
  2. 每个servletcontext下可以有多个servlet, 每个servlet需要有配置url映射. 每个servlet需要被包装为StandardWrapper类, 存储到servletcontext容器中.
  3. ServletContext 对象是一个为整个 web 应用提供共享的内存,多个servlet实例见可以通过context进行通信.
  4. ServletContext 在tomcat中对应的类是ApplicationContext

参照笔记: https://blog.csdn.net/yangsnow_rain_wind/article/details/80118321


1、spi简单说明
spi,即service privider interface,是jdk为厂商和插件提供的一种解耦机制。
spi的具体规范为:当服务的提供者,提供了服务接口的一种实现之后,在jar包的META-INF/services/目录里同时创建一个以服务接口命名的文件。该文件里就是实现该服务接口的具体实现类。而当外部程序装配这个模块的时候,就能通过该jar包META-INF/services/里的配置文件找到具体的实现类名,并通过反射机制实例化,完成模块的注入。 基于这样一个约定就能很好的找到服务接口的实现类,而不需要再代码里制定。jdk提供服务实现查找的一个工具类:java.util.ServiceLoader

2、spring-web中的具体应用
从servlet3.0开始,web容器启动时为提供给第三方组件机会做一些初始化的工作,例如注册servlet或者filtes等,servlet规范中通过ServletContainerInitializer.onStartup实现此功能。

每个框架要使用ServletContainerInitializer就必须在对应的jar包的META-INF/services 目录创建一个名为javax.servlet.ServletContainerInitializer的文件,文件内容指定具体的ServletContainerInitializer实现类,那么,当web容器启动时就会运行这个初始化器做一些组件内的初始化工作。

一般伴随着ServletContainerInitializer一起使用的还有HandlesTypes注解,通过HandlesTypes可以将感兴趣的一些类注入到ServletContainerInitializerde的onStartup方法作为参数传入。

spring-web的jar定义了一个具体的实现类,SpringServletContainerInitializer,并且在META-INF/services/目录下定义了如下文件org.springframework.web.SpringServletContainerInitializer。

3、SpringServletContainerInitializer

SpringServletContainerInitializer是接口ServletContainerInitializer的实现类,tomcat启动时调用processServletContainerInitializers,通过SPI机制,找到classpath下所有实现ServletContainerInitializers接口的类,然后初始化这个类,并调用此类的接口onStartup.

SpringServletContainerInitializer类上注解为@HandlesTypes(WebApplicationInitializer.class)~,它的作用是将感兴趣的一些类注入到ServletContainerInitializer,并作为参数传给onStartup方法,并后续完成类初始化。

源码如下:

最终ServletContainerInitializers.onStartup方法变成了实现WebApplicationInitializer.onStartup(ServletContext)

4. WebApplicationInitializer

通过实现接口WebApplicationInitializer,在其中可以添加servlet,listener等,在加载Web项目的时候会加载这个接口实现类,从而起到web.xml相同的作用。

其重要的一个实现类是SpringBootServletInitializer

5. SpringBootServletInitializer

  1.  

事件监听

ServletContextListener:在servlet启动时,获得监听(contextInitialized,contextDestroyed)

ContextLoaderListener: 用来在部署相关Web应用时初始化其上下文环境(initWebApplicationContext, 并放置在servletContext.attr(".root")属性中),在停止退出Web应用时清理其资源

ServletContextListener:

包括两个接口方法:contextInitialized,contextDestroyed,在Web 应用的生命周期中,ServletContext 对象最早被创建,最晚被销毁,常被用于在web容器启动war之前对servlet进行提前配置,

如设置attribute参数到servletContext中。SpringMVC框架中被用来初始化IOC容器等,(ContextLoaderListener类中在contextInitialized方法中初始化initWebApplicationContext(被放在servletContext.attr(".root")属性中))

Filter

Filter(过滤器)可以改变HTTP请求的内容、响应、及header信息,过滤器通常不产生响应或像 servlet 那样对请求作出响应,而是修改或调整到资源的请求,修改或调整来自资源的响应。

当容器接收到传入的请求时,它将获取列表中所有符合该请求的过虑器组成过虑器链(FilterChain),然后通过FilterChain嵌套调用各过虑器的Filter.doFilter()方法(一个过滤器可以使得滤器链调用下一个过滤器),传入ServletRequest 和ServletResponse进行处理。

当滤器链调用完各Filter.doFilter()方法后,会调用相关Servlet.service()方法,从而进行Servlet的处理。注意,Filter.doFilter()可以阻止过滤器链接下来的调用,返回时过滤器负责填充Reponse对象。

过滤器实例移除之前,容器必须先调用过滤器的Filter.destroy()方法。

web.xml中组件加载顺序为:

context-param -> listener -> filter -> servlet(同类则按编写顺序执行)


ApplicationContextInitializer:

ApplicationContextInitializer是Spring框架原有的东西,这个类的主要作用就是在ConfigurableApplicationContext类型(或者子类型)的ApplicationContext做refresh之前,允许我们对ConfiurableApplicationContext的实例做进一步的设置和处理。

ApplicationContextInitializer接口是在spring容器刷新Refresh之前执行的一个回调函数

实际应用:

在一个Springboot应用中,classpath上会包含很多jar包,有些jar包需要在ConfigurableApplicationContext#refresh()调用之前对应用上下文做一些初始化动作,因此它们会提供自己的ApplicationContextInitializer实现类,然后放在自己的META-INF/spring.factories属性文件中,这样相应的ApplicationContextInitializer实现类就会被SpringApplication#initialize发现。

添加方法有三种

1. 启动类里手动增加initializer

  1. @SpringBootApplication
  2. @EnableConfigServer
  3. @EnableDiscoveryClient
  4. public class ConfigServer {
  5. public static void main(String[] args) {
  6. SpringApplication springApplication = new SpringApplication(ConfigServer.class);
  7.  
  8. // 方法一:添加自定义的 ApplicationContextInitializer 实现类的实例(注册ApplicationContextInitializer)
  9. springApplication.addInitializers(new ApplicationContextInitializer1());
  10.  
  11. ConfigurableApplicationContext context = springApplication.run(args);
  12.  
  13. context.close();
  14. }
  15. }

2.application.properties添加配置方式

context.initializer.classes = com.springboot.xx.xx.ApplicationPropertiesApplicationContextInitializer

3. 使用spring.factories方式

1. 先定义先定义ApplicationContextInitializer

2、然后在项目下的resources下新建META-INF文件夹,文件夹下新建spring.factories文件

  1. org.springframework.context.ApplicationContextInitializer=com.x.ApplicationContextInitializer1

总结:

ApplicationContextInitializer是Spring留出来允许我们在上下文刷新之前做自定义操作的钩子,若我们有需求想要深度整合Spring上下文,借助它不乏是一个非常好的实现。


网关作用:

在微服务实施之后,各个服务的拆分粒度很小,对于客户端来说,做一个操作可能会涉及到 后端的多个服务组件的调用,那意味着它需要频繁的发起多次访问才能进行数据聚合实现用 户的功能。 如果我们在所有的微服务之前增加一个网关,对于客户端来说它需要做什么功能操作直接调 用网关并且告诉网关所要做的事情即可,网关根据请求的功能对后端的多个服务的数据进行 聚合聚合哦从而减少客户端的调用频次。 并且,由于有了网关的聚合,我们还可以在网关层对请求进行统一鉴权和认证; 包括还可 以实现限流、请求日志统一记录、 灰度发布等等。

Enable 注解不仅仅可以像前面演示的案例一样很简单的实 现多个 Configuration 的整合,还可以实现一些复杂的场 景,比如可以根据上下文来激活不同类型的 bean, @Import 注解可以配置三种不同的 class

1. 第一种就是前面演示过的,基于普通 bean 或者带有 @Configuration 的 bean 进行诸如

2. 实现 ImportSelector 接口进行动态注入
3. 实现 ImportBeanDefinitionRegistrar 接口进行动态注入

@EnableAutoConfiguration 注解的实现原理

在@EnableAutoConfiguration注解内使用到了@import注解来完成导入配置的功能,而EnableAutoConfigurationImportSelector内部则是使用了SpringFactoriesLoader.loadFactoryNames方法进行扫描具有META-INF/spring.factories文件的jar包

自动填充属性
  1. EnableConfigurationProperties
 
 

Spring及tomcat初始化日志的更多相关文章

  1. spring boot Tomcat访问日志

    1.Tomcat设置访问日志 <Host name="localhost" appBase="webapps" unpackWARs="true ...

  2. 从启动日志看Spring IOC的初始化和Bean生命周期

    一.Tomcat中启动IoC容器的日志 启动Tomcat等容器时,控制台每次都打印出一些日志. 最近刚好在研究Spring源码,所以换个角度,从启动日志来简单的看看Spring的初始化过程! 以下是T ...

  3. Spring初始化日志

    Spring启动时的日志: 2013-11-22 14:55:59:319[INFO]: FrameworkServlet 'spring3': initialization completed in ...

  4. Spring Boot 项目初始化

    Spring Boot 项目创建 File->New->New Project->Spring Initializr 勾选 Web Spring Boot 版本选择稳定版,本文选择 ...

  5. Spring Boot 系列:日志动态配置详解

    世界上最快的捷径,就是脚踏实地,本文已收录架构技术专栏关注这个喜欢分享的地方. 开源项目: 分布式监控(Gitee GVP最有价值开源项目 ):https://gitee.com/sanjianket ...

  6. spring + spring mvc + tomcat 面试题(史上最全)

    文章很长,而且持续更新,建议收藏起来,慢慢读! 高并发 发烧友社群:疯狂创客圈(总入口) 奉上以下珍贵的学习资源: 疯狂创客圈 经典图书 : 极致经典 + 社群大片好评 < Java 高并发 三 ...

  7. 配置Tomcat的日志系统

    成功配置tomcat的log4j日志系统,格式:HTML+每天以yyyy-mm-dd.log命名的日志文件 一.引言: 实习单位让用log4j配置webapp的日志系统,要求产生的日志文件是html格 ...

  8. Spring 中配置log4j日志功能

    一,添加log4j依赖包 可从官网上下载该依赖包log4j-x.x.xx.jar,下载后 build path,添加依赖包 二,创建 log4j.properties 配置文件 log4j.prope ...

  9. 如何配置Spring Boot Tomcat

    1.概述 Spring Boot Web应用程序默认包含预配置的嵌入式Web服务器.但在某些情况下,我们要修改默认配置以满足自定义要求. 在本教程中,我们将介绍通过application.proper ...

随机推荐

  1. Java算法——回溯法

    回溯法一种选优搜索法,又称试探法.利用试探性的方法,在包含问题所有解的解空间树中,将可能的结果搜索一遍,从而获得满足条件的解.搜索过程采用深度遍历策略,并随时判定结点是否满足条件要求,满足要求就继续向 ...

  2. 使用tess4j完成身份证和营业执照图片的文字识别

    这两天研究了一下关于OCR图文解析的技术.当然市场上已经有开源服务,比如百度的AI开放平台,就有OCR相关的API接口.我这里选用的是Tesseract开源框架,java封装版本是tess4j.结合网 ...

  3. IntelliJ IDEA 2019 的安装与破解

    IDEA 全称 IntelliJ IDEA,是java编程语言开发的集成环境.IntelliJ在业界被公认为最好的java开发工具,尤其在智能代码助手.代码自动提示.重构.J2EE支持.各类版本工具( ...

  4. Spine学习七 - spine动画资源+ Unity Mecanim动画系统

    前面已经讲过 Spine自己动画状态机的动画融合,但是万一有哥们就是想要使用Unity的动画系统,那有没有办法呢?答案是肯定的,接下来,就说说如何实现: 1. 在project面板找打你导入的Spin ...

  5. vue 页面首次加载缓慢原因及解决方案

    第一次打包vue的项目部署到服务器,发现首次加载特别的缓慢要几十秒才加载出来,完全没有在本地开发环境上那么流畅. 主要原因是页面在打包后没有进行相关的配置导致资源文件特别大,一次想要全部加载完成回特别 ...

  6. HashMap源码解析、jdk7和8之后的区别、相关问题分析(多线程扩容带来的死循环)

    一.概览 HashMap<String, Integer> map = new HashMap<>(); 这个语句执行起来,在 jdk1.8 之前,会创建一个长度是 16 的 ...

  7. 小程序开发-使用Loading和Toast提示框

    小程序提示框 Loading提示框使用方式 1. 在wxml中作为组件使用 <loading hidden="{{hidden}}"> 加载中... </load ...

  8. C#编辑GridView的Thead

    背景 有这样一个需求,需要更改GridView的Thead,即表头.不只是多行表头,而是任意的内容,可能是一段文字,也可能是一个图片,综合网上的一些资料,大致整理出一些做法. 内容 大致有两种方法 第 ...

  9. 单应用模式 - Layuiadmin单页版放入TP6.0的部署方案

    thinkphp6.0.3单应用模式.layuiadmin1.4.0单页版,不需要tp的视图驱动 1. 复制 src.start 两个文件夹 2. 粘贴到 thinkphp 的 public 目录下 ...

  10. CSS的坑

    如何触发 bfc 规则 浮动元素:float 除 none 以外的值 绝对定位元素:position (absolute.fixed) display 为 inline-block.table-cel ...