zoukankan      html  css  js  c++  java
  • 调试tomcat9.0.19源码

    本文所用到的环境:

    • IntelliJ IDEA
    • Apache Maven 3.3.9
    • jdk1.8

    1. 查看Tomcat版本

    $TOMCAT_HOMEinversion.bat

    D:Program_Filesapache-tomcat-9.0.19in>version.bat
    Using CATALINA_BASE:   "D:Program_Filesapache-tomcat-9.0.19"
    Using CATALINA_HOME:   "D:Program_Filesapache-tomcat-9.0.19"
    Using CATALINA_TMPDIR: "D:Program_Filesapache-tomcat-9.0.19	emp"
    Using JRE_HOME:        "D:Program FilesJavajdk1.8.0_77"
    Using CLASSPATH:       "D:Program_Filesapache-tomcat-9.0.19inootstrap.jar;D:Program_Filesapache-tomcat-9.0.19in	omcat-juli.jar"
    Server version: Apache Tomcat/9.0.19
    Server built:   Apr 12 2019 14:22:48 UTC
    Server number:  9.0.19.0
    OS Name:        Windows 10
    OS Version:     10.0
    Architecture:   amd64
    JVM Version:    1.8.0_77-b03
    JVM Vendor:     Oracle Corporation
    D:Program_Filesapache-tomcat-9.0.19in>
    

    这里使用的是JDK1.8,如果不是JDK1.8,则需要查看tomcat的兼容,选择适合自己的版本

    2. 下载源码

    根据自己的Tomcat版本,下载对应的源码

    选择对应版本的tomcat,这里我使用的tomcat9,选择Archives

    下载完成后解压,apache-tomcat-9.0.19-src

    3. 创建项目结构

    • 在D盘创建“D: omcat9.0.19”文件夹,然后将解压后的文件拷贝到该目录中,同时创建“catalina-home”目录

    • 拷贝“apache-tomcat-9.0.19-srcconf”,到“catalina-home”目录下

    • 创建“D: omcat9.0.19pom.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/maven-v4_0_0.xsd">
       
          <modelVersion>4.0.0</modelVersion>
          <groupId>org.apache.tomcat</groupId>
          <artifactId>Tomcat9.0.19</artifactId>
          <name>Tomcat 9.0 Study</name>
          <version>1.0</version>
          <packaging>pom</packaging>
       
          <modules>
              <module>apache-tomcat-9.0.19-src</module>
          </modules>
      </project>
      
    • 创建“D: omcat9.0.19apache-tomcat-9.0.19-srcpom.xml”文件

      <?xml version="1.0" encoding="UTF-8"?>
      <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>Tomcat9.0</artifactId>
          <name>Tomcat9</name>
          <version>9.0</version>
      
          <build>
              <finalName>Tomcat9</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>2.3</version>
                      <configuration>
                          <encoding>UTF-8</encoding>
                          <source>1.8</source>
                          <target>1.8</target>
                      </configuration>
                  </plugin>
              </plugins>
          </build>
      
          <dependencies>
              <dependency>
                  <groupId>org.apache.ant</groupId>
                  <artifactId>ant</artifactId>
                  <version>1.9.5</version>
              </dependency>
              <dependency>
                  <groupId>org.apache.ant</groupId>
                  <artifactId>ant-apache-log4j</artifactId>
                  <version>1.9.5</version>
              </dependency>
              <dependency>
                  <groupId>org.apache.ant</groupId>
                  <artifactId>ant-commons-logging</artifactId>
                  <version>1.9.5</version>
              </dependency>
              <dependency>
                  <groupId>javax.xml.rpc</groupId>
                  <artifactId>javax.xml.rpc-api</artifactId>
                  <version>1.1</version>
              </dependency>
              <dependency>
                  <groupId>wsdl4j</groupId>
                  <artifactId>wsdl4j</artifactId>
                  <version>1.6.2</version>
              </dependency>
              <dependency>
                  <groupId>org.eclipse.jdt.core.compiler</groupId>
                  <artifactId>ecj</artifactId>
                  <version>4.4</version>
              </dependency>
          </dependencies>
      </project>
      

    最终的目录结构为:

    Administrator@git MINGW64 /d/tomcat9.0.19
    $ ls -l                                                                                                                 total 6
    drwxr-xr-x 1 Administrator 197121   0 3月  30 17:50 apache-tomcat-9.0.19-src
    drwxr-xr-x 1 Administrator 197121   0 3月  30 17:41 catalina-home
    -rw-r--r-- 1 Administrator 197121 533 3月  30 17:27 pom.xml
    
    Administrator@git MINGW64 /d/tomcat9.0.19
    $ ls -l catalina-home/                                                                                                  total 8
    drwxr-xr-x 1 Administrator 197121 0 3月  30 17:38 conf
    

    4. 将该项目导入到IDEA中

    5. 编译

    由于这里使用是JDK1.8,所以需要注释掉这些代码,否则容易报错:

    编译:

    6. 运行

    1)创建Application

    vm option 配置:

    -Dfile.encoding=UTF-8 -Dcatalina.home=catalina-home -Dcatalina.base=catalina-home -Djava.endorsed.dirs=catalina-home/endorsed -Djava.io.tmpdir=catalina-home/temp -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -Djava.util.logging.config.file=catalina-home/conf/logging.properties
    

    在Bootstrap的main方法当中加入测试代码:

     System.out.println("======================Tomcat Study======================");
    

    下面是部分启动日志:

    ======================Tomcat Study======================
    30-Mar-2020 17:38:32.009 警告 [main] org.apache.catalina.startup.ClassLoaderFactory.validateFile Problem with directory [D:	omcat9.0.19catalina-homelib], exists: [false], isDirectory: [false], canRead: [false]
    30-Mar-2020 17:38:32.017 警告 [main] org.apache.catalina.startup.ClassLoaderFactory.validateFile Problem with directory [D:	omcat9.0.19catalina-homelib], exists: [false], isDirectory: [false], canRead: [false]
    30-Mar-2020 17:38:32.017 警告 [main] org.apache.catalina.startup.ClassLoaderFactory.validateFile Problem with directory [D:	omcat9.0.19catalina-homelib], exists: [false], isDirectory: [false], canRead: [false]
    30-Mar-2020 17:38:32.017 警告 [main] org.apache.catalina.startup.ClassLoaderFactory.validateFile Problem with directory [D:	omcat9.0.19catalina-homelib], exists: [false], isDirectory: [false], canRead: [false]
    
    

    但是启动日志会有乱码,解决方法:

    为何会有乱码:
    原因:一般是中文编码不匹配导致;经跟踪,发现是ResourceBundle读取orgapachecatalinastartupLocalStrings_zh_CN.properties文件时没有用utf8解码导致;
    解决:修改org.apache.tomcat.util.res.StringManager类中的getString函数;

    if (bundle != null) {
    str = bundle.getString(key);
    }
    

    改为

    if (bundle != null) {
    str = new String(bundle.getString(key).getBytes(“ISO-8859-1”), “UTF-8”);
    }
    

    再次运行,一切正常

    引用链接:http://www.itgather.com/archives/54

    2)实验

    1. 在“catalina-homewebapps”目录中创建“demoindex.html”文件:
    <html>
    <head><title>Tomcat9.0.19_Test</title></head>
    <body>
        
      <h1>Hello World!!!</h1> 
      
    </body>
    </html>
    
     访问: http://127.0.0.1:8080/demo/ 
    
    1. 在“catalina-homewebapps”目录中创建“demoindex.jsp”文件:
    <%@ page contentType="text/html;charset=utf-8" pageEncoding="utf-8"%>
    <html>
    <head><title>Test-title</title></head>
    <body>
    <%
        request.setCharacterEncoding("utf-8");
        String method = request.getMethod() ;   // 取得提交方式
        String ip = request.getRemoteAddr() ;   // 取得客户端的IP地址
        String path = request.getServletPath() ;    // 取得访问路径
        String contextPath1= request.getContextPath() ; // 取得上下文资源名称
        String contextPath2 = getServletContext().getContextPath() ;// 取得上下文资源名称
        String realPath=getServletContext().getRealPath("/");//取得虚拟目录所对应的真实路径
    %>
    <h3>请求方式:<%=method%></h3>
    <h3>IP地址:<%=ip%></h3>
    <h3>访问路径:<%=path%></h3>
    <h3>上下文名称1:<%=contextPath1%></h3>
    <h3>上下文名称2:<%=contextPath2%></h3>
    <h3>真实路径:<%=realPath%></h3>
    </body>
    </html>
    

    访问: http://127.0.0.1:8080/demo/index.jsp

    调试程序

    index.jsp在被编译后会生成“index_jsp.java”和“index_jsp.class”文件,位置如下:

    Administrator@git MINGW64 /d/tomcat9.0.19/catalina-home/work/Catalina/localhost/demo/org/apache/jsp
    $ pwd
    /d/tomcat9.0.19/catalina-home/work/Catalina/localhost/demo/org/apache/jsp
    
    Administrator@git MINGW64 /d/tomcat9.0.19/catalina-home/work/Catalina/localhost/demo/org/apache/jsp
    $ ls index_jsp.java
    index_jsp.java
    
    Administrator@git MINGW64 /d/tomcat9.0.19/catalina-home/work/Catalina/localhost/demo/org/apache/jsp
    $ ls index_jsp.class
    index_jsp.class
    
    

    下面是“index_jsp.java”文件的内容:

    /*
     * Generated by the Jasper component of Apache Tomcat
     * Version: Apache Tomcat/9.0.x-dev
     * Generated at: 2020-03-30 10:23:23 UTC
     * Note: The last modified time of this file was set to
     *       the last modified time of the source file after
     *       generation to assist with modification tracking.
     */
    package org.apache.jsp;
    
    import javax.servlet.*;
    import javax.servlet.http.*;
    import javax.servlet.jsp.*;
    
    public final class index_jsp extends org.apache.jasper.runtime.HttpJspBase
        implements org.apache.jasper.runtime.JspSourceDependent,
                     org.apache.jasper.runtime.JspSourceImports {
    
      private static final javax.servlet.jsp.JspFactory _jspxFactory =
              javax.servlet.jsp.JspFactory.getDefaultFactory();
    
      private static java.util.Map<java.lang.String,java.lang.Long> _jspx_dependants;
    
      private static final java.util.Set<java.lang.String> _jspx_imports_packages;
    
      private static final java.util.Set<java.lang.String> _jspx_imports_classes;
    
      static {
        _jspx_imports_packages = new java.util.HashSet<>();
        _jspx_imports_packages.add("javax.servlet");
        _jspx_imports_packages.add("javax.servlet.http");
        _jspx_imports_packages.add("javax.servlet.jsp");
        _jspx_imports_classes = null;
      }
    
      private volatile javax.el.ExpressionFactory _el_expressionfactory;
      private volatile org.apache.tomcat.InstanceManager _jsp_instancemanager;
    
      public java.util.Map<java.lang.String,java.lang.Long> getDependants() {
        return _jspx_dependants;
      }
    
      public java.util.Set<java.lang.String> getPackageImports() {
        return _jspx_imports_packages;
      }
    
      public java.util.Set<java.lang.String> getClassImports() {
        return _jspx_imports_classes;
      }
    
      public javax.el.ExpressionFactory _jsp_getExpressionFactory() {
        if (_el_expressionfactory == null) {
          synchronized (this) {
            if (_el_expressionfactory == null) {
              _el_expressionfactory = _jspxFactory.getJspApplicationContext(getServletConfig().getServletContext()).getExpressionFactory();
            }
          }
        }
        return _el_expressionfactory;
      }
    
      public org.apache.tomcat.InstanceManager _jsp_getInstanceManager() {
        if (_jsp_instancemanager == null) {
          synchronized (this) {
            if (_jsp_instancemanager == null) {
              _jsp_instancemanager = org.apache.jasper.runtime.InstanceManagerFactory.getInstanceManager(getServletConfig());
            }
          }
        }
        return _jsp_instancemanager;
      }
    
      public void _jspInit() {
      }
    
      public void _jspDestroy() {
      }
    
      public void _jspService(final javax.servlet.http.HttpServletRequest request, final javax.servlet.http.HttpServletResponse response)
          throws java.io.IOException, javax.servlet.ServletException {
    
        if (!javax.servlet.DispatcherType.ERROR.equals(request.getDispatcherType())) {
          final java.lang.String _jspx_method = request.getMethod();
          if ("OPTIONS".equals(_jspx_method)) {
            response.setHeader("Allow","GET, HEAD, POST, OPTIONS");
            return;
          }
          if (!"GET".equals(_jspx_method) && !"POST".equals(_jspx_method) && !"HEAD".equals(_jspx_method)) {
            response.setHeader("Allow","GET, HEAD, POST, OPTIONS");
            response.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED, "JSP 只允许 GET、POST 或 HEAD。Jasper 还允许 OPTIONS");
            return;
          }
        }
    
        final javax.servlet.jsp.PageContext pageContext;
        javax.servlet.http.HttpSession session = null;
        final javax.servlet.ServletContext application;
        final javax.servlet.ServletConfig config;
        javax.servlet.jsp.JspWriter out = null;
        final java.lang.Object page = this;
        javax.servlet.jsp.JspWriter _jspx_out = null;
        javax.servlet.jsp.PageContext _jspx_page_context = null;
    
    
        try {
          response.setContentType("text/html;charset=utf-8");
          pageContext = _jspxFactory.getPageContext(this, request, response,
          			null, true, 8192, true);
          _jspx_page_context = pageContext;
          application = pageContext.getServletContext();
          config = pageContext.getServletConfig();
          session = pageContext.getSession();
          out = pageContext.getOut();
          _jspx_out = out;
    
          out.write("
    ");
          out.write("<html>
    ");
          out.write("<head><title>Test-title</title></head>
    ");
          out.write("<body>
    ");
    
        request.setCharacterEncoding("utf-8");
        String method = request.getMethod() ;   // 取得提交方式
        String ip = request.getRemoteAddr() ;   // 取得客户端的IP地址
        String path = request.getServletPath() ;    // 取得访问路径
        String contextPath1= request.getContextPath() ; // 取得上下文资源名称
        String contextPath2 = getServletContext().getContextPath() ;// 取得上下文资源名称
        String realPath=getServletContext().getRealPath("/");//取得虚拟目录所对应的真实路径
    
          out.write("
    ");
          out.write("<h3>请求方式:");
          out.print(method);
          out.write("</h3>
    ");
          out.write("<h3>IP地址:");
          out.print(ip);
          out.write("</h3>
    ");
          out.write("<h3>访问路径:");
          out.print(path);
          out.write("</h3>
    ");
          out.write("<h3>上下文名称1:");
          out.print(contextPath1);
          out.write("</h3>
    ");
          out.write("<h3>上下文名称2:");
          out.print(contextPath2);
          out.write("</h3>
    ");
          out.write("<h3>真实路径:");
          out.print(realPath);
          out.write("</h3>
    ");
          out.write("</body>
    ");
          out.write("</html>");
        } catch (java.lang.Throwable t) {
          if (!(t instanceof javax.servlet.jsp.SkipPageException)){
            out = _jspx_out;
            if (out != null && out.getBufferSize() != 0)
              try {
                if (response.isCommitted()) {
                  out.flush();
                } else {
                  out.clearBuffer();
                }
              } catch (java.io.IOException e) {}
            if (_jspx_page_context != null) _jspx_page_context.handlePageException(t);
            else throw new ServletException(t);
          }
        } finally {
          _jspxFactory.releasePageContext(_jspx_page_context);
        }
      }
    }
    
    

    这些是JSP的内置对象,另外还有request和response内置对象,在方法参数上

        final javax.servlet.jsp.PageContext pageContext;
        javax.servlet.http.HttpSession session = null;
        final javax.servlet.ServletContext application;
        final javax.servlet.ServletConfig config;
        javax.servlet.jsp.JspWriter out = null;
        final java.lang.Object page = this;
        javax.servlet.jsp.JspWriter _jspx_out = null;
        javax.servlet.jsp.PageContext _jspx_page_context = null;
    

    下面是它们的赋值操作:

          pageContext = _jspxFactory.getPageContext(this, request, response,
          			null, true, 8192, true);
          _jspx_page_context = pageContext;
          application = pageContext.getServletContext();
          config = pageContext.getServletConfig();
          session = pageContext.getSession();
          out = pageContext.getOut();
          _jspx_out = out;
    

    能够看到它们都是通过pageContext的对应方法来进行赋值的。

    实际上我们也可以在界面上将这些内置对象打印出来:

    test.jsp

    <%@ page contentType="text/html" pageEncoding="GBK"%>
    <%@ page import="java.util.*"%>	<!-- 导入java.util包 -->
    <html>
    <head><title>PageScope</title></head>
        <body>
                <h4>request:<%=request%></h4>
                <h4>session:<%=session%></h4>
                <h4>application:<%=application%></h4>
                <h4>response:<%=response%></h4>
                <h4>out:<%=out%></h4>
                <h4>config:<%=config%></h4>
                <h4>page:<%=page%></h4>
    
                <h4>pageContext:<%=pageContext%></h4>
                <h4>getException:<%=pageContext.getException()%></h4>
                <h4>getPage:<%=(pageContext.getPage()==page)%></h4>
                <h4>getRequest:<%=(pageContext.getRequest()==request)%></h4>
                <h4>getResponse:<%=(pageContext.getResponse()==response)%></h4>
                <h4>getSession:<%=(pageContext.getSession()==session)%></h4>
                <h4>getServletConfig:<%=(pageContext.getServletConfig()==config) %></h4>
                <h4>getServletContext:<%=(pageContext.getServletContext()==application)%></h4>
        </body>
    </html>
    

    运行结果:

    再回到调试的问题上来,想要调试“index_jsp.java”,需要创建“org/apache/jsp”文件夹,然后将该文件移动到该文件夹下,打上断点就可以开始调试了:

    3)注意

    默认情况下解析JSP会报错

    1. 现象:
    Type Exception Report
    
    Message java.lang.NullPointerException
    
    Description The server encountered an unexpected condition that prevented it from fulfilling the request.
    
    Exception
    
    org.apache.jasper.JasperException: java.lang.NullPointerException
    	org.apache.jasper.servlet.JspServletWrapper.handleJspException(JspServletWrapper.java:638)
    	org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:514)
    	org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:385)
    	org.apache.jasper.servlet.JspServlet.service(JspServlet.java:329)
    	javax.servlet.http.HttpServlet.service(HttpServlet.java:741)
    Root Cause
    
    java.lang.NullPointerException
    	org.apache.jsp.index_jsp._jspService(index_jsp.java:165)
    	org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:70)
    	javax.servlet.http.HttpServlet.service(HttpServlet.java:741)
    	org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:476)
    	org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:385)
    	org.apache.jasper.servlet.JspServlet.service(JspServlet.java:329)
    	javax.servlet.http.HttpServlet.service(HttpServlet.java:741)
    Note The full stack trace of the root cause is available in the server logs.
    
    1. 问题分析和解决方法

      原因是我们直接启动org.apache.catalina.startup.Bootstrap的时候没有加载org.apache.jasper.servlet.JasperInitializer,从而无法编译JSP。解决办法是在tomcat的源码org.apache.catalina.startup.ContextConfig中手动将JSP解析器初始化:
      ————————————————
      版权声明:本文为CSDN博主「yehong1225」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
      原文链接:https://blog.csdn.net/yekong1225/article/details/81000446

    2. 再次测试正常

    4)切换到Tomcat主目录,将VM options修改为如下配置即可

    -Dcatalina.home=apache-tomcat-9.0.19-src -Dcatalina.base=apache-tomcat-9.0.19-src
    -Djava.endorsed.dirs=apache-tomcat-9.0.19-src/endorsed -Djava.io.tmpdir=apache-tomcat-9.0.19-src/temp
    -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager
    -Djava.util.logging.config.file=apache-tomcat-9.0.19-src/conf/logging.properties
    

    参考链接:

  • 相关阅读:
    ASP.NET Core 从入门到精通-资源收集导航
    【5分钟系列】计算机系统结构的定义
    C#反射与特性(九):全网最全-解析反射
    C#反射与特性(七):自定义特性以及应用
    C#反射与特性(六):设计一个仿ASP.NETCore依赖注入Web
    C#反射与特性(五):类型成员操作
    C#反射与特性(四):实例化类型
    C#反射与特性(三):反射类型的成员
    C#反射与特性(二):探究反射
    安卓TabLayout+ViewPager实现切页
  • 原文地址:https://www.cnblogs.com/cosmos-wong/p/12608165.html
Copyright © 2011-2022 走看看