当前位置:   article > 正文

Tomcat知识点(深入剖析Tomcat学习笔记)_深入剖析tomcat pdf

深入剖析tomcat pdf

servlet容器的3步操作

  1. 创建一个request对象
  2. 创建一个调用Servlet的response对象,用来向Web客户端发送响应
  3. 调用Servlet的service()方法

Catalina是一种Servlet容器

Catalina的两个模板:连接器(connector)和容器(container)

连接器:负责将一个请求与容器相关联(为每一个接收到的Http请求创建一个request对象和一个response对象,然后将处理过程交给容器)

容器:从连接器中接收request对象和response对象,并负责调用响应的Servlet的service对象

连接器

连接器的基本操作

连接服务器

  1. public class HttpConnector implements Runnable {
  2. boolean stopped;
  3. private String scheme = "http";
  4. @Override
  5. public void run() {
  6. ServerSocket serverSocket = null;
  7. int port = 8080;
  8. try {
  9. serverSocket = new ServerSocket(port, 1, InetAddress.getByName("127.0.0.1"));
  10. } catch (IOException e) {
  11. e.printStackTrace();
  12. System.exit(1);
  13. }
  14. while (!stopped) {
  15. Socket socket = null;
  16. try {
  17. socket = serverSocket.accept();
  18. } catch (IOException e) {
  19. e.printStackTrace();
  20. }
  21. HttpProcessor processor = new HttpProcessor(this);
  22. processor.process(socket);
  23. }
  24. }
  25. public void start() {
  26. Thread thread = new Thread(this);
  27. thread.start();
  28. }
  29. }

处理

  1. public class HttpProcessor {
  2. private HttpConnector httpConnector;
  3. private HttpRequest request;
  4. private HttpResponse response;
  5. public HttpProcessor(HttpConnector httpConnector) {
  6. this.httpConnector = httpConnector;
  7. }
  8. public void process(Socket socket) {
  9. SocketInputStream inputStream = null;
  10. OutputStream outputStream = null;
  11. try {
  12. inputStream = new SocketInputStream(socket.getInputStream(), 2048);
  13. outputStream = socket.getOutputStream();
  14. request = new HttpRequest(inputStream);
  15. response=new HttpResponse(outputStream);
  16. response.setRequest(request);
  17. response.setHeader("Server", "Jsq Servlet Container");
  18. parseRequest(inputStream, outputStream);
  19. parseHeader(inputStream);
  20. if (request.getRequestURI().startWith("/servlet/")) {
  21. ServletProcessor processor = new ServletProcessor();
  22. processor.process(request,response);
  23. }else{
  24. StaticResourceProcessor processor = new StaticResourceProcessor();
  25. processor.process(request, response);
  26. }
  27. socket.close();
  28. } catch (IOException e) {
  29. e.printStackTrace();
  30. }
  31. }
  32. }

Tomcat中的连接器

容器

处理请求servlet资源,并为Web客户端填充填充response对象

容器与连接器的连接关系

  1. HttpConnector connector = new HttpConnector();
  2. SimpleContainer container = new SimpleContainer();
  3. connector.setContainer(container);

4种类型的容器(Engine、Host、Context、Wrapper)

  1. Engine:表示整个Catalina servlet引擎
  2. Host:表示包含有一个或多个context容器的虚拟主机
  3. Context:表示一个Web应用程序,一个Context可以有多个Wrapper
  4. Wrapper:表示一个独立的servlet

Engine>Host>Context>Wrapper(包含关系)

容器中的管道任务

4个接口:Pipeline(addValve方法添加阀)、Valve(阀,用来处理接收到的请求)、ValveContext(实现依次调用阀)、Contained(限制至多与一个servlet容器相关联)

一个servlet容器中有一条管道,当调用容器的invoke方法,容器会将处理工作交给管道处理,管道会从第一个阀开始,依次执行任务,知道所有任务执行完成为止(调用ValveContext实例的invokeNext方法)

