找回密码
立即注册
搜索
热搜: Java Python Linux Go
发回帖 发新帖

2440

积分

0

好友

328

主题
发表于 7 小时前 | 查看: 5| 回复: 0

Tomcat 目录结构

Tomcat 的核心目录结构清晰定义了其功能和配置的存放位置,了解它们是理解其工作原理的第一步。

目录/文件 核心用途 与配置的关系
bin/ 存放启动(startup.sh/bat)、关闭(shutdown.sh/bat)及环境设置脚本。 脚本中会引用 conf 下的配置来启动 JVM。
conf/ 核心配置目录。存放全局配置文件。 server.xml (主配置), web.xml (全局默认配置), tomcat-users.xml (用户权限), context.xml (上下文默认配置)。
logs/ 存放运行日志(catalina.out, localhost.log 等)。 记录 server.xml 中定义的 Host 和 Context 的运行状态及错误。
webapps/ 默认应用部署目录。将 WAR 包或文件夹放入此处会自动部署。 每个子目录代表一个 Web 应用,内部包含该应用特有的 WEB-INF/web.xml

各目录之间的关键关系如下:

  • conf/server.xml 定义了 Tomcat 的整体架构(端口、主机、引擎)。
  • conf/web.xml 定义了所有 Web 应用的默认行为(如默认 Servlet 映射、MIME 类型、会话超时时间)。
  • webapps/<app>/WEB-INF/web.xml 是特定应用的配置,它会覆盖或补充 conf/web.xml 中的配置。
  • webapps/ 下的文件内容受 server.xml<Host>标签的 appBase 属性控制。

Tomcat 核心配置文件

server.xml

server.xml 是 Tomcat 的主配置文件,位于 conf/ 目录下,它定义了整个容器的层级结构和核心组件,是理解其架构的关键。

  • <Server>: 根元素,代表整个 Tomcat 实例。
  • <Service>: 包含一个 Engine 和多个 Connector。用于将来自不同端口的请求关联到同一个处理引擎。
  • <Connector>: 连接器。负责接收客户端请求(HTTP/HTTPS/AJP)。
    • 关键属性:port (端口), protocol (协议处理器), connectionTimeout
    • 作用:建立 TCP 连接,解析 HTTP 报文,生成 Request/Response 对象传给 Engine。
  • <Engine>: 引擎。处理来自 Connector 的请求。一个 Service 只能有一个 Engine。
    • 关键属性:defaultHost (默认主机名)。
    • 作用:根据请求的域名将请求分发给对应的 Host。
  • <Host>: 虚拟主机。对应一个域名(如 localhostwww.example.com)。
    • 关键属性:name, appBase (应用基础目录,默认为 webapps)。
    • 作用:管理该域名下的所有 Web 应用(Context),实现多站点部署。
  • <Context>: Web 应用上下文。代表一个具体的 Web 应用(如 /myapp)。
    • 作用:定义应用的路径、资源链接、会话配置等。
    • 注意:在 Tomcat 9+ 中,通常建议在 conf/Catalina/localhost/ 下单独配置 XML 文件,而不是直接写在 server.xml 中,以避免因修改应用配置而重启整个服务。

一个典型的 server.xml 配置示例如下:

<?xml version="1.0" encoding="UTF-8"?>
<!--
Server: 根元素,代表整个 Tomcat 实例。
port="8005": 监听关闭命令的端口
shutdown="SHUTDOWN": 关闭指令字符串。 (telnet localhost 8005 发送 SHUTDOWN 可停止服务)。
-->
<Server port="8005" shutdown="SHUTDOWN">
  <Listener className="org.apache.catalina.startup.VersionLoggerListener" />
  <Listener className="org.apache.catalina.core.AprLifecycleListener" SSLEngine="on" />
  <Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener" />

  <!-- Service: 包含一个 Engine 和多个 Connector。名称通常默认为 "Catalina"。-->
  <Service name="Catalina">

    <!--
        Connector: 连接器,负责接收客户端请求。
        protocol: 使用 NIO (非阻塞 IO) 协议。
        port: 服务端口,默认 8080。
        connectionTimeout: 连接超时时间 (毫秒)。
        redirectPort: 如果收到 HTTPS 请求,重定向到此端口 (默认 8443)。
        -->
    <Connector port="8080" protocol="HTTP/1.1"
               connectionTimeout="20000"
               redirectPort="8443"
               maxThreads="200"
               minSpareThreads="25" />

    <!--
        Engine: 处理请求的核心容器。
        defaultHost: 当请求的 Host 头不匹配任何定义的 Host 时,使用此主机。
        -->
    <Engine name="Catalina" defaultHost="localhost">

      <!--
          Host: 虚拟主机,对应一个域名或 IP。
          name: 主机名 (如 www.example.com 或 localhost)。
          appBase: 应用部署的基础目录,默认为 webapps。
          unpackWARs: 是否自动解压 WAR 包。
          autoDeploy: 是否自动检测并部署新的应用。
          -->
      <Host name="localhost" appBase="webapps"
            unpackWARs="true" autoDeploy="true">

        <!-- AccessLogValve: 记录访问日志 -->
        <Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
               prefix="localhost_access_log" suffix=".txt"
               pattern="%h %l %u %t "%r" %s %b" />

        <!--
            Context: 代表一个具体的 Web 应用。
            注意:在生产环境中,通常不建议直接在 server.xml 中配置 Context,
            而是建议在 $CATALINA_BASE/conf/Catalina/localhost/ 目录下创建单独的 XML 文件。
            path: 应用的访问路径 (如 /myapp)。
            docBase: 应用的实际物理路径 (可以是绝对路径,也可以是 appBase 下的相对路径)。
            -->
        <Context path="/myapp" docBase="myapp" reloadable="true" />

        <!-- 默认 Context: 代表根路径 "/" 的应用 (通常是 manager 或 host-manager,或者默认的欢迎页) -->
        <!-- <Context path="" docBase="ROOT" /> -->

      </Host>
    </Engine>
  </Service>
