tomcat源码学习记录

tomcat 学习记录

  • tomcat 编译
    • ant 下载
    • 编译
    • 运行
  • 源码Debug
    • 运行 Bootstrap
    • 运行Tomcat
    • 查看状态
  • pom.xml
  • 测试
    • EmbeddedTomcat
  • 参考
    • 书籍
    • 博客

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 包

参考

  • Tomcat 源码阅读与调试环境搭建 - 基于Idea和Tomcat 8.5

ant 下载

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

编译

  • 根路径下 build.properties.default,将其复制为 build.properties
  • 打开ant侧边栏,点击“+”,选择tomcat下的build.xml文件
  • 由于 windows默认编码集为GBK,由于使用startup.bat启动tomcat时,它会读取catalina.bat的代码并打开一个新窗口运行。打开的cmd默认编码可能不是utf-8,与系统编码不一致,所以导致乱码
    • 通过修改注册表
    • 修改 conf/logging.properties 日志编码为GBK
  • 在项目结构设置里,添加 JDK,同时设置 java 目录为源代码目录

点击 ant 窗口的运行按钮

运行

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

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

tomcat源码学习记录_第1张图片

源码Debug

导入 ant 依赖
在这里插入图片描述
导入 ${user.home}/tomcat-build-libs 下的依赖
tomcat源码学习记录_第2张图片

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

tomcat源码学习记录_第3张图片

运行 Bootstrap

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

tomcat源码学习记录_第4张图片

运行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"/>

tomcat源码学习记录_第5张图片

pom.xml




<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.0modelVersion>
  <groupId>org.apache.tomcatgroupId>
  <artifactId>apache-tomcat-10.1.16-srcartifactId>
  <name>Tomcatname>
  <version>10.1.16version>
  <build>
    
    <finalName>apache-tomcat-10.1.16-srcfinalName>
    <sourceDirectory>javasourceDirectory>
    <resources>
      <resource>
        <directory>javadirectory>
      resource>
    resources>
    <plugins>
      
      <plugin>
        <groupId>org.apache.maven.pluginsgroupId>
        <artifactId>maven-compiler-pluginartifactId>
        <version>3.1version>
        <configuration>
          <encoding>UTF-8encoding>
          <source>11source>
          <target>11target>
        configuration>
      plugin>
    plugins>
  build>
  
  <dependencies>
    <dependency>
      <groupId>geronimo-specgroupId>
      <artifactId>geronimo-spec-jaxrpcartifactId>
      <version>1.1-rc4version>
    dependency>

    <dependency>
      <groupId>wsdl4jgroupId>
      <artifactId>wsdl4jartifactId>
      <version>1.6.3version>
    dependency>

    <dependency>
      <groupId>junitgroupId>
      <artifactId>junitartifactId>
      <version>4.13.2version>
      <scope>testscope>
    dependency>

    <dependency>
      <groupId>org.hamcrestgroupId>
      <artifactId>hamcrestartifactId>
      <version>2.2version>
      <scope>testscope>
    dependency>

    <dependency>
      <groupId>org.easymockgroupId>
      <artifactId>easymockartifactId>
      <version>4.3version>
    dependency>

    <dependency>
      <groupId>cglibgroupId>
      <artifactId>cglibartifactId>
      <version>3.3.0version>
    dependency>

    <dependency>
      <groupId>org.objenesisgroupId>
      <artifactId>objenesisartifactId>
      <version>3.3version>
    dependency>

     <dependency>
      <groupId>com.unboundidgroupId>
      <artifactId>unboundid-ldapsdkartifactId>
      <version>6.0.10version>
    dependency>

    <dependency>
      <groupId>com.puppycrawl.toolsgroupId>
      <artifactId>checkstyleartifactId>
      <version>10.12.4version>
    dependency>

    <dependency>
      <groupId>org.jacocogroupId>
      <artifactId>org.jacoco.agentartifactId>
      <version>0.8.11version>
    dependency>

    <dependency>
      <groupId>com.github.spotbugsgroupId>
      <artifactId>spotbugsartifactId>
      <version>4.8.0version>
      <type>pomtype>
    dependency>

    <dependency>
      <groupId>biz.aQute.bndgroupId>
      <artifactId>biz.aQute.bndlibartifactId>
      <version>7.0.0version>
    dependency>

    <dependency>
      <groupId>org.apache.tomcatgroupId>
      <artifactId>jakartaee-migrationartifactId>
      <version>1.0.7version>
    dependency>

    <dependency>
      <groupId>net.jsigngroupId>
      <artifactId>jsign-coreartifactId>
      <version>5.0version>
    dependency>

    <dependency>
      <groupId>org.apache.derbygroupId>
      <artifactId>derbyartifactId>
      <version>10.16.1.1version>
      <scope>testscope>
    dependency>

    <dependency>
      <groupId>antgroupId>
      <artifactId>antartifactId>
      <version>1.7.0version>
    dependency>


    <dependency>
      <groupId>org.eclipse.jdtgroupId>
      <artifactId>ecjartifactId>
      <version>3.36.0version>
    dependency>

    <dependency>
      <groupId>org.apache.tomcatgroupId>
      <artifactId>tomcat-juliartifactId>
      <version>11.0.0-M14version>
    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()+ "]");
        }
    }
}

参考

  • Apache Tomcat

书籍

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

博客

  • Tomcat源码详解知识体系详解
  • tomcat源码分析
  • Tomcat 分析

你可能感兴趣的:(java,web,tomcat,学习,java)