Wrapper(一个独立的servlet)

  1. 管理基础servlet生命周期(调用servlet的init()、service()、destroy()等方法)
  2. Wrapper是最低级的servlet容器,不能再向其中添加子容器
  3. load()载入并初始化servlet类
  4. allocate()分配一个已经初始化的servlet实例

一个Wrapper的实现

  1. public static void main(String[] args) {
  2. HttpConnector connector = new HttpConnector();
  3. SimpleWrapper wrapper = new SimpleWrapper();
  4. wrapper.setServletClass("ModernServlet");
  5. SimpleLoader loader = new SimpleLoader();
  6. HeaderLoggerValve headerLoggerValve = new HeaderLoggerValve();
  7. ClientIPLoggerValve clientIPLoggerValve = new ClientIPLoggerValve();
  8. wrapper.setLoader(loader);
  9. ((Pipeline) wrapper).addValve(headerLoggerValve);
  10. ((Pipeline) wrapper).addValve(clientIPLoggerValve);
  11. connector.setContainer(wrapper);
  12. try {
  13. connector.initialize();
  14. connector.start();
  15. System.in.read();
  16. } catch (IOException e) {
  17. e.printStackTrace();
  18. }
  19. }

Context(一个Web应用程序)

  1. 一个Context实例可以有一个或多个Wrapper实例作为子容器
  2. addWrapper()方法和createWrapper()方法

一个Context实现

  1. public static void main(String[] args) {
  2. HttpConnector connector = new HttpConnector();
  3. SimpleWrapper wrapper1 = new SimpleWrapper();
  4. wrapper1.setName("Modern");
  5. wrapper1.setServletClass("ModernServlet");
  6. SimpleWrapper wrapper2 = new SimpleWrapper();
  7. wrapper2.setName("Primitive");
  8. wrapper2.setServletClass("Primitive");
  9. SimpleContext context = new SimpleContext();
  10. context.addChild(wrapper1);
  11. context.addChild(wrapper2);
  12. HeaderLoggerValve headerLoggerValve = new HeaderLoggerValve();
  13. ClientIPLoggerValve clientIPLoggerValve = new ClientIPLoggerValve();
  14. context.setLoader(loader);
  15. ((Pipeline) context).addValve(headerLoggerValve);
  16. ((Pipeline) context).addValve(clientIPLoggerValve);
  17. SimpleContextMapper mapper = new SimpleContextMapper();
  18. mapper.setProtocol("http");
  19. context.addMapper(mapper);
  20. SimpleLoader loader = new SimpleLoader();
  21. context.setLoader(loader);
  22. context.addServletMapping("/Primitive","Primitive");
  23. context.addServletMapping("/Modern","Modern");
  24. connector.setContainer(context);
  25. try {
  26. connector.initialize();
  27. connector.start();
  28. System.in.read();
  29. } catch (IOException e) {
  30. e.printStackTrace();
  31. }
  32. }

原理

  1. 容器中包含一个管道,容器的invoke方法会调用管道的invoke方法(如:SimpleContext类的invoke方法调用pipeline的invoke方法)

  2. 管道的invoke方法会调用所有添加到其容器中的阀,再调用其基础阀的invoke方法(pipeline的invoke方法调用pipelineValveContext的invokeNext,包含ContextValve的invoke方法)

  3. 在Wrapper实例中,基础阀负责载入相关联的servlet类,并对请求进行响应(ContextValve的invoke方法)

  4. 在包含子容器的Context实例中,基础阀使用映射器来查找一个子容器,该子容器负责处理接收到的请求,若找到相应的子容器,则调用器invoke方法,转到步骤1继续执行(ContextValve的invoke方法中,context.map(request,true),分配servlet实例,并调用它的service()方法)

  5. context.map方法中

    String name = context.findServletMapping(relativeURI) wrapper = (Wrapper) context.findChild(name)
    

    start具体步骤

Host(包含有一个或多个context容器的虚拟主机)

