tomcat源码学习记录

2023-12-13 04:12:33

tomcat 编译

下载 tomcat 10 源码,解压然后idea导入
包存放的默认位置如下:base.path=${user.home}/tomcat-build-libs
同时在项目的 tomcat/res/ide-support/idea/tomcat.iml 文件中提供了jar的依赖配置方式, 可以覆盖 .idea 配置,但对于 社区版有些插件是无法安装的,就从 ${user.home}/tomcat-build-libs 手动导入 jar 包

参考

ant 下载

ant 二进制包下载 后添加环境变量 %ANT_HOME%\bin,idea2023 会自动识别, 或者打开 help-> action 搜索 ant

编译

点击 ant 窗口的运行按钮

运行

在输出目录下的 build/bin 运行 startup.bat

在浏览器 http://localhost:8080/

在这里插入图片描述

源码Debug

导入 ant 依赖
在这里插入图片描述
导入 ${user.home}/tomcat-build-libs 下的依赖
在这里插入图片描述

针对 java lang ClassNotFoundException listeners ContextListener 错误,是由于在idea的maven项目中要将java文件编译,加载进内存需要将文件夹设置为Sources Root

在这里插入图片描述

运行 Bootstrap

java/org/apache/catalina/startup/Bootstrap.java 中,自己调试运行

在这里插入图片描述

运行Tomcat

代码路径 java/org/apache/catalina/startup/Tomcat.java

public static void main(String[] args) throws Exception {
    // Process some command line parameters
    String[] catalinaArguments = null;
    for (int i = 0; i < args.length; i++) {
        if (args[i].equals("--no-jmx")) {
            Registry.disableRegistry();
        } else if (args[i].equals("--catalina")) {
            // This was already processed before
            // Skip the rest of the arguments as they are for Catalina
            ArrayList<String> result = new ArrayList<>();
            for (int j = i + 1; j < args.length; j++) {
                result.add(args[j]);
            }
            catalinaArguments = result.toArray(new String[0]);
            break;
        }
    }
    SecurityClassLoad.securityClassLoad(Thread.currentThread().getContextClassLoader());
    Tomcat tomcat = new Tomcat();
    // Create a Catalina instance and let it parse the configuration files
    // It will also set a shutdown hook to stop the Server when needed
    // Use the default configuration source
    tomcat.init(null, catalinaArguments);
    boolean await = false;
    String path = "";
    // Process command line parameters
    for (int i = 0; i < args.length; i++) {
        if (args[i].equals("--war")) {
            if (++i >= args.length) {
                throw new IllegalArgumentException(sm.getString("tomcat.invalidCommandLine", args[i - 1]));
            }
            File war = new File(args[i]);
            tomcat.addWebapp(path, war.getAbsolutePath());
        } else if (args[i].equals("--path")) {
            if (++i >= args.length) {
                throw new IllegalArgumentException(sm.getString("tomcat.invalidCommandLine", args[i - 1]));
            }
            path = args[i];
        } else if (args[i].equals("--await")) {
            await = true;
        } else if (args[i].equals("--no-jmx")) {
            // This was already processed before
        } else if (args[i].equals("--catalina")) {
            // This was already processed before
            // Skip the rest of the arguments as they are for Catalina
            break;
        } else {
            throw new IllegalArgumentException(sm.getString("tomcat.invalidCommandLine", args[i]));
        }
    }
    tomcat.start();
    // Ideally the utility threads are non daemon
    if (await) {
        tomcat.getServer().await();
    }
}

查看状态

conf/tomcat-users.xml 添加用户

 <user username="admin" password="admin" roles="manager-gui,admin-gui,tomcat"/>

在这里插入图片描述

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<!--
  ~ Licensed to the Apache Software Foundation (ASF) under one or more
  ~ contributor license agreements.  See the NOTICE file distributed with
  ~ this work for additional information regarding copyright ownership.
  ~ The ASF licenses this file to You under the Apache License, Version 2.0
  ~ (the "License"); you may not use this file except in compliance with
  ~ the License.  You may obtain a copy of the License at
  ~
  ~      http://www.apache.org/licenses/LICENSE-2.0
  ~
  ~ Unless required by applicable law or agreed to in writing, software
  ~ distributed under the License is distributed on an "AS IS" BASIS,
  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  ~ See the License for the specific language governing permissions and
  ~ limitations under the License.
  -->

