精华内容
下载资源
问答
  • tomcat工作原理
    千次阅读
    2020-01-26 21:52:09

    tomcat工作原理(基本过程)


    今天嘞,我们来粗略的谈一下tomcat的工作原理,希望有错误的地方请大家积极指出!

    铺垫知识

    emmm,在说之前我先说一下基本的铺垫知识吧。

    • tomcat是使用java语言编写的
    • 计算机依靠网卡设备和外界交互,网卡将电信号转变为物理信号(0,1),网卡在数据转化完毕之后将数据交给端口
    • 一台电脑最多可以开216个端口,不会出现端口不够用的情况,因为端口开的过多,内存会首先崩掉,所以这么多端口是完全够用的,端口在物理上只有一块地址,逻辑上有很多端口
    • 电脑上的程序和网络进行数据交换,必须要通过端口进行交换
    • 任意两个独立的程序,不能同时占用一个端口,一个独立运行的程序是一个进程,两个线程不能同时占用一个端口,但是一个进程内的线程可以做到数据共享,进程之间做不到数据共享
    • 端口上来了数据之后,程序通过监听端口来得到数据,程序监听是每隔一段时间看一次,称为轮询,发现数据之后就将数据取走。轮询通过while循环来实现
    • tomcat有接收请求返回请求的作用
    • Socket(套接字)用来监听端口接收数据发送数据,socket和网卡直接交互,数据传输的各种标记是由socket来加的,即组装协议格式。在接收数据时,将数据进行提取,去掉各种标记
    • tomcat的代码里包含了socket的实现,因为socket要不断进行轮询,所以这种线程是一直存活的,里面包含了一个死循环,在触发某个条件时,循环终止,进程也结束。
    • tomcat请求分发功能:tomcat接收到请求信息,将请求分配到相应的servlet里面去,这种功能称为请求分发
    • tomcat如何把消息传到servlet中:tomcat和网站都是用java写的,tomcat和这些网站最终会合成一个项目,tomcat中有main方法,可以调用网站中的各种方法
      铺垫知识暂时想起来了这些,下面来看一下tomcat的工作原理

    tomcat工作原理

    • tomcat会扫描webapp文件里的所有Java文件,拿到所有java文件的路径,将带有@webServlet注解信息的java文件挑选出来,挑选出来之后存到map结构中,举个例子:假如我们写了一个名为TestDemoServlet的servlet,并且这个servlet在本地的路径是com.qcby.servlet.TestDemoServlet,那么map中就会这样存放(“TestDemoServlet”:“com.qcby.servlet.TestDemoServlet”)
    • tomcat中的main函数执行下述功能:
    main(){
    	socket监听端口...(此处为轮询)
    	拿到网络数据,数据是字符串的形式str,str1
    	HttpServletRequest request = 字符串处理方法(str);
    	HttpServletResponse respons = 字符串处理方法(str1);
    	String url=request.getHearder("Request URL");//这是经过处理后的url,socket取出各种标记,
    												 //并去掉域名,处理之后的url就是要访问的目标servlet
    	使用Map.get(url);拿到本地路径
    	通过本地路径对目标servlet进行实例化:
    		"com.qcby.servlet.TestDemoServlet"------>class------->newiInstance//这就要用到反射了,因为访问的servlet具有不确定性,
    			 														 	  //所以使用反射可以动态生成各种类的实例
    	//TestDemoServlet ob=new TestDemoservlet();反射的效果和这句话一样
    	生成实例之后,利用代理执行类中的doGet和doPost方法:ss.invoke();
    	执行完之后,将携带的数据发送给socket,由socket组装协议格式,组装完成之后向外界发送数据	
    }
    

    tomcat工作流程图

    为了以防本人说不清楚,所以下面奉上本人画的流程图:
    在这里插入图片描述
    就是这样的一个过程啦!

    更多相关内容
  • Tomcat工作原理

    2020-06-09 23:01:40
    Tomcat是什么 Tomcat 服务器是一个免费的开放源代码的Web 应用服务器,属于轻量级应用服务器,在中小型系统和并发访问用户不是很多的场合下被普遍使用,是开发和调试JSP 程序的首选。 web服务器按功能分类可分为:...

    Tomcat是什么

    Tomcat 服务器是一个免费的开放源代码的Web 应用服务器,属于轻量级应用服务器,在中小型系统和并发访问用户不是很多的场合下被普遍使用,是开发和调试JSP 程序的首选。

    web服务器按功能分类可分为:

    |- Web Server
            |- Http Server
            |- Application Server
                |- Servlet Container
                |- CGI Server
                |- ......

    Http 服务器:

    HTTP Server本质上也是一种应用程序——它通常运行在服务器之上,绑定服务器的IP地址并监听某一个tcp端口来接收并处理HTTP请求,这样客户端(一般来说是IE, Firefox,Chrome这样的浏览器)就能够通过HTTP协议来获取服务器上的网页(HTML格式)、文档(PDF格式)、音频(MP4格式)、视频(MOV格式)等等资源。

    一个HTTP Server关心的是HTTP协议层面的传输和访问控制,所以在Apache/Nginx上你可以看到代理、负载均衡等功能。

    • 客户端通过HTTP Server访问服务器上存储的静态资源(HTML文件、图片文件等等)。
    • 通过CGI/Servlet技术,也可以将处理过的动态内容通过HTTP Server分发,但是一个HTTP Server始终只是把服务器上的文件如实的通过HTTP协议传输给客户端。

    HTTP Server中经常使用的是Apache、Nginx两种,HTTP Server主要用来做静态内容服务、代理服务器、负载均衡等。直面外来请求转发给后面的应用服务(Tomcat,django什么的)。

    |- Http Server
        |- Apache
        |- Nginx

     

    Application 服务器:

    Application Server 是一个应用执行的服务器。它首先需要支持开发语言的 Runtime(对于 Tomcat 来说,就是 Java),保证应用能够在应用服务器上正常运行。其次,需要支持应用相关的规范,例如类库、安全方面的特性。与HTTP Server相比,Application Server能够动态的生成资源并返回到客户端。

    |- Application Server
        |- Tomcat
        |- Jetty

    应用服务器往往也会集成 HTTP Server 的功能,但是不如专业的 HTTP Server 那么强大,所以Application Server往往是运行在 HTTP Server 的背后,执行应用,将动态的内容转化为静态的内容之后,通过 HTTP Server 分发到客户端。

    Tomcat运行在JVM之上,它和HTTP服务器一样,绑定IP地址并监听TCP端口,同时还包含以下指责:

    1. 管理Servlet程序的生命周期;
    2. 将URL映射到指定的Servlet进行处理;
    3. 与Servlet程序合作处理HTTP请求——根据HTTP请求生成HttpServletRequest/Response对象并传递给Servlet进行处理,
       将Servlet中的HttpServletResponse对象生成的内容返回给浏览器;

     Tomcat 属于是一个「Application Server」,但是更准确的来说,是一个「Servlet/JSP」应用的容器。

    Tomcat架构组成

               

        1.Server(服务器): Server的实现类StandardServer可以包含一个到多个Service。

        2.Service(服务): Service的实现类StandardService调用了容器(Container)接口,即Servlet Engine(引擎),并且指明了该

                                      Service归属的Server,它将一个或者多个Connector组件和一个Engine建立关联。

        3.Container(容器): Engine(引擎)、Host(主机)、Context(上下文)均继承自Container接口,它们都是容器。

                                          他们有父子关系,Engine是顶级容器,直接包含Host容器,而Host容器又包含Context容器

                     Engine   在Service组件中有且只有一个;Engine组件从一个或多个Connector中接收请求并处理,

                                   并将完成的响应返回给Connector,最终传递给客户端。

                     Host       定义了一个虚拟主机,一个虚拟主机可以有多个Context

                     Context  每一个运行的webapp其实最终都是以Context的形成存在,每个Context都有一个根路径和请求URL路径,

                                    即每个context就对应一个web应用

        4.Connector(连接器): Connector(连接器)将 Service(服务)和 Container(容器)连接起来,

                                              首先它需要注册到一个Service,它的作用就是把来自客户端的请求转发到Container(容器),

                                              这就是它为什么称作连接器的原因。

    server.xml的整体结构如下:

    <Server>
    <Service>
        <Connector />
        <Connector />
        <Engine>
            <Host>
                <Context /><!-- 现在常常使用自动部署,不推荐配置Context元素,Context小节有详细说明 -->
            </Host>
        </Engine>
    </Service>
    </Server>

    Tomcat工作原理

              

    Tomcat的核心是两个组件:连接器(Connector)容器(Container)

     

    Connector:负责生成 请求对象 和 响应对象,Tomcat默认的是HttpConnector,

                        根据收到的Http请求报文生成Request对象和Response对象,并把这两个对象传递给Container,

                        然后根据Response中的内容生成相应的HTTP报文。

    Container:容器的父接口,所有子容器都必须实现这个接口,就是说服务器部署的项目是运行在Container中的。

                       Container里面的项目获取到Connector传递过来对应的的Request对象和Response对象进行相应的操作。

    多个Connector和一个Container就形成了一个Service,有了Service就可以对外提供

     

    Tomcat要为一个Servlet的请求提供服务,需要做四件事:

        1. 创建一个request对象 并填充那些有可能被所引用的Servlet使用的信息,如参数,头部、cookies、查询字符串等

            一个request对象就是javax.servlet.ServletRequest或javax.servlet.http.ServletRequest接口的一个实例

        2. 创建一个response对象,所引用的servlet使用它来给客户端发送响应

            一个response对象是javax.servlet.ServletResponse或javax.servlet.http.ServletResponse接口的一个实例

        3. 调用servlet的service方法,并传入request和response对象。这里servlet会从request对象取值,给response写值

        4. 根据servlet返回的response生成相应的HTTP响应报文

     

    很多开源应用服务器都是集成tomcat作为web container的,而且对于tomcat的servlet container这部分代码很少改动。

    这样,这些应用服务器的性能基本上就取决于Tomcat处理HTTP请求的connector模块的性能。

     

    Tomcat运行原理分析

        1. Tomcat是运行在JVM中的一个进程。它被定义为-中间件,是一个在 Java 项目与JVM之间的中间容器

        2. Web项目没有入口方法(main方法),意味着Web项目中的方法不会自动运行起来

        3. Web项目部署进Tomcat的webapp中,就是希望Tomcat去调用写好的方法去为客户端返回需要的资源和数据

        4. Tomcat可以运行起来,并调用写好的方法,表明 Tomcat 一定有一个main方法

        5. 对于Tomcat而言,它并不知道我们会有什么样的方法,这些都只是在项目被部署进webapp后才确定,

            因此,Tomcat必然用到了Java的反射来实现类的动态加载、实例化、获取方法、调用方法。

        6. 根据协议和端口号选定Service和Engine

            Service中的Connector组件可接收特定端口的请求,Tomcat启动时,Service组件监听特定的端口。

            Catalina这个Service监听了8080端口(基于HTTP协议)和8009端口(基于AJP协议)。

            请求进来时,Tomcat 根据 协议 和 端口号 选定处理请求的Service;Service一旦选定,Engine也就确定。

        7. 根据域名或IP地址选定Host

            Service确定后,Tomcat在Service中寻找 名称 与 域名/IP地址 匹配的Host处理该请求。

            如果没有找到,则使用Engine中指定的defaultHost来处理该请求。

        8. 根据URI选定Context/Web应用

            Tomcat根据应用的 path属性与URI的匹配程度来选择Web应用处理相应请求

        9.Tomcat如何确定调用什么方法,取决于客户端的请求,比如:http://127.0.0.1:8080/StudentList/index.java?show这样的一个请求,通过http协议 和 8080端口 选定Service;通过主机名(127.0.0.1)选定Host;然后通过uri(/StudentList/index.java?show)选定Web应用

     

    Tomcat运行流程

              

    假设来自客户的请求为:http://localhost:8080/test/index.jsp

        1. 请求被发送到本机端口8080,被在那里侦听的Coyote HTTP/1.1 Connector获得 
        2. Connector把该请求交给它所在的Service的Engine来处理,并等待Engine的回应 
        3. Engine获得请求localhost:8080/test/index.jsp,匹配它所有虚拟主机Host 
        4. Engine匹配到名为localhost的Host(即使匹配不到也把请求交给该Host处理,因为该Host被定义为该Engine的默认主机) 
        5. localhost Host获得请求/test/index.jsp,匹配它所拥有的所有Context 
        6. Host匹配到路径为/test的Context(如果匹配不到就把该请求交给路径名为""的Context去处理) 
        7. path="/test"的Context获得请求/index.jsp,在它的mapping table中寻找对应的servlet 
        8. Context匹配到URL PATTERN为*.jsp的servlet,对应于JspServlet类 
        9. 构造HttpServletRequest对象和HttpServletResponse对象,作为参数调用JspServlet的doGet或doPost方法 
        10.Context把执行完了之后的HttpServletResponse对象返回给Host 
        11.Host把HttpServletResponse对象返回给Engine 
        12.Engine把HttpServletResponse对象返回给Connector 
        13.Connector把HttpServletResponse对象返回给客户browser 
     

     

    展开全文
  • tomcat工作原理

    2018-04-02 10:37:11
    深入理解tomcat工作原理,剖析其工作的过程,tomcat各节点的作用
  • tomcat工作原理.docx

    2022-06-06 21:37:15
    tomcat工作原理.docxtomcat工作原理.docxtomcat工作原理.docxtomcat工作原理.docxtomcat工作原理.docxtomcat工作原理.docxtomcat工作原理.docxtomcat工作原理.docxtomcat工作原理.docx
  • 分析Tomcat工作原理

    2021-01-09 00:45:48
    SpringBoot 就像一条巨蟒,慢慢缠绕着我们,使我们麻痹。不得不承认,使用了 SpringBoot 确实提高了工作...但是,清楚 Tomcat工作原理和处理请求流程和分析 Spring 框架源码一样的重要。至少面试官特别喜欢问这些底
  • tomcat 工作原理

    2012-06-22 21:22:20
    够基础、够循序渐进,加上作者本身对tomcat的深入理解,所以行文中处处向读者传递着tomcat的设计思想,我想这才是大部分人研究tomcat所希望学到的
  • tomcat工作原理,从最简单的socket服务端,客户端开始,逐步扩展!最终手把手教你完成一个简单的servlet 容器。最终彻底搞懂tomcat
  • 有一点需要声明,《深入剖析tomcat》是以tomcat4为样本进行分析的,版本老了一点,但大体的设计思想并不会有太大的变化。 二、模块介绍 2.1、simple_tomcat01 一个简单的程序,只是创建一个ServerSocket,监听8080...
  • tomcat工作原理
  • tomcat工作原理-框架

    2019-04-12 01:17:45
    tomcat工作原理_上_.rar,tomcat工作原理(上).pptx
  • MyTomcat学习 Tomcat工作原理
  • tomcat工作原理深入详解——HowTomcatWorks中文版.pdf
  • tomcat服务器工作原理

    2018-12-28 11:38:12
    更深入的了解tomcat服务器的运行机制 更好的了解底层技术实现。
  • 模拟tomcat工作原理

    2019-05-29 02:40:26
    NULL 博文链接:https://kaobian.iteye.com/blog/1126616
  • Tomcat工作原理之运行机制

    万次阅读 多人点赞 2018-03-25 14:26:48
    一、Tomcat运行原理分析1.Tomcat是运行在JVM中的一个进程。它定义为【中间件】,顾名思义,是一个在Java项目与JVM之间的中间容器。2.Web项目的本质,是一大堆的资源文件和方法。Web项目没有入口方法(main方法),,...

    一、Tomcat运行原理分析
    1.Tomcat是运行在JVM中的一个进程。它定义为【中间件】,顾名思义,是一个在Java项目与JVM之间的中间容器。

    2.Web项目的本质,是一大堆的资源文件和方法。Web项目没有入口方法(main方法),意味着Web项目中的方法不会自动运行起来。

    3.Web项目部署进Tomcatwebapp中的目的是很明确的,那就是希望Tomcat去调用
    写好的方法去为客户端返回需要的资源和数据。
    4. Tomcat
    可以运行起来,并调用写好的方法。那么,Tomcat一定有一个main方法。
    5.
    对于Tomcat而言,它并不知道我们会有什么样的方法,这些都只是在项目被部署进webapp下后才确定的,由此分析,必然用到了Java的反射来实现类的动态加载、实例化、获取方法、调用方法。但是我们部署到Tomcat的中的Web项目必须是按照规定好的接口来进行编写,以便进行调用

    6.Tomcat如何确定调用什么方法呢。这取却于客户端的请求,http://127.0.0.1:8080/JayKing.Tomcat.Study/index.java?show这样的一个请求,通过http协议,在浏览器发往本机的8080端口,携带的参数show方法,包含此方法的路径为JayKing.Tomcat.Study,文件名为:index.java

    二、模拟Tomcat运行

    1.客户端类

    package JayKing.Tomcat.Study;
    import java.io.IOException;
    import java.io.OutputStreamWriter;
    import java.io.Writer;
    import java.net.Socket;
    import java.net.UnknownHostException;
    import java.util.Scanner;
    public class Client {
    	private static int port = 5228;
    	private static String host = "127.0.0.1";
        //http://127.0.0.1:8080/JayKing.Tomcat.Study/index.java?show
    	public static void main(String[] args) {
    		try {
    			Socket con=new Socket(host,port);
    			System.out.println("请输入URL地址:");
    			Scanner scanner=new Scanner(System.in);
    			String info=scanner.nextLine().trim();
    			Writer writer = new OutputStreamWriter(con.getOutputStream());
    			writer.write(info);
    			writer.flush();
    			writer.close();
    		} catch (UnknownHostException e) {
    			// TODO Auto-generated catch block
    			e.printStackTrace();
    		} catch (IOException e) {
    			// TODO Auto-generated catch block
    			e.printStackTrace();
    		}
    	}
    }
    
    
    

    2.服务器类

    package JayKing.Tomcat.Study;
    
    import java.io.BufferedReader;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.InputStreamReader;
    import java.lang.reflect.InvocationTargetException;
    import java.lang.reflect.Method;
    import java.net.ServerSocket;
    import java.net.Socket;
    
    public class TomcatTest {
    	private static int post = 5228;
     
    	private static UrlUtil urlutil = new UrlUtil();
    
    	public static void main(String[] args) {
    		System.out.println(" My Tomcat is Running");
    		try {
    			ServerSocket server = new ServerSocket(post);
    			while (true) {
    				Socket socket = server.accept();// 服务器每接受一次请求,就创建一个socket对象
    				InputStream in = socket.getInputStream();
    				BufferedReader br = new BufferedReader(
    						new InputStreamReader(in));
    				String info = null;
    				String infoline = br.readLine();
    				while (infoline != null) {
    					info =info+infoline;
    					infoline = br.readLine();
    				}
    				UrlBean url = urlutil.readString(info);
    				if (url != null) {
    					String path=url.getPath();
    					String className = url.getFileName();
    					String methodName = url.getParameter().trim();
    					ClassLoader classloader=ClassLoader.getSystemClassLoader();	
    					try {
    						classloader.loadClass(path+"."+className);
    						Class<?> getclass=Class.forName(path+"."+className);
    						Method method=getclass.getMethod(methodName, null);
    						method.invoke(getclass.newInstance(), null);
    						
    					} catch (ClassNotFoundException e) {
    						// TODO Auto-generated catch block
    						e.printStackTrace();
    					} catch (NoSuchMethodException e) {
    						// TODO Auto-generated catch block
    						e.printStackTrace();
    					} catch (SecurityException e) {
    						// TODO Auto-generated catch block
    						e.printStackTrace();
    					} catch (IllegalAccessException e) {
    						// TODO Auto-generated catch block
    						e.printStackTrace();
    					} catch (IllegalArgumentException e) {
    						// TODO Auto-generated catch block
    						e.printStackTrace();
    					} catch (InvocationTargetException e) {
    						// TODO Auto-generated catch block
    						e.printStackTrace();
    					} catch (InstantiationException e) {
    						// TODO Auto-generated catch block
    						e.printStackTrace();
    					}		
    				} else {
    
    				}
    			}
    		} catch (IOException e) {
    			// TODO Auto-generated catch block
    			e.printStackTrace();
    		}
    	}
    }
    

    3.工具类

    package JayKing.Tomcat.Study;
    
    //格式:协议://主机号:端口号/目录路径/文件名
    //例如: http://127.0.0.1:8080/Test/Manage/index.jsp
    public class UrlUtil {
    	public UrlBean readString(String info) {
    		UrlBean url = null;
    		int tag1 = info.indexOf(":");
    		int tag2 = info.lastIndexOf(":");
    		int tag3 = info.indexOf("/", tag2);
    		int tag4 = info.lastIndexOf("/");
    		int tag5 = info.indexOf("?");
    		int tag6=info.lastIndexOf(".");
    		String Protocol = info.substring(0, tag1);
    		String Host = info.substring(tag1 + 3, tag2);
    		String Port = info.substring(tag2 + 1, tag3);
    		String Path = info.substring(tag3 + 1, tag4);
    		String FileName = info.substring(tag4 + 1, tag6);
    		String Parameter = info.substring(tag5 + 1, info.trim().length());
    		if (Host != null && Path != null && FileName != null) {
    			if (Protocol == null) {
    				Protocol = "http";
    			}
    			if (Port == null) {
    				Port = "8080";
    			}
    			url = new UrlBean(Protocol, Host, Port, Path, FileName, Parameter);
    			return url;
    		}
    
    		return url;
    
    	}
    }
    
    4.Model类
    package JayKing.Tomcat.Study;
    
    //格式:协议://主机号:端口号/目录路径/文件名
    //例如: http://127.0.0.1:8080/Test/Manage/index.jsp?a=1&b=2
    public class UrlBean {
    	private String Protocol;
    	private String Host;
    	private String Port;
    	private String Path;
    	private String FileName;
    	private String Parameter;
    
    	public UrlBean(String protocol, String host, String port, String path,
    			String fileName, String parameter) {
    		super();
    		Protocol = protocol;
    		Host = host;
    		Port = port;
    		Path = path;
    		FileName = fileName;
    		Parameter = parameter;
    	}
    
    	public UrlBean() {
    	}
    
    	public String getProtocol() {
    		return Protocol;
    	}
    
    	public void setProtocol(String protocol) {
    		Protocol = protocol;
    	}
    
    	public String getHost() {
    		return Host;
    	}
    
    	public void setHost(String host) {
    		Host = host;
    	}
    
    	public String getPort() {
    		return Port;
    	}
    
    	public void setPort(String port) {
    		Port = port;
    	}
    
    	public String getPath() {
    		return Path;
    	}
    
    	public void setPath(String path) {
    		Path = path;
    	}
    
    	public String getFileName() {
    		return FileName;
    	}
    
    	public void setFileName(String fileName) {
    		FileName = fileName;
    	}
    
    	public String getParameter() {
    		return Parameter;
    	}
    
    	public void setParameter(String parameter) {
    		Parameter = parameter;
    	}
    }
    
    5.测试方法类
    package JayKing.Tomcat.Study;
    public class index {
    	public void show() {
    		System.out.println("方法已经被执行!");
    	}
    }
    

    6.运行结果

     

     

    三、Tomcat原理总结

    1. Tomcat需要main方法启动。
    2. Tomcat需要监听本机上的某个端口。
    3. Tomcat需要抓取此端口上来自客户端的链接并获得请求调用的方法与参数。

    4. Tomcat需要根据请求调用的方法,动态地加载方法所在的类,完成累的实例化并通过该实例获得需要的方法最终将请求传入方法执行。

    5. 将结果返回给客户端(jsp/html页面、json/xml字符串)


     



    展开全文
  • tomcat工作原理-组件

    2019-04-12 01:26:45
    tomcat组件.rar,tomcat组件.pptx
  • tomcat工作原理

    千次阅读 2021-05-20 21:05:51
    本文源自转载:你还记得 Tomcat工作原理么 一、Tomcat 整体架构 Tomcat 是一个免费的、开源的、轻量级的 Web 应用服务器。适合在并发量不是很高的中小企业项目中使用。 二、文件目录结构 以下是 Tomcat 8 ...

    本文源自转载:你还记得 Tomcat 的工作原理么

    一、Tomcat 整体架构

    Tomcat 是一个免费的、开源的、轻量级的 Web 应用服务器。适合在并发量不是很高的中小企业项目中使用。

     

    二、文件目录结构

    以下是 Tomcat 8 主要目录结构

     

    三、功能组件结构

    Tomcat 的核心功能有两个,分别是负责接收和反馈外部请求的连接器 Connector,和负责处理请求的容器 Container。其中连接器和容器相辅相成,一起构成了基本的 web 服务 Service。每个 Tomcat 服务器可以管理多个 Service。

     

    四、Tomcat 连接器核心原理

    Tomcat 连接器框架——Coyote

    4.1 连接器核心功能

    一、监听网络端口,接收和响应网络请求。

    二、网络字节流处理。将收到的网络字节流转换成 Tomcat Request 再转成标准的 ServletRequest 给容器,同时将容器传来的 ServletResponse 转成 Tomcat Response 再转成网络字节流。

    4.2 连接器模块设计

    为满足连接器的两个核心功能,我们需要一个通讯端点来监听端口;需要一个处理器来处理网络字节流;最后还需要一个适配器将处理后的结果转成容器需要的结构。

    对应的源码包路径 org.apache.coyote 。对应的结构图如:

    五、Tomcat 容器核心原理

    Tomcat 容器框架——Catalina

    5.1 容器结构分析

    每个 Service 会包含一个容器。容器由一个引擎可以管理多个虚拟主机。每个虚拟主机可以管理多个 Web 应用。每个 Web 应用会有多个 Servlet 包装器。Engine、Host、Context 和 Wrapper,四个容器之间属于父子关系。

    对应的源码包路径 org.apache.coyote 。对应的结构图如下:

    5.2 容器请求处理

    容器的请求处理过程就是在 Engine、Host、Context 和 Wrapper 这四个容器之间层层调用,最后在 Servlet 中执行对应的业务逻辑。各容器都会有一个通道 Pipeline,每个通道上都会有一个 Basic Valve(如StandardEngineValve), 类似一个闸门用来处理 Request 和 Response 。其流程图如下。

    六、Tomcat 请求处理流程

    上面的知识点已经零零碎碎地介绍了一个 Tomcat 是如何处理一个请求。简单理解就是连接器的处理流程 + 容器的处理流程 = Tomcat 处理流程。哈!那么问题来了,Tomcat 是如何通过请求路径找到对应的虚拟站点?是如何找到对应的 Servlet 呢?

    6.1 映射器功能介绍

    这里需要引入一个上面没有介绍的组件 Mapper。顾名思义,其作用是提供请求路径的路由映射。根据请求URL地址匹配是由哪个容器来处理。其中每个容器都会它自己对应的Mapper,如 MappedHost。不知道大家有没有回忆起被 Mapper class not found 支配的恐惧。在以前,每写一个完整的功能,都需要在 web.xml 配置映射规则,当文件越来越庞大的时候,各个问题随着也会出现

    6.2 HTTP请求流程

    打开 tomcat/conf 目录下的 server.xml 文件来分析一个http://localhost:8080/docs/api 请求。

    第一步:连接器监听的端口是8080。由于请求的端口和监听的端口一致,连接器接受了该请求。

    第二步:因为引擎的默认虚拟主机是 localhost,并且虚拟主机的目录是webapps。所以请求找到了 tomcat/webapps 目录。

    第三步:解析的 docs 是 web 程序的应用名,也就是 context。此时请求继续从 webapps 目录下找 docs 目录。有的时候我们也会把应用名省略。

    第四步:解析的 api 是具体的业务逻辑地址。此时需要从 docs/WEB-INF/web.xml 中找映射关系,最后调用具体的函数。

    <?xml version="1.0" encoding="UTF-8"?>
    <Server port="8005" shutdown="SHUTDOWN">
    
      <Service name="Catalina">
    
    	<!-- 连接器监听端口是 8080,默认通讯协议是 HTTP/1.1 -->
        <Connector port="8080" protocol="HTTP/1.1"
                   connectionTimeout="20000"
                   redirectPort="8443" />
    			   
    	<!-- 名字为 Catalina 的引擎,其默认的虚拟主机是 localhost -->
        <Engine name="Catalina" defaultHost="localhost">
    
    	  <!-- 名字为 localhost 的虚拟主机,其目录是 webapps-->
          <Host name="localhost"  appBase="webapps"
                unpackWARs="true" autoDeploy="true">
    
          </Host>
        </Engine>
      </Service>
    </Server>

    七、SpringBoot 如何启动内嵌的 Tomcat

    SpringBoot 一键启动服务的功能,让有很多刚入社会的朋友都忘记 Tomcat 是啥。随着硬件的性能越来越高,普通中小项目都可以直接用内置 Tomcat 启动。但是有些大一点的项目可能会用到 Tomcat 集群和调优,内置的 Tomcat 就不一定能满足需求了。

    我们先从源码中分析 SpringBoot 是如何启动 Tomcat,以下是 SpringBoot 2.x 的代码。

    代码从 main 方法开始,执行 run 方法启动项目。

    SpringApplication.run

    从 run 方法点进去,找到刷新应用上下文的方法。

    this.prepareContext(context, environment, listeners, applicationArguments, printedBanner);
    this.refreshContext(context);
    this.afterRefresh(context, applicationArguments);

    从 refreshContext 方法点进去,找 refresh 方法。并一层层往上找其父类的方法。

    this.refresh(context);

    在 AbstractApplicationContext 类的 refresh 方法中,有一行调用子容器刷新的逻辑。

    this.postProcessBeanFactory(beanFactory);
    this.invokeBeanFactoryPostProcessors(beanFactory);
    this.registerBeanPostProcessors(beanFactory);
    this.initMessageSource();
    this.initApplicationEventMulticaster();
    this.onRefresh();
    this.registerListeners();
    this.finishBeanFactoryInitialization(beanFactory);
    this.finishRefresh();

    从 onRefresh 方法点进去,找到 ServletWebServerApplicationContext 的实现方法。在这里终于看到了希望。

    protected void onRefresh() {
        super.onRefresh();
    
        try {
            this.createWebServer();
        } catch (Throwable var2) {
            throw new ApplicationContextException("Unable to start web server", var2);
        }
    }

    从 createWebServer 方法点进去,找到从工厂类中获取 WebServer的代码。

    if (webServer == null && servletContext == null) {
        ServletWebServerFactory factory = this.getWebServerFactory();
        // 获取 web server 
        this.webServer = factory.getWebServer(new ServletContextInitializer[]{this.getSelfInitializer()});
    } else if (servletContext != null) {
        try {
            // 启动 web server
            this.getSelfInitializer().onStartup(servletContext);
        } catch (ServletException var4) {
            throw new ApplicationContextException("Cannot initialize servlet context", var4);
        }
    }

    从 getWebServer 方法点进去,找到 TomcatServletWebServerFactory 的实现方法,与之对应的还有 Jetty 和 Undertow。这里配置了基本的连接器、引擎、虚拟站点等配置。

    public WebServer getWebServer(ServletContextInitializer... initializers) {
        Tomcat tomcat = new Tomcat();
        File baseDir = this.baseDirectory != null ? this.baseDirectory : this.createTempDir("tomcat");
        tomcat.setBaseDir(baseDir.getAbsolutePath());
        Connector connector = new Connector(this.protocol);
        tomcat.getService().addConnector(connector);
        this.customizeConnector(connector);
        tomcat.setConnector(connector);
        tomcat.getHost().setAutoDeploy(false);
        this.configureEngine(tomcat.getEngine());
        Iterator var5 = this.additionalTomcatConnectors.iterator();
    
        while(var5.hasNext()) {
            Connector additionalConnector = (Connector)var5.next();
            tomcat.getService().addConnector(additionalConnector);
        }
    
        this.prepareContext(tomcat.getHost(), initializers);
        return this.getTomcatWebServer(tomcat);
    }

    服务启动后会打印日志

    o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat initialized with port(s): 8900 (http)
    o.apache.catalina.core.StandardService   : Starting service [Tomcat]
    org.apache.catalina.core.StandardEngine  : Starting Servlet Engine: Apache Tomcat/8.5.34
    o.a.catalina.core.AprLifecycleListener   : The APR based Apache Tomcat Native library which allows optimal ...
    o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext
    o.s.web.context.ContextLoader            : Root WebApplicationContext: initialization completed in 16858 ms

     

    展开全文
  • IDEA启动tomcat 工作原理

    千次阅读 2018-11-20 10:17:00
    1.IDEA启动tomcat工作原理 idea启动tomcat 会打印: 我们需要关注的是CATALINA_BASE与CATALINA_HOME的区别,这里虽然表示的路径是一样的,配置tomcat多实例的时候就会不一样了 CATALINA_BASE 是tomcat工作目录 ...
  • Tomcat 工作原理——线程池概述 实验
  • Tomcat工作原理祥解

    2011-10-21 10:59:15
    Tomcat工作原理祥解,Tomcat工作原理祥解
  • Tomcat工作原理详解

    千次阅读 2017-03-27 11:27:47
    Tomcat简介  一、Tomcat背景  自从JSP发布之后,推出了各式各样的JSP引擎。Apache Group在完成GNUJSP1.0的开发以后,开始考虑在SUN的JSWDK基础上开发一个可以直接提供Web服务的JSP服务器,当然同时也支持...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 146,917
精华内容 58,766
关键字:

tomcat工作原理