若一个Context实例使用ContextConfig对象进行设置,就必须使用一个Host对象,使用ContextConfig对象需要知道应用程序web.xml文件的位置,这里代码显示Context实例需要一个Host实例作为其父容器

  1. StandardHost host = new StandardHost();
  2. host.addChild(context);
  3. host.setName("localhost");
  4. host.setAppBase("webapps");
  5. connector.setContainer(host);

Engine(一个独立的servlet)

支持多个Host(虚拟机)

  1. SimpleEngine engine = new SimpleEngine();
  2. engine.addChild(host);
  3. engine.setDefaultHost("localhost");
  4. connector.setContainer(engine);

容器的生命周期管理

Catalina启动或关闭的时候,它的组件也一起启动或关闭

Catalina允许一个组件包含其他组件,Catalina启动类只要启动一个组件便可以将应用程序的所有组件启动

Lifecycle、LifecycleEvent、LifecycleListener、LifecycleSupport

Lifecycle接口

BEFORE_START_EVENT、START_EVENT、AFTER_START_EVENT在组件启动时触发

BEFORE_STOP_EVENT、STOP_EVENT、AFTER_STOP_EVENT在组件关闭时触发

Context实现Lifecycle的方式

public class SimpleContext implements Context
public interface Context extends Container
public interface Container extends Lifecycle

实现addLifecycleListener、findLifecycleListeners、removeLifecycleListener方法

start方法中(启动组件和子容器)

  1. public void start() throws LifecycleException {
  2. lifecycle.fireLifecycleEvent(BEFORE_INIT_EVENT,null);
  3. started=true;
  4. //启动加载器
  5. if ((loader != null) && (loader instanceof Lifecycle)) {
  6. ((Lifecycle) loader).start();
  7. }
  8. //启动子容器
  9. Container children[] = findChildren();
  10. for (int i = 0; i < children.length; i++) {
  11. if (children[i] instanceof Lifecycle) {
  12. ((Lifecycle) children[i]).start();
  13. }
  14. }
  15. //启动pipeline
  16. if (pipeline instanceof Lifecycle) {
  17. ((Lifecycle) pipeline).start();
  18. lifecycle.fireLifecycleEvent(START_EVENT, null);
  19. }
  20. lifecycle.fireLifecycleEvent(AFTER_INIT_EVENT, null);
  21. }

stop方法中(关闭组件和子容器)

  1. public void stop() throws LifecycleException {
  2. lifecycle.fireLifecycleEvent(BEFORE_STOP_EVENT,null);
  3. lifecycle.fireLifecycleEvent(STOP_EVENT,null);
  4. started=false;
  5. //关闭pipeline
  6. if (pipeline instanceof Lifecycle) {
  7. ((Lifecycle) pipeline).stop();
  8. }
  9. //关闭子容器
  10. Container children[] = findChildren();
  11. for (int i = 0; i < children.length; i++) {
  12. if (children[i] instanceof Lifecycle) {
  13. ((Lifecycle) children[i]).stop();
  14. }
  15. }
  16. //关闭加载器
  17. if ((loader != null) && (loader instanceof Lifecycle)) {
  18. ((Lifecycle) loader).stop();
  19. }
  20. lifecycle.fireLifecycleEvent(AFTER_STOP_EVENT, null);
  21. }

LifecycleEvent(生命周期事件)

Lifecycle作为入参

LifecycleListener接口(生命周期的事件监听器)

当某个事件监听器监听到相关事件发生时,会调用该方法

LifecycleSupport(帮助管理监听器,并触发相应的生命周期事件)

容器的组件

载入器(Loader)

servlet只允许载入WEB-INF/classes目录及其子目录下的类。和WEB-INFO/lib目录下的库

Logger接口的setContainer和getContainer方法使日志记录器和某个servlet容器相关联

Loader接口的setContainer和getContainer方法使载入器和某个servlet容器相关联

或context的setLoader方法使载入器和某个servlet容器相关联

Loader loader =new WebAppLoader()
context.setLoader(loader)

日志记录器(Logger)

Logger接口的setContainer和getContainer方法使日志记录器和某个servlet容器相关联

或context的setLogger方法使日志记录器和某个servlet容器相关联