</Server>

web.xml

Tomcat 中有两个层级的 web.xml,它们共同定义了 Web 应用的行为:

  • 1、全局默认配置 (conf/web.xml):为服务器上所有应用提供默认设置。它定义了默认的 Servlet(如 default 处理静态资源,jsp 处理 JSP 文件)、默认的 MIME 映射、会话超时时间(默认 30 分钟)、欢迎页面列表等。
  • 2、应用级配置 (WEB-INF/web.xml):位于每个 Web 应用内部,用于配置该应用特有的 Servlet、Filter、Listener、初始化参数、安全约束等。

加载顺序:Tomcat 启动时先加载 conf/web.xml,再加载应用的 WEB-INF/web.xml。应用配置会覆盖全局配置中同名的设置。

一个典型的应用级 web.xml 配置示例如下:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
         http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
         version="4.0">

  <!-- 1. 应用描述 -->
  <display-name>My Demo Application</display-name>
  <description>This is a sample web application for Tomcat analysis.</description>

  <!-- 2. 上下文参数 (Context Param): 全局初始化参数,所有 Servlet 都可访问 -->
  <context-param>
    <param-name>dbDriver</param-name>
    <param-value>com.mysql.cj.jdbc.Driver</param-value>
  </context-param>
  <context-param>
    <param-name>dbUrl</param-name>
    <param-value>jdbc:mysql://localhost:3306/mydb</param-value>
  </context-param>

  <!-- 3. Listener: 监听器,用于监听应用生命周期事件 -->
  <listener>
    <listener-class>com.example.listener.AppInitListener</listener-class>
  </listener>

  <!-- 4. Filter: 过滤器,拦截请求进行处理 (如编码设置、权限验证) -->
  <filter>
    <filter-name>CharacterEncodingFilter</filter-name>
    <filter-class>org.apache.catalina.filters.SetCharacterEncodingFilter</filter-class>
    <init-param>
      <param-name>encoding</param-name>
      <param-value>UTF-8</param-value>
    </init-param>
    <init-param>
      <param-name>forceRequest</param-name>
      <param-value>true</param-value>
    </init-param>
  </filter>
  <filter-mapping>
    <filter-name>CharacterEncodingFilter</filter-name>
    <url-pattern>/*</url-pattern><!-- 拦截所有请求 -->
  </filter-mapping>

  <!-- 5. Servlet: 核心组件,处理业务逻辑 -->
  <servlet>
    <servlet-name>HelloServlet</servlet-name>
    <servlet-class>com.example.servlet.HelloServlet</servlet-class>
    <!-- 初始化参数,仅该 Servlet 可见 -->
    <init-param>
      <param-name>greeting</param-name>
      <param-value>Hello World</param-value>
    </init-param>
    <!-- 加载顺序: 数字越小越先加载,负数或无表示按需加载 -->
    <load-on-startup>1</load-on-startup>
  </servlet>
  <servlet-mapping>
    <servlet-name>HelloServlet</servlet-name>
    <url-pattern>/hello</url-pattern><!-- 访问 http://host:port/app/hello -->
  </servlet-mapping>

  <!-- 另一个 Servlet 示例 -->
  <servlet>
    <servlet-name>UserServlet</servlet-name>
    <servlet-class>com.example.servlet.UserServlet</servlet-class>
  </servlet>
  <servlet-mapping>
    <servlet-name>UserServlet</servlet-name>
    <url-pattern>/user/*</url-pattern><!-- 路径映射,匹配 /user/xxx -->
  </servlet-mapping>

  <!-- 6. Welcome File List: 默认首页列表 -->
  <welcome-file-list>
    <welcome-file>index.html</welcome-file>
    <welcome-file>index.jsp</welcome-file>
    <welcome-file>default.html</welcome-file>
  </welcome-file-list>

  <!-- 7. Error Page: 自定义错误页面 -->
  <error-page>
    <error-code>404</error-code>
    <location>/error/404.html</location>
  </error-page>
  <error-page>
    <exception-type>java.lang.Exception</exception-type>
    <location>/error/general_error.jsp</location>
  </error-page>

</web-app>

Catalina 容器组件架构

Catalina 是 Apache Tomcat 的核心 Servlet 容器引擎,其核心架构设计遵循了分层处理责任链模式。理解其内部组件如何协同工作是掌握 Tomcat 工作机理的关键。

主要组件如下:

  • Connector (连接器):基于 NIO/NIO2/APR 模型。负责网络通信,解析 HTTP 协议,将原始请求封装成标准的 Request 对象,并将 Response 对象写回客户端。
  • Container (容器):负责处理业务逻辑,内部也是分层结构:
    • Engine:顶级容器,匹配 Host。
    • Host:虚拟主机容器,匹配 Context。
    • Context:应用容器,匹配 Wrapper (Servlet)。
    • Wrapper:最底层容器,管理单个 Servlet 的生命周期。

Catalina 容器处理请求的核心机制是 管道-阀门(Pipeline-Valve)责任链模式

  • Pipeline(管道)
    • 定义:每个容器组件(Engine、Host、Context、Wrapper)都拥有一个唯一的 Pipeline 对象。
    • 作用:它是请求处理的“传送带”。当请求进入某个容器时,就会进入该容器的 Pipeline。
    • 结构:Pipeline 内部维护了一个阀门(Valve)链表和一个特殊的基础阀门(BasicValve)。
  • Valve(阀门)
    • 定义:具体的处理单元,实现了 org.apache.catalina.Valve 接口。
    • 作用:执行具体的业务逻辑或非业务逻辑(如打印日志、检查权限)。
    • 结构分类
      • 普通阀门:可以添加多个,按顺序执行。例如:AccessLogValve(访问日志)、RemoteAddrValve(IP 过滤)、SingleSignOnValve(单点登录)。
      • 基础阀门:每个 Pipeline 只能有一个,且必须位于链表的末尾。它的职责通常是调用下一个层级的容器(例如:Host 的 Basic Valve 负责找到并调用对应的 Context)。4个容器的 BaseValve 分别是 StandardEngineValveStandardHostValveStandardContextValveStandardWrapperValve

Tomcat Catalina容器层级与请求处理流程图

一次完整的 HTTP 请求处理流程

现在,让我们把上述所有组件串联起来,看看当一个用户发起 HTTP 请求(例如 http://localhost:8080/myapp/hello)时,Tomcat 是如何一步步处理的:

  1. 建立连接:客户端与 Tomcat 的 Connector (监听 8080 端口) 建立 TCP 连接。
  2. 解析请求:Connector 读取 HTTP 报文,解析出 URL、Header、Body 等信息,封装成 HttpServletRequest 和 HttpServletResponse 对象。
  3. 映射 Engine:Connector 将请求交给关联的 Service 中的 Engine。
  4. 映射 Host:Engine 根据请求头中的 Host 字段(如 localhost),在其管理的 Host 列表中找到匹配的 Host 组件。如果未找到,使用 defaultHost。
  5. 映射 Context:Host 根据 URL 的路径部分(/myapp),在其管理的 Context 列表中找到对应的 Context(即 Web 应用)。此时,Host 的 Pipeline 中的 Valve 会执行(如访问日志)。
  6. 映射 Wrapper (Servlet):Context 根据剩余的路径(/hello),查阅该应用的 web.xml 或注解配置,找到匹配的 Servlet (Wrapper)。如果找不到,可能由默认的 DefaultServlet 处理(返回 404 或静态资源)。在此过程中,Context 配置的 Filter 链(filterChain)会被执行。
  7. 执行 Servlet:Wrapper 调用目标 Servlet 的 service() 方法( doGet/doPost 等)。业务逻辑执行完毕,数据写入 Response 对象。
  8. 响应返回:响应对象沿原路返回(Wrapper -> Context -> Host -> Engine -> Connector)。Connector 将 Response 对象序列化为 HTTP 响应报文,发送给客户端。
  9. 关闭连接:根据 HTTP 协议版本(Keep-Alive 设置),决定是关闭连接还是保持连接等待下一次请求。

这个流程清晰地展示了 Tomcat 如何通过分层容器和责任链模式,将一个复杂的 HTTP 请求处理分解为多个清晰、可扩展的步骤。掌握这个流程,对于排查问题、性能调优以及深入理解 Java Web 技术栈都至关重要。




上一篇:NVIDIA GPU 性能关键:探秘SM子分区与CUDA优化中的隐性瓶颈
下一篇:边界-约束-收敛理论:在AI时代重构嵌入式工程开发的核心方法
您需要登录后才可以回帖 登录 | 立即注册

手机版|小黑屋|网站地图|云栈社区 ( 苏ICP备2022046150号-2 )

GMT+8, 2026-3-17 10:23 , Processed in 0.522395 second(s), 41 queries , Gzip On.

Powered by Discuz! X3.5

© 2025-2026 云栈社区.

快速回复 返回顶部 返回列表