<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
			http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>org.apache.tomcat</groupId>
  <artifactId>apache-tomcat-10.1.16-src</artifactId>
  <name>Tomcat</name>
  <version>10.1.16</version>
  <build>
    <!--指定源目录-->
    <finalName>apache-tomcat-10.1.16-src</finalName>
    <sourceDirectory>java</sourceDirectory>
    <resources>
      <resource>
        <directory>java</directory>
      </resource>
    </resources>
    <plugins>
      <!--引入编译插件-->
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-compiler-plugin</artifactId>
        <version>3.1</version>
        <configuration>
          <encoding>UTF-8</encoding>
          <source>11</source>
          <target>11</target>
        </configuration>
      </plugin>
    </plugins>
  </build>
  <!--tomcat 依赖的基础包-->
  <dependencies>
    <dependency>
      <groupId>geronimo-spec</groupId>
      <artifactId>geronimo-spec-jaxrpc</artifactId>
      <version>1.1-rc4</version>
    </dependency>

    <dependency>
      <groupId>wsdl4j</groupId>
      <artifactId>wsdl4j</artifactId>
      <version>1.6.3</version>
    </dependency>

    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.13.2</version>
      <scope>test</scope>
    </dependency>

    <dependency>
      <groupId>org.hamcrest</groupId>
      <artifactId>hamcrest</artifactId>
      <version>2.2</version>
      <scope>test</scope>
    </dependency>

    <dependency>
      <groupId>org.easymock</groupId>
      <artifactId>easymock</artifactId>
      <version>4.3</version>
    </dependency>

    <dependency>
      <groupId>cglib</groupId>
      <artifactId>cglib</artifactId>
      <version>3.3.0</version>
    </dependency>

    <dependency>
      <groupId>org.objenesis</groupId>
      <artifactId>objenesis</artifactId>
      <version>3.3</version>
    </dependency>

     <dependency>
      <groupId>com.unboundid</groupId>
      <artifactId>unboundid-ldapsdk</artifactId>
      <version>6.0.10</version>
    </dependency>

    <dependency>
      <groupId>com.puppycrawl.tools</groupId>
      <artifactId>checkstyle</artifactId>
      <version>10.12.4</version>
    </dependency>

    <dependency>
      <groupId>org.jacoco</groupId>
      <artifactId>org.jacoco.agent</artifactId>
      <version>0.8.11</version>
    </dependency>

    <dependency>
      <groupId>com.github.spotbugs</groupId>
      <artifactId>spotbugs</artifactId>
      <version>4.8.0</version>
      <type>pom</type>
    </dependency>

    <dependency>
      <groupId>biz.aQute.bnd</groupId>
      <artifactId>biz.aQute.bndlib</artifactId>
      <version>7.0.0</version>
    </dependency>

    <dependency>
      <groupId>org.apache.tomcat</groupId>
      <artifactId>jakartaee-migration</artifactId>
      <version>1.0.7</version>
    </dependency>

    <dependency>
      <groupId>net.jsign</groupId>
      <artifactId>jsign-core</artifactId>
      <version>5.0</version>
    </dependency>

    <dependency>
      <groupId>org.apache.derby</groupId>
      <artifactId>derby</artifactId>
      <version>10.16.1.1</version>
      <scope>test</scope>
    </dependency>

    <dependency>
      <groupId>ant</groupId>
      <artifactId>ant</artifactId>
      <version>1.7.0</version>
    </dependency>


    <dependency>
      <groupId>org.eclipse.jdt</groupId>
      <artifactId>ecj</artifactId>
      <version>3.36.0</version>
    </dependency>

    <dependency>
      <groupId>org.apache.tomcat</groupId>
      <artifactId>tomcat-juli</artifactId>
      <version>11.0.0-M14</version>
    </dependency>

  </dependencies>
</project>

测试

EmbeddedTomcat

public class EmbeddedTomcat {

    private static void resetLogging() {
        final String loggingConfig = "handlers = java.util.logging.ConsoleHandler\n" +
            ".handlers = java.util.logging.ConsoleHandler\n" +
            "java.util.logging.ConsoleHandler.level = FINE\n" +
            "java.util.logging.ConsoleHandler.formatter = org.apache.juli.OneLineFormatter\n" +
            "java.util.logging.ConsoleHandler.encoding = UTF-8\n";
        try {
            InputStream is = new ByteArrayInputStream(loggingConfig.getBytes(StandardCharsets.UTF_8));
            LogManager.getLogManager().readConfiguration(is);
            LogFactory.getLog(EmbeddedTomcat.class).info("Logger configured to System.out");
        } catch (SecurityException | IOException e) {
            // Ignore, the VM default will be used
        }
    }

    public static void main(String... args) throws Exception {
        Registry.disableRegistry();
        Tomcat tomcat = new Tomcat();
        resetLogging();
        tomcat.setPort(8080);
        Connector connector = tomcat.getConnector();
        connector.setProperty("bindOnInit", "false");
        // No file system docBase required
        Context ctx = tomcat.addContext("", null);
        skipTldsForResourceJars(ctx);
        CounterServlet counterServlet = new CounterServlet();
        Tomcat.addServlet(ctx, "counterServlet", counterServlet);
        ctx.addServletMappingDecoded("/", "counterServlet");
        //ctx.addApplicationListener(new WsContextListener());

        tomcat.start();
        Thread.sleep(60*1000);
    }

    public static void skipTldsForResourceJars(Context context) {
        StandardJarScanner scanner = (StandardJarScanner) context.getJarScanner();
        StandardJarScanFilter filter = (StandardJarScanFilter) scanner.getJarScanFilter();
        filter.setTldSkip(filter.getTldSkip() + ",resources*.jar");
    }

    private static class CounterServlet extends HttpServlet {

        private static final long serialVersionUID = 1L;

        private AtomicInteger callCount = new AtomicInteger(0);

        @Override
        protected void service(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {
            req.getSession(true);
            resp.setContentType("text/plain");
            resp.getWriter().print("OK: " + req.getRequestURL() + "[" + callCount.incrementAndGet()+ "]");
        }
    }
}

参考

书籍

  • 深入剖析 Tomcat
  • Tomcat 架构解析

博客

文章来源:https://blog.csdn.net/qq_41146650/article/details/134874057
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。