0%

tomcat嵌入式

Tomcat 嵌入式开发详解

从 Tomcat 7 开始,官方提供了嵌入式支持,允许通过 Java 代码直接创建和启动 Tomcat 服务器,无需手动配置 server.xml 等文件。这种方式广泛应用于开发工具(如 IDEA 内置服务器)、集成测试及轻量级应用部署。本文将详细介绍 Tomcat 嵌入式开发的核心用法和实践案例。

嵌入式 Tomcat 核心组件

嵌入式 Tomcat 的核心类是 org.apache.catalina.startup.Tomcat,它封装了 Tomcat 服务器的创建、配置和启动流程。主要涉及以下组件:

  • Tomcat:服务器入口,负责初始化和启动整个 Tomcat 实例。
  • Context:代表一个 Web 应用上下文,对应传统的 <Context> 配置。
  • Host:虚拟主机,用于管理多个 Context
  • Connector:连接器,配置端口、协议等网络参数。

入门示例:快速启动嵌入式 Tomcat

依赖配置

使用 Maven 引入嵌入式 Tomcat 依赖(以 Tomcat 9 为例):

1
2
3
4
5
6
7
8
9
10
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-core</artifactId>
<version>9.0.80</version>
</dependency>
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-jasper</artifactId> <!-- 支持 JSP 需添加 -->
<version>9.0.80</version>
</dependency>

映射简单 Servlet

通过代码创建并启动 Tomcat,直接映射一个 Servlet 处理请求:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
import org.apache.catalina.LifecycleException;
import org.apache.catalina.startup.Tomcat;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

public class EmbeddedTomcatDemo {
public static void main(String[] args) throws LifecycleException {
// 1. 创建 Tomcat 实例
Tomcat tomcat = new Tomcat();

// 2. 配置端口(默认 8080,可自定义)
tomcat.setPort(8080);

// 3. 创建 Web 应用上下文(contextPath 为 "/test",docBase 设为 null 表示内存中运行)
org.apache.catalina.Context context = tomcat.addContext("/test", null);

// 4. 注册 Servlet
String servletName = "helloServlet";
Tomcat.addServlet(context, servletName, new HttpServlet() {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
resp.getWriter().write("Hello, Embedded Tomcat!");
}
});

// 5. 映射 Servlet 路径(访问 "/test/hello" 触发)
context.addServletMappingDecoded("/hello", servletName);

// 6. 初始化并启动 Tomcat
tomcat.init();
tomcat.start();
System.out.println("Tomcat 启动成功,访问 http://localhost:8080/test/hello");

// 7. 阻塞主线程,保持服务器运行
tomcat.getServer().await();
}
}

运行结果
访问 http://localhost:8080/test/hello,页面显示 Hello, Embedded Tomcat!

核心 API 解析

Tomcat 类核心方法

方法 功能描述
setPort(int port) 设置默认连接器端口(默认 8080)。
addContext(String contextPath, String docBase) 创建 Web 应用上下文,contextPath 为访问路径,docBase 为应用目录(null 表示内存中运行)。
addWebapp(String contextPath, String docBase) 部署本地 Web 应用(支持 WAR 包或目录)。
init() 初始化 Tomcat 服务器(加载配置)。
start() 启动 Tomcat 服务器。
getServer().await() 阻塞当前线程,防止服务器退出。

Context 类核心操作

Context 代表一个 Web 应用,主要用于配置 Servlet、过滤器、初始化参数等:

  • 添加 Servlet 映射
1
2
3
4
5
6
7
// 方式一:通过 Tomcat.addServlet() 注册
Tomcat.addServlet(context, "myServlet", new MyServlet());
context.addServletMappingDecoded("/my/*", "myServlet");

// 方式二:直接实例化 Servlet
ServletHolder holder = new ServletHolder(new MyServlet());
context.addServletMappingDecoded("/my/*", holder);
  • 设置初始化参数
1
2
context.setInitParameter("appName", "EmbeddedApp");
// 在 Servlet 中通过 getServletContext().getInitParameter("appName") 获取
  • 配置会话超时
