- Catalina catalina = new Catalina(); // 没做其他事情
- catalina.setAwait(true);
- 以下步骤是解析servler.xml
- StandardServer server = new StandardServer(); // 没做其他事情
- catalina.setServer(server);
- server.addLifecycleListener(...);
- StandardService service = new StandardService(); // 没做其他事情
- server.addService(service);
- Connector connector = new Connector(); // 会根据配置初始化protocolHandler
-
- endpoint = new JIoEndpoint(); // 初始化Endpoint, JioEndpoint中会setMaxConnections(0);
- cHandler = new Http11ConnectionHandler(this); //
-
- ((JIoEndpoint) endpoint).setHandler(cHandler); // endpoint对应的连接处理器
- service.addConnector(connector);
- Engine engine = new StandardEngine(); // pipeline.setBasic(new StandardEnginevalve());
- service.setContainer(engine);
- Host host = new StandardHost(); // pipeline.setBasic(new StandardHostValve());
- engine.addChild(host);
- Context context = new StandardContext(); // pipeline.setBasic(new StandardContextValve());
- host.addChild(context);
- engine.setParentClassLoader(Catalina.class.getClassLoader()); // 实际调用的是Containerbase.setParentClassLoader方法,设置属性parentClassLoader为shareClassLoader
- server.setCatalina(catalina);
- server.init(); // 开始初始化
- catalina.start(); // 开始启动
解析server.xml最主要的作用就是
- 把server.xml中定义的节点都生成对应的java对象,比如在解析某一个Host节点时就会对应生成一个StandardHost对象
- 把server.xml中定义的节点的层级关系解析出来,比如StandardContext对象.addChild(StandardHost对象)
- 设置每个容器的pipeline的基础Valve
Tomcat初始化主要做了以下事情:
- 将StandardServer实例注册到JMX
- 将StringCache实例注册到JMX
- 将StandardService实例注册到JMX
- container.init(); // 对StandardEngine进行初始化
-
- 初始化startStopExecutor线程池,用来启动子容器的
- connector.init(); // 对Connector进行初始化
-
- adapter = new CoyoteAdapter(this);
- protocolHandler.setAdapter(adapter);
-
- protocolHandler.init(); // 初始化协议处理器
-
-
- endpoint.init(); // 初始化协议处理器对应的endpoint,默认在初始化的时候就会bind
-
-
-
-
- endpoint.bind()
-
-
-
-
-
-
- serverSocketFactory = new DefaultServerSocketFactory(this);
- serverSocket = serverSocketFactory.createSocket(getPort(), getBacklog(), getAddress());
-
-
-
-
- mapperListener.init(); // 没做什么其他的
初始化做得事情比较少,最重要的可能就是endpoint的bind的了
启动- catalina.start()
- getServer().start();
-
- fireLifecycleEvent(CONFIGURE_START_EVENT, null);
- services[i].start();
-
-
- container.start(); // 启动StandardEngine
-
-
-
-
- results.add(startStopExecutor.submit(new StartChild(children[i]))); // 每个Childrean容器(StandardHost)用单独的线程启动
-
-
-
-
-
-
- results.add(startStopExecutor.submit(new StartChild(children[i]))); // 每个Childrean容器(StandardContext)用单独的线程启动
-
-
-
-
-
-
-
-
- 以下为一个应用的启动过程
- 生成一个WebappLoader
-
-
-
-
-
-
-
-
-
- 启动WebappLoader
-
-
-
-
-
-
-
-
-
-
- 生成WebappClassLoader
- 将/WEB-INF/classes和/WEB-INF/lib目录作为loaderRepositories,后面应用如果加载类就从这两个目录加载
-
-
-
-
-
-
-
-
-
-
- fireLifecycleEvent(Lifecycle.CONFIGURE_START_EVENT, null);
-
-
-
-
-
-
-
-
-
-
- 解析web.xml文件
-
-
-
-
-
-
-
-
-
-
-
-
- 创建WebXml对象
- 解析web.xml文件内容设置WebXml对象属性
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- WebXML对象有以下几个主要属性
- Map
servlets
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Map
servletMappings - Map
filters
- Map
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Set
filterMaps
- Set
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 收集ServletContainerInitializers
- 将WebXML对象中的信息配置到Context对象中
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- context.addFilterDef(filter);
- context.addFilterMap(filterMap);
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- context.addApplicationListener(listener);
- 遍历每个ServletDef,生成一个Wrapper,context.addChild(wrapper);
-
-
-
-
-
-
-
-
-
-
-
-
- 调用ServletContainerInitializers
-
-
-
-
-
-
-
-
- 上面会启动在server.xml中定义的Context,接下来会启动webapp文件夹下面的Context,是通过HostConfig触发的,调用HostConfig的start()
-
-
-
-
-
-
-
-
- deployApps();
-
-
-
-
-
-
-
-
-
-
- deployDescriptors(configbase, configbase.list()); // 描述符部署
- deployWARs(appbase, filteredAppPaths); // war包部署
-
-
-
-
-
-
-
-
-
-
-
- deployDirectories(appbase, filteredAppPaths); // 文件夹部署
-
-
-
-
-
-
-
-
-
-
-
-
- 生成Context对象
- context.setName(cn.getName());
-
-
-
-
-
-
-
-
-
-
-
-
-
- context.setPath(cn.getPath());
- host.addChild(context); // 这里会启动context,启动Context就会执行和上面类似的步骤
-
-
-
-
-
-
-
-
-
- threadStart(); // 启动一个background线程
-
-
-
-
- executor.start(); // 启动线程池, 如果用的默认连接池,这里不会启动
- connector.start(); // 启动请求连接器
-
-
-
-
- protocolHandler.start(); // 启动接收连接
-
-
-
-
-
-
- endpoint.start(); // 启动Endpoint
-
-
-
-
-
-
-
-
- 如果没有配置Executor,就创建一个默认的Executor
- 初始化connectionLimitLatch
-
-
-
-
-
-
-
-
-
- 如果是NIO,则运行Poller线程
- 运行Acceptor线程
-
-
-
-
-
-
-
- mapperListener.start();
-
-
-
-
-
-
- 主要初始化Mapper对象,Mapper对象的结构层级如下
-
-
-
-
-
-
-
-
- Mapper中有属性Host[] hosts
- Host中有属性ContextList contextList
-
-
-
-
-
-
-
-
-
- ContextList中有属性Context[] contexts
- Context中有属性ContextVersion[] versions
-
-
-
-
-
-
-
-
-
- ContextVersion中有如下属性
-
-
-
-
-
-
-
-
-
-
- Wrapper[] exactWrappers,保存需要根据Servlet名字精确匹配的Wrapper
- Wrapper[] wildcardWrappers,保存需要根据Servlet名字匹配以("/*")结尾的Wrapper
-
-
-
-
-
-
-
-
-
-
-
- Wrapper[] extensionWrappers,保存需要根据Servlet名字匹配以("*.")开始的Wrapper
- Wrapper中有如下两个属性
-
-
-
-
-
-
-
-
-
-
-
-
- name,Wrapper的名字
- object,真实的Wrapper的对象
-
-
-
-
-
-
- catalina.await(); // 使用ServerSocket来监听shutdown命令来阻塞
- catalina.stop(); // 如果阻塞被解开,那么开始停止流程
启动做的事情就比较多了,主要分为以下几大步骤
启动容器
启动容器主要是部署应用,部署应用分为两部分:
- 部署server.xml中定义的Context
- 部署webapp文件夹下的Context
部署一个应用主要分为以下步骤
- 生成Context对象,server.xml中定义的Context在解析server.xml时就已经生成了,webapp文件夹下的是在部署之前生成的
- 为每个应用生成一个WebappClassLoader
- 解析web.xml
- 设置Context对象中的属性,比如有哪些Wrapper
启动Connector
主要是:
- 启动Endpoint开始接收请求
- 构造Mapper对象,用来处理请求时,快速解析出当前请求对应哪个Context,哪个Wrapper
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)