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 为例):
<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 处理请求:
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() {
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 映射:
// 方式一:通过 Tomcat.addServlet() 注册
Tomcat.addServlet(context, "myServlet", new MyServlet());
context.addServletMappingDecoded("/my/*", "myServlet");
// 方式二:直接实例化 Servlet
ServletHolder holder = new ServletHolder(new MyServlet());
context.addServletMappingDecoded("/my/*", holder);
- 设置初始化参数:
context.setInitParameter("appName", "EmbeddedApp");
// 在 Servlet 中通过 getServletContext().getInitParameter("appName") 获取
- 配置会话超时:
context.setSessionTimeout(30); // 30 分钟
部署本地 Web 应用
除了动态注册 Servlet,嵌入式 Tomcat 还支持部署本地已有的 Web 应用(如传统的 WAR 包或目录结构)。
示例:部署本地 Web 应用目录
假设本地有一个标准 Web 应用,目录结构如下:
mywebapp/
├── WEB-INF/
│ ├── web.xml
│ ├── classes/
│ └── lib/
└── index.jsp
部署代码:
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 调整网络参数:
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() {
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.xml、web.xml,通过代码动态配置。 - 轻量级:仅引入必要依赖,减少资源占用。
- 灵活性高:可根据业务需求动态调整服务器参数(如端口、线程池)。
- 易于集成:方便嵌入到其他应用中,作为内置服务器使用。
注意事项
- 依赖冲突:嵌入式 Tomcat 可能与项目中其他 Servlet 容器依赖(如 Jetty)冲突,需排除冗余依赖。
- JSP 支持:若需解析 JSP,需额外引入
tomcat-embed-jasper依赖。 - 资源路径:部署本地 Web 应用时,
docBase需使用绝对路径或正确的相对路径(避免因工作目录变化导致找不到资源)。 - 端口占用:启动前检查端口是否被占用,可通过
setPort(0)让系统自动分配空闲端口。