使用嵌入式 Tomcat 创建Java Web应用程序

使用嵌入式 Tomcat 创建Java Web应用程序

可以直接去Github仓库中拉取项目

前提

  • JDK:1.8
  • Tomcat:9.0.82

教程

第一步:引入 Maven 依赖

我们需要在 pom.xml 中引入核心运行库、JSP 解析支持,以及日志桥接工具。日志对于观察 Lifecycle 状态切换和 Connector 的接收流程至关重要。

注意:你可能会观察到对于javax.servlet我们定义的是provided,这是因为Web应用中的lib目录下

不应该出现Servlet API或者Tomcat自身的JAR,这些JAR由我们内嵌的Tomcat负责提供。所以在
Maven构建应用时,对Servlet API的依赖应该指定为<scope>provided</scope>

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>com.puyu.study</groupId>
    <artifactId>devcenter-embedded-tomcat</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <tomcat.version>9.0.82</tomcat.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.apache.tomcat.embed</groupId>
            <artifactId>tomcat-embed-core</artifactId>
            <version>${tomcat.version}</version>
        </dependency>

        <dependency>
            <groupId>org.apache.tomcat.embed</groupId>
            <artifactId>tomcat-embed-jasper</artifactId>
            <version>${tomcat.version}</version>
        </dependency>

        <dependency>
            <groupId>org.apache.tomcat.embed</groupId>
            <artifactId>tomcat-embed-el</artifactId>
            <version>${tomcat.version}</version>
        </dependency>

        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>4.0.1</version>
            <scope>provided</scope>
        </dependency>

        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>1.7.36</version>
        </dependency>
        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-classic</artifactId>
            <version>1.2.11</version>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>jul-to-slf4j</artifactId>
            <version>1.7.36</version>
        </dependency>

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

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.8.1</version>
            </plugin>
        </plugins>
    </build>
</project>

第二步:编写启动类

2.1:创建目录结构
text 复制代码
devcenter-embedded-tomcat
├── src
│   ├── main
│   │   ├── java          # 放置你的 Java 代码
│   │   ├── resources     # 放置 logback.xml
│   │   └── webapp        # 放置 index.html (作为 Web 根目录)
│   └── test
└── pom.xml
2.2:编写启动类 Main

在src/main/java下创建com.perry.tomcat包

在该包下创建 TomcatLauncher.java 类:

java 复制代码
package com.perry.tomcat;

import org.apache.catalina.Context;
import org.apache.catalina.LifecycleException;
import org.apache.catalina.startup.Tomcat;
import org.slf4j.bridge.SLF4JBridgeHandler;

import java.io.File;

public class TomcatLauncher {
    static {
        // 关键:将 Tomcat 原生的 JUL 日志桥接到 SLF4J,这样你才能看到 DEBUG 日志
        java.util.logging.LogManager.getLogManager().reset();
        SLF4JBridgeHandler.install();
    }
    public static void main(String[] args) throws LifecycleException {
        // 1. 实例化 Tomcat
        Tomcat tomcat = new Tomcat();

        // 2. 设置基础配置
        tomcat.setPort(8080);
        tomcat.getConnector(); // 触发 Connector 的创建

        // 3. 设置 Web 应用上下文
        // 参数1: contextPath (浏览器访问路径)
        // 参数2: docBase (webapp 文件夹的物理路径)
        String webappPath = new File("src/main/webapp").getAbsolutePath();
        Context context = tomcat.addWebapp("", webappPath);

        // 4. 启动 Tomcat
        System.out.println(">>> 准备触发 Lifecycle.init() 和 start()...");
        tomcat.start();

        System.out.println(">>> Tomcat 已启动,监听端口: 8080");

        // 5. 阻塞主线程,保持服务器运行
        tomcat.getServer().await();
    }
}
2.3:配置日志

在 src/main/resources 下创建 logback.xml。这样你就能在控制台看到 Lifecycle 状态切换的详细过程:

xml 复制代码
<configuration>
    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
        </encoder>
    </appender>

    <logger name="org.apache.catalina" level="DEBUG" />
    <logger name="org.apache.coyote" level="DEBUG" />
    <logger name="org.apache.tomcat" level="DEBUG" />

    <root level="INFO">
        <appender-ref ref="STDOUT" />
    </root>
</configuration>

第三步:如何 Debug 源码

请按以下步骤操作:

  1. 找到核心类:在 IDEA 中双击 Shift,搜索并打开 org.apache.catalina.util.LifecycleBase。
  2. 设置断点:在 init() 方法打上断点。
  3. 启动调试:在 TomcatLauncher 类上右键,选择 Debug 'TomcatLauncher.main()'。
相关推荐
BlockChain88812 小时前
SpringBoot实战一:10分钟搭建企业级用户管理系统(20000字完整项目)
java·spring boot·后端
消失的旧时光-194312 小时前
第六课 · 6.1 从 JDBC 到 MyBatis:SQL 工程化是如何发生的?
java·sql·mybatis
Jaxson Lin12 小时前
Java编程进阶:线程基础与实现方式全解析
java·开发语言
夜喵YM12 小时前
基于 Spire.XLS.Free for Java 实现无水印 Excel 转 PDF
java·pdf·excel
茶本无香12 小时前
设计模式之五—门面模式:简化复杂系统的统一接口
java·设计模式
她说可以呀12 小时前
网络基础初识
java·网络·java-ee
没有bug.的程序员12 小时前
Java锁优化:从synchronized到CAS的演进与实战选择
java·开发语言·多线程·并发·cas·synchronized·
麦兜*12 小时前
SpringBoot Profile多环境配置详解,一套配置应对所有场景
java·数据库·spring boot
MetaverseMan12 小时前
rpc节点: synchronized (this) + 双检锁,在 race condition 的情况下分析
java·区块链
笃行客从不躺平12 小时前
Seata + AT 模式 复习记录
java·分布式