学习tomcat源码、tomcat性能优化或者找debug可能都需要将tomcat跑起来。这里使用idea调试tomcat项目。

获取源码:

git clone https://github.com/apache/tomcat.git

目前main分支(tomcat 11)是一个基于Java 21开发的分支,却用到了java 22才添加的api,这导致我们直接使用main分支会出现比较多的问题。这里我们使用10.1.x分支。

首先我们切换到该分支

git checkout 10.1.x

tomcat(10.1.x分支)这是一个基于Java 17的ant项目,和lombok一样。在idea中需要先安装ant插件方便后续管理这个项目。
你需要将其转换为对应ide的项目(注意你需要在java 17的环境下执行):

ant ide-intellij

这里和lombok一样,由于需要下载一些文件,可能会比较慢。

导入idea后,打开org.apache.catalina.startup.Bootstrap,可以执行里面的main方法启动项目。但是会有一些错误:

严重: 配置应用程序监听器[listeners.ContextListener]错误
严重: 配置应用程序监听器[listeners.SessionListener]错误
严重: 配置应用程序监听器[async.AsyncStockContextListener]错误
严重: 配置应用程序监听器[websocket.drawboard.DrawboardContextListener]错误

此时打开localhost:8080是会报错的:

java.lang.NullPointerException: Cannot invoke "jakarta.servlet.jsp.JspFactory.releasePageContext(jakarta.servlet.jsp.PageContext)" because "org.apache.jsp.index_jsp._jspxFactory" is null

listeners.ContextListener这几个在example项目里面的的listener实现,在它们的xml配置了。在默认情况下tomcat使用当前目录作为home目录,xml等配置文件是正常可用的,但是ContextListener这样的类是java文件还未编译,加载必然是失败的。而默认root目录下的index是jsp,服务还未正确启动,所以500了。

要解决这个问题首先需要构建一个可用的Tomcat工作区,然后将这个工作区设置为tomcat的home目录。
构建工作目录:

ant deploy

启动时设置工作目录

-Dcatalina.home=D:\IdeaProjects\tomcat\output\build
-Dcatalina.base=D:\IdeaProjects\tomcat\output\build

此时功能就正常了,将自己的webapp部署到output\build\webapps目录下就是一个正常的服务了(其实deploy之后的build目录就是我们正常使用的tomcat,现在我们的代码逻辑是我们的tomcat项目,而配置与webapp使用的是build目录下的配置)。

如果需要调试请求过程,那么在此方法上打上断点即可。
org.apache.catalina.connector.CoyoteAdapter#service

标签: none

添加新评论