1. tomcat入门

入门模块仅做学习大纲梳理,忽略了具体操作指引。

Tomcat的三种部署模式:

简单架构模型

连接器的非阻塞模式(NIO)

通道(Channel)、缓冲区(Buffer)、选择器(Selector)

容器container的责任链模式:

1.请求被Connector组件接收,创建Request和Response对象。

2.Connector将Request和Response交给Container,先通过Engine的pipeline组件流经内部的每个Valve。

3.请求流转到Host的pipeline组件中,并且经过内部Valve的过。

4.请求流转到Context的pipeline组件中,并且经过内部的Valve的过滤。

5.请求流转到Wrapper的pipeline组件中,并且经过内部的Valve的过滤。

6.Wrapper内部的WrapperValve创建FilterChain实例,调用指定的Servlet实例处理请求。

7.返回。

2.tomcat架构进阶

tomcat顶层结构

Server:服务器的意思,代表整个tomcat服务器,一个tomcat只有一个Server;

Service:Server中的一个逻辑功能层, 一个Server可以包含多个Service;

Connector:称作连接器,是Service的核心组件之一,一个Service可以有多个Connector,主要是连接客户端请求;

Container:Service的另一个核心组件,按照层级有Engine,Host,Context,Wrapper四种,一个Service只有一个Engine,其主要作用是执

行业务逻辑;
Jasper:JSP引擎;
Session:会话管理;

Connector解析

Connector使用ProtocolHandler来处理请求的Endpoint用来处理底层Socket的网络连接。

Processor用于将Endpoint接收到的Socket封装成Request。

Adapter充当适配器,用于将Request转换为ServletRequest交给Container进行具体的处理。

ProtocolHandler由包含了三个部件:Endpoint、Processor,Adapter

Container解析

service中的name是catalina,engine中的name也是catalina,这个就证明一个service就只有一个engine, 一个engine可以有多个host主机

host,站点,虚拟主机。

Engine:引擎、只有一个定义了一个名为Catalina的Engine

Host:站点、虚拟主机一个Engine包含多个Host的设计,使得一个服务器实例可以承担多个域名的服务,是很灵活的设计

Context:一个应用默认配置下webapps下的每个目录都是一个应用

Wrapper:一个Servlet

结合tomcat目录结构理解上面的4个容器之间的关系

3.tomcat类加载机制

引用自:https://www.cnblogs.com/ghoster/p/7602158.html