SystemOutLogger、SystemErrLogger、FileLogger

Bootstrap中

System.setProperties("catalina.base", System.getProperties("user.dir"));
FileLogger logger = new FileLogger();
logger.setPrefix("FileLog_");
logger.setSuffix(".txt");
logger.setTimeStamp(true);
logger.setDirectory("webroot");
context.setLogger(logger);

Session 管理器(Manager)

Manager接口的setContainer和getContainer方法使管理器和某个servlet容器相关联

或context的setManager方法使管理器和某个servlet容器相关联

领域(Realm)(保证安全性)

一个阀(验证器),对当前用户进行身份验证,验证器调用context的领域对象的authenticate()方法验证

context的setRealm方法使管理器和某个servlet容器相关联

资源(Resource)

服务器组件和服务组件(serve和service)

服务器组件提供一种优雅的方式启动和关闭整个Catalina部署(initialize、start、stop、await方法)(addService方法添加服务组件)

服务组件封装了servlet容器和连接器之间的关系(可以有一个servlet容器和多个连接器组成)

  1. StandardService service = new StandardService();
  2. service.setName("Stand-alone Service");
  3. StandardServer server = new StandardServer();
  4. server.addService(service);
  5. service.setContainer(engine);
  6. service.addConnector(connector);
  7. if (server instanceof Lifecycle) {
  8. try {
  9. server.initialize();
  10. ((Lifecycle) server).start();
  11. server.await();
  12. } catch (IOException e) {
  13. e.printStackTrace();
  14. }
  15. }

Digester库(用来将XML文档中的元素转换成java对象)

部署器

用来部署和安装Web应用程序,是Deployer接口的实例

要使用一个Web应用程序,必须要将表示该应用程序的Context实例部署到一个Host实例中。在Tomcat中,Context实例可以用WAR文件的形式部署,也可以将整个Web应用程序复制到Tomcat安装目录下的webapp下,对于部署的每个应用程序,可以在其中包含一个描述符文件,该文件包含Context实例的配置信息,描述符文件采用xml文档格式。

HostConfig类型的生命周期监听器,来将Context实例添加到Host实例中。HostConfig实例的start方法会逐个部署和安装指定目录中的所有Web应用程序,HostConfig类的start方法有deployApps方法,deployApps方法中会调用deployDescriptors()、deployWARs()、deployDirectories()方法来部署Context实例(web应用程序)

关闭钩子

在正常关闭(System.exit()或程序的最后一个非守护进程线程退出)和虚拟机突然中断时,虚拟机启动所有已经注册的关闭钩子(关闭钩子是先前已经通过Runtime类注册的线程),所有关闭钩子会并发执行,直到完成任务。然后虚拟机根据情况调用所有没有被调用过的终结器。(无论用户如何关闭应用程序,清理代码总是能够得到执行)

创建关闭钩子

  1. 创建一个Thread类的子类,实现子类的run方法
  2. 在应用程序中实例化关闭钩子类
  3. 在当前Runtime类的addShutdownHook方法注册关闭钩子
  1. public class ShutdownHook extends Thread{
  2. @Override
  3. public void run() {
  4. System.out.println("shutdown");
  5. }
  6. }
  7. ShutdownHook shutdownHook = new ShutdownHook();
  8. Runtime.getRuntime().addShutdownHook(shutdownHook);

启动Tomcat(Catalina类和Bootstrap类)

Catalina类用于启动和关闭Server对象,并负责解析Tomcat配置文件(server.xml)

Catalina包含一个Digester对象解析server.xml,一个Server对象,Server对象有一个Service对象,Service对象包含一个Servlet容器和一个或多个连接器

Bootstrap类是一个入口点,负责创建Catalina实例,并调用process()方法,作为一个独立的应用程序运行Tomcat。

Manager应用程序的Servlet类

Manager应用程序用于管理已经部署的Web应用程序(如显示已部署Web应用程序信息)

基于JMX的管理

JMX(java manager extensions)

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小丑西瓜9/article/detail/500785
推荐阅读
相关标签
  

闽ICP备14008679号