1
context.setSessionTimeout(30); // 30 分钟

部署本地 Web 应用

除了动态注册 Servlet,嵌入式 Tomcat 还支持部署本地已有的 Web 应用(如传统的 WAR 包或目录结构)。

示例:部署本地 Web 应用目录

假设本地有一个标准 Web 应用,目录结构如下:

1
2
3
4
5
6
mywebapp/
├── WEB-INF/
│ ├── web.xml
│ ├── classes/
│ └── lib/
└── index.jsp

部署代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class DeployWebappDemo {
public static void main(String[] args) throws LifecycleException, ServletException {
Tomcat tomcat = new Tomcat();
tomcat.setPort(8080);

// 部署本地 Web 应用(contextPath 为 "/app",docBase 为应用目录路径)
String webappDir = "path/to/mywebapp"; // 本地 Web 应用目录
tomcat.addWebapp("/app", webappDir);

tomcat.init();
tomcat.start();
System.out.println("Web 应用部署成功,访问 http://localhost:8080/app");
tomcat.getServer().await();
}
}

说明

  • addWebapp 方法会自动解析 WEB-INF/web.xml 中的配置(Servlet、过滤器等)。
  • 支持直接部署 WAR 包(docBase 设为 WAR 文件路径即可)。

自定义连接器配置

默认情况下,嵌入式 Tomcat 使用 8080 端口和 HTTP/1.1 协议。可通过自定义 Connector 调整网络参数:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
public class CustomConnectorDemo {
public static void main(String[] args) throws LifecycleException {
Tomcat tomcat = new Tomcat();

// 自定义连接器(端口 8081,使用 NIO 协议)
org.apache.catalina.connector.Connector connector = new org.apache.catalina.connector.Connector(
"org.apache.coyote.http11.Http11NioProtocol"
);
connector.setPort(8081);
connector.setRedirectPort(8443); // HTTPS 重定向端口
tomcat.setConnector(connector);

// 添加一个简单的 Servlet
org.apache.catalina.Context context = tomcat.addContext("/", null);
Tomcat.addServlet(context, "hello", new HttpServlet() {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws IOException {
resp.getWriter().write("Custom Connector: 8081");
}
});
context.addServletMappingDecoded("/*", "hello");

tomcat.init();
tomcat.start();
System.out.println("访问 http://localhost:8081");
tomcat.getServer().await();
}
}

实践场景与优势

1. 典型应用场景

  • 开发工具集成:IDE(如 IntelliJ IDEA、Eclipse)内置嵌入式 Tomcat,简化开发调试。
  • 自动化测试:在单元测试中启动嵌入式 Tomcat,模拟真实环境测试 Web 接口。
  • 轻量级部署:无需安装 Tomcat,直接通过 JAR 包启动应用(如 Spring Boot 内嵌 Tomcat)。
  • 微服务场景:每个服务独立启动嵌入式 Tomcat,避免端口冲突和配置繁琐。

2. 优势

  • 零配置:无需手动编写 server.xmlweb.xml,通过代码动态配置。
  • 轻量级:仅引入必要依赖,减少资源占用。
  • 灵活性高:可根据业务需求动态调整服务器参数(如端口、线程池)。
  • 易于集成:方便嵌入到其他应用中,作为内置服务器使用。

注意事项

  1. 依赖冲突:嵌入式 Tomcat 可能与项目中其他 Servlet 容器依赖(如 Jetty)冲突,需排除冗余依赖。
  2. JSP 支持:若需解析 JSP,需额外引入 tomcat-embed-jasper 依赖。
  3. 资源路径:部署本地 Web 应用时,docBase 需使用绝对路径或正确的相对路径(避免因工作目录变化导致找不到资源)。
  4. 端口占用:启动前检查端口是否被占用,可通过 setPort(0) 让系统自动分配空闲端口。

欢迎关注我的其它发布渠道

表情 | 预览
快来做第一个评论的人吧~
Powered By Valine
v1.3.10