Tomcat

StandardContext初始化过程

//org.apache.catalina.core.StandardContext#startInternal

  // 子容器启动
for (Container child : findChildren()) {
if (!child.getState().isAvailable()) {
child.start();
}
} //初始化WebappLoader
if (getLoader() == null) {
WebappLoader webappLoader = new WebappLoader(getParentClassLoader());
webappLoader.setDelegate(getDelegate());
setLoader(webappLoader);
} //实例化contextManager ,用于管理session
Manager contextManager = null;
try {
contextManager = getCluster().createManager(getName());
} catch (Exception ex) {
log.error("standardContext.clusterFail", ex);
ok = false;
}
setManager(contextManager); //1.
//初始化所有Listener实例,
if (ok) {
if (!listenerStart()) {
log.error( "Error listenerStart");
}
}
//2.
try {
// 启动StandardManager,该类管理Session信息
if ((manager != null) && (manager instanceof Lifecycle)) {
((Lifecycle) getManager()).start();
} //启动后台线程, 检查seesion超时
super.threadStart();
} //3. 初始化 application filters
if (ok) {
if (!filterStart()) {
log.error("Error filterStart");
ok = false;
}
} //4.
//加载和初始化标记"load on startup"大于1的Servelet
if (ok) {
loadOnStartup(findChildren());
}

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



事件监听

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

@SpringBootApplication
@EnableConfigServer
@EnableDiscoveryClient
public class ConfigServer {
public static void main(String[] args) {
SpringApplication springApplication = new SpringApplication(ConfigServer.class); // 方法一:添加自定义的 ApplicationContextInitializer 实现类的实例(注册ApplicationContextInitializer)
springApplication.addInitializers(new ApplicationContextInitializer1()); ConfigurableApplicationContext context = springApplication.run(args); context.close();
}
}

2.application.properties添加配置方式

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

3. 使用spring.factories方式

1. 先定义先定义ApplicationContextInitializer

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

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包

自动填充属性
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. 求X值问题

    这,其实是一道数学题,难就难在要把数学模型用编程语言实现,其中的规律如果看不出来就比较鸡肋,这类题可以算是智商题,做这类题千万不能紧张,血的教训. 题目描述 已知有整数x,x + 100为一个平方数. ...

  2. java23种设计模式——七、桥接模式

    原文地址:https://www.cnblogs.com/chenssy/p/3317866.html 源码在我的github和gitee中获取 目录 java23种设计模式-- 一.设计模式介绍 j ...

  3. 记录laravelchina中的微信小程序教程的第四节的安装easy WeChat扩展的报错

    composer require "overtrue/laravel-wechat:~5.0 PHP Fatal error: Allowed memory size of 16106127 ...

  4. C# Chart各个属性详细解析、应用

    Chart笔记 前台页面代码: <form id="form1" runat="server"> <div> <asp:Chart ...

  5. Go测试开发(一) 怎么写Go代码

    安装过程略过,网上搜一大把. 介绍 本文会在一个module中开发一个简单的Go package. 同时介绍go tool(也就是go命令行). 以及如何fetch,build和install Go的 ...

  6. Myabtis动态SQL,你真的会了吗?

    目录 前言 什么是动态SQL? 常用的标签 if choose.when.otherwise where foreach set sql include 总结 拓展一下 Mybatis中如何避免魔数? ...

  7. 状压dp:luogu P2704 [NOI2001]炮兵阵地

    https://www.luogu.org/problemnew/show/P2704 知识点:1.滚动数组:取模实现 2.位运算优先级最低 顾是if(!(a&b))而不是if(!a& ...

  8. .NET实现可交互的WINDOWS服务(转载自CSDN"烈火蜓蜻")

    Windows 服务应用程序在不同于登录用户的交互区域的窗口区域中运行.窗口区域是包含剪贴板.一组全局原子和一组桌面对象的安全对象.由于 Windows 服务的区域不是交互区域,因此 Windows ...

  9. Java获取Linux上指定文件夹下所有第一级子文件夹

    说明:需要只获得第一级文件夹目录 package com.sunsheen.jfids.studio.monitor.utils; import java.io.BufferedReader; imp ...

  10. ui自动化---CssSelector

    xpath切换到css