1.主流的Java Web服务器,如Tomcat、Jetty、WebLogic、WebSphere等都实现了自己定义的类加载器(一般都不止一个)。因为一个功能健全的web服务器要解决一下几个问题:

    1)部署在一个服务器上的两个web应用程序所使用的Java类库可以实现互相隔离。这是最基本的需求,两个不同的应用程序可能会依赖同一个第三方类库的不同版本,不能要求一个类库在一个服务器中只有一份,服务器应当保证两个应用程序的类库可以互相独立使用

    2)部署在同一个服务器上的两个Web应用程序所使用的Java类库可以互相共享。这个需求也非常很常见,如,用户可能有10各使用Spring组织的应用程序部署在同一台服务器上,如果把10份Spring分别存放在各个应用程序的隔离目录中,将会是很大的资源浪费-这主要不是浪费磁盘空间的问题,而是指类库在使用时都要被加载到服务器内存,如果类库不能共享,虚拟机的方法区就会很容易出现过度膨胀的风险

    3)服务器需要尽可能地保证自身的安全不受部署的Web应用程序影响。目前,有许多主流的Java Web服务器自身也是使用Java语言来实现的。因此,服务器本身也有类库依赖的问题,一般来说,基于安全考虑,服务器所使用的类库应该与应用程序的类库相互独立

    4)支持jsp应用的Web服务器,大多数都需要支持HotSwap功能。我们知道,jsp文件最终要编译成Java Class才能由虚拟机执行,但jsp文件由于其纯文本存储的特性,运行时修改的概率远远大于第三方类库或程序自身的Class文件。而且ASP、PHP和JSP这些网页应用也把修改后无需重启作为一个很大的“优势”来看待,因此,“主流”的Web服务器都会支持JSP的热替换,当然也有“非主流”的,如运行在生产模式下的WebLogic服务器默认就不会处理JSP文件的变化

  由于存在上述问题,在部署Web应用时,单独的一个ClassPath就无法满足需求了,所以各种Web服务器都“不约而同”地提供了好几个ClassPath路径供用户存放第三方类库,这些路径一般都以lib或classes命名,被放置到不同路径中的类库,具备不同的访问范围和服务对象,通常,每一个目录都会有一个相应的自定义类加载器去加载放置在里面的Java类库。

  2.Tomcat对用户类库与类加载器的规划

    在其目录结构下有三组目录(“/common/*”、“/server/*”、“/shared/*”)可以存放Java类库,另外还可以加上Web应用程序本身的目录“/WEB-INF/*”,一共4组,把Java类库放置在这些目录中的含义分别如下:

    1)放置在/commom目录中:类库可被Tomcat和所有的Web应用程序共同使用

    2)放置在/server目录中:类库可被Tomcat使用,对所有的Web应用程序都不可见

    3)放置在/shared目录中:类库可被所有的Web应用程序所共同使用,但对Tomcat自己不可见

    4)放置在/WebApp/WEB-INF目录中:类库仅仅可以被此Web应用程序使用,对Tomcat和其他Web应用程序都不可见

    为了支持这套目录结构,并对目录里面的类库进行加载和隔离,Tomcat自定义了多个类加载器,这些类加载器按照经典的双亲委派模型来实现,所下图:

    

    最上面的三个类加载器是JDK默认提供的类加载器,这三个加载器的的作用之前也说过,这里不再赘述了,可以在http://www.cnblogs.com/ghoster/p/7594224.html简单了解。而CommonClassLoader、CatalinaClassLoader、SharedClassLoader和WebAppClassLoader则是Tomcat自己定义的类加载器,他们分别加载/common/*、/server/*、/shared/*和/WebApp/WEB-INF/*中的Java类库。其中WebApp类加载器和jsp类加载器通常会存在多个实例,每一个Web应用程序对应一个WebApp类加载器,每一个jsp文件对应一个Jsp类加载器

    从上图的委派关系可以看出,CommonClassLoader能加载的类都可以被CatalinaClassLoader和SharedClassLoader使用,而CatalinaClassLoader和SharedClassLoader自己能加载的类则与对方相互隔离。WebAppClassLoader可以使用SharedClassLoader加载到的类,但各个WebAppClassLoader实例之间相互隔离。而JasperLoader的加载范围仅仅是这个JSP文件所编译出来的哪一个Class,它出现的目的就是为了被丢弃:当服务器检测到JSP文件被修改时,会替换掉目前的JasperLoader的实例,并通过在建立一个新的Jsp类加载器来实现JSP文件的HotSwap功能

4.打破双亲委派模型企业级应用实战

需求背景:在使用多数据源的情况下,同时连接某大厂魔改的数据库mppdb和pgsql数据库的时候。出现了无法同时加载mppdb和pgsql的驱动的问题。

原因分析:spring在启动时会调用应用类加载器加载org目录下的.class文件,同时spring自定义类加载器分别加载BOOT-INF,META-INF 目录下的文件,mppdb 与pgsql驱动的本质都是.jar文件,所以会放在META-INF目录下的lib目录下。

又因为mppdb是某国内大厂以pgsql为蓝本魔改的,遗留下一个问题,mppdb与mysql驱动的类名是完全一致的。而两驱动都放在lib目录下,由同一个类加载器来加载,就会出现以下情况:当第一个驱动pgsql加载时,使用双亲机制正常加载,

当第二个驱动mppdb再次加载时,会判断该类是否加载过,此时,由于类加载器一致,类名一致,类加载器会误认为mppdb驱动已经加载过了,实际是之前加载的pgsql驱动,所以spring不会再去加载mppdb,而是从缓冲中把pgsql的驱动抛出,

从而导致了,spring在启动时无法同时加载mppdn驱动和pgsql驱动。

解决方案:

方案一:遵循双亲委派模型

在spring容器启动后(此时spring已经加载到其中一个驱动,假设是pgsql驱动),新开一个jvm进程,在该进程中使用扩展类加载器加载mppdb驱动,根据双亲委派模型,扩展类加载器是应用类加载器的父类,当需要加载驱动时会优先委派父类加载,

所以同一个类在父类加载器和子类加载器都能加载的情况下,父类加载器总能优先加载的。这样就保证了,新起的进程总是能加载到扩展类加载器加载的mppdb驱动。

方案二:打破双亲委派模型

在spring容器启动后(此时spring已经加载到其中一个驱动,假设是pgsql驱动),不必新开进程,还是在该spring的进程内,使用应用类加载器XMLClassLoader去加载mppdb驱动,如果此时使用双亲委派模型,会加载到spring初始化时加载到的驱动,即pgsql驱动,

故而 需要将XMLClassLoader 的父加载器设置为null,禁止其父加载器加载,而由其自己加载,即可以成功加载mppdb驱动,具体实现涉及公司信息安全,在此仅提供问题解决思路。

tomcat学习步骤,附带打破双亲委派模型企业应用实战的更多相关文章

  1. Tomcat 类加载器打破双亲委派模型

    我们分为4个部分来探讨: 1. 什么是类加载机制? 2. 什么是双亲委任模型? 3. 如何破坏双亲委任模型? 4. Tomcat 的类加载器是怎么设计的? 我想,在研究tomcat 类加载之前,我们复 ...

  2. 【JVM第二篇--类加载机制】类加载器与双亲委派模型

    写在前面的话:本文是在观看尚硅谷JVM教程后,整理的学习笔记.其观看地址如下:尚硅谷2020最新版宋红康JVM教程 一.什么是类加载器 在类加载过程中,加载阶段有一个动作是"通过一个类的全限 ...

  3. java虚拟机(二)--类加载机制和双亲委派模型

    一.类的生命周期 加载(Loading).验证(Verification).准备(Preparation).解析(Resolution).初始化(Initialization).使用(Using).卸 ...

  4. JDBC、Tomcat为什么要破坏双亲委派模型?

    问题一:双亲委派模型是什么 如果一个类加载器收到了加载某个类的请求,则该类加载器并不会去加载该类,而是把这个请求委派给父类加载器,每一个层次的类加载器都是如此,因此所有的类加载请求最终都会传送到顶端的 ...

  5. JVM总括四-类加载过程、双亲委派模型、对象实例化过程

    JVM总括四-类加载过程.双亲委派模型.对象实例化过程 目录:JVM总括:目录 一. 类加载过程 类加载过程就是将.class文件转化为Class对象,类实例化的过程,(User user = new ...

  6. java类加载器和双亲委派模型

    一. 类加载器 ClassLoader即常说的类加载器,其功能是用于从Class文件加载所需的类,主要场景用于热部署.代码热替换等场景. 系统提供3种的类加载器:Bootstrap ClassLoad ...

  7. Java类加载机制以及双亲委派模型

    一.Java类加载机制 1.概述 Class文件由类装载器装载后,在JVM中将形成一份描述Class结构的元信息对象,通过该元信息对象可以获知Class的结构信息:如构造函数,属性和方法等,Java允 ...

  8. Java虚拟机详解(十一)------双亲委派模型

    在上一篇博客,我们介绍了类加载过程,包括5个阶段,分别是“加载”,“验证”,“准备”,“解析”,“初始化”,如下图所示: 本篇博客,我们来介绍Java虚拟机的双亲委派模型,在介绍之前,我先抛出一个问题 ...

  9. 图解JVM类加载机制和双亲委派模型

    我们都知道以 .java 结尾的 Java 源文件,经过编译之后会变成 .class 结尾的字节码文件.JVM 通过类加载器来加载字节码文件,然后再执行程序. 什么时候加载一个类 那么,什么时候类加载 ...

随机推荐

  1. Spring AOP 源码分析系列文章导读

    1. 简介 前一段时间,我学习了 Spring IOC 容器方面的源码,并写了数篇文章对此进行讲解.在写完 Spring IOC 容器源码分析系列文章中的最后一篇后,没敢懈怠,趁热打铁,花了3天时间阅 ...

  2. Python3.5学习十八 Python之Web框架 Django

    Python之Web框架: 本质:Socket 引用wsgiref创建web框架 根据web框架创建过程优化所得: 分目录管理 模板单独目录 执行不同函数单独存入一个方法py文件 Web框架的两种形式 ...

  3. [学习笔记]普通平衡树Splay

    哈哈哈哈哈哈哈终于会打\(splay\)啦 现在我来发一下\(splay\)的讲解吧 小蒟蒻由于码风与他人不同,所以自己找了上百篇码风诡异的\(splay\)合成的,感谢\(zcysky\)的代码与我 ...

  4. 27_网络编程-初识socket

    一.C/S B/S 架构         1.定义             (1)C/S结构,即Client/Server(客户机/服务器)结构,是大家熟知的软件系统体系结构,通过将任务合理分配到Cl ...

  5. diamond的设计思路

    diamond主要包含四个包:diamond-client.diamond-sdk.diamond-server和diamond-util client就非常简单的进行http的调用server拿数据 ...

  6. Swift 里字符串(十一)OC 字符串和 Swift 字符串的转换

     to OC func _bridgeToObjectiveCImpl() -> AnyObject { if _guts.isSmall { return _guts.asSmall.wit ...

  7. Hbuilder用ajax连接阿里服务器上的servlet以及注意事项

    Hbuiler连接服务器上的servlet的步骤与连接本地项目中的servlet基本一致,详细内容参考上一片博客:https://www.cnblogs.com/ljysy/p/10294640.ht ...

  8. 解决chkconfig设置开机启动时出现missing LSB的错误

    0x00 主要原因是脚本不符合LSB tags规范,在#!/bin/bash下面添加如下代码即可 以tomcat为例 ### BEGIN INIT INFO # Provides: bbzhh.com ...

  9. 理解 async/await 的执行

    这是一篇简单的短文章,方便理解. 开局先丢官宣:sec-async-function-definitions 这个链接是对 await 的解释,解释了它的执行. await 的执行意味着(官宣巴拉巴拉 ...

  10. Python学习--11 面向对象高级编程

    多重继承 Python里允许多重继承,即一个类可以同时继承多个类: class Mammal(Animal): pass class Runnable(object): def run(self): ...