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. CentOS7(Linux)源码安装Redis

    介绍 项目中经常需要用到Redis做缓存数据库,可是还有小伙伴不会在Linux上安装Redis,毕竟我们开发的项目都是要在服务器上运行的,今天就来讲讲如何在CentOS7环境使用源码进行安装Redis ...

  2. 程序员必知必会Git的小知识

    单人开发 1.初始化一个仓库 git init //cd到你工作的文件夹,初始化git仓库,默认会生成.git隐藏目录 2.配置自己的信息(Git 不喜欢不愿透漏姓名的人) git config -- ...

  3. 高可用集群corosync+pacemaker之crmsh使用(一)

    上一篇博客我们聊了下高可用集群corosync+pacemaker的相关概念以及corosync的配置,回顾请参考https://www.cnblogs.com/qiuhom-1874/p/13585 ...

  4. APM姿态控制流程

    对初学者了解控制流程有一定帮助 在主循环执行过程中(比如Pixhawk的任务调度周期2.5ms,400Hz:APM2.x为10ms,100Hz),每一个周期,程序会按下述步骤执行:• 首先,高层次文件 ...

  5. 【JAVA】给大家推荐一道有意思的java测试题。你知道答案吗?

    作者:程序员小冰,CSDN博客:http://blog.csdn.net/qq_21376985, QQ986945193 公众号:程序员小冰 public class Test { /** * * ...

  6. Web测试经典bug、安全性测试

    典型BUG 表格的排序.翻页.添加.删除的联合测试 输入框的长度检查 数据库表中如果指定utf8长度为150,则可以输入150个中文或英文字母等 (有时候界面判断失误,却只能输入50个汉字) 数据添加 ...

  7. 2020重新出发,NOSQL,redis高并发系统的分析和设计

    高并发系统的分析和设计 任何系统都不是独立于业务进行开发的,真正的系统是为了实现业务而开发的,所以开发高并发网站抢购时,都应该先分析业务需求和实际的场景,在完善这些需求之后才能进入系统开发阶段. 没有 ...

  8. 在logback的fileNamePattern配置%i 带来的异常

    我在logback的配置文件中企图这样配置: <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPol ...

  9. AI研讨会直播:《人工智能开发前沿》实战系列公开课第1期

    报名链接:https://www.slidestalk.com/m/276 活动背景 业务需求.数据.算法.算力等因素,决定人工智能技术走向产业落地面临各种挑战.博客园联合示说网以及产业内人工智能技术 ...

  10. CentOS如何设置IP连接网络

    1.登录系统,进入:cd /etc/sysconfig/network-scripts 目录下,如下图: 找到 ifcfg-ens33(文件) 第二步:使用vi编辑器打开ifcfg-ens33文件,使 ...