嵌入式Tomcat学习-第二天
写在前面
什么是嵌入式 Tomcat?
嵌入式 Tomcat 是将 Apache Tomcat 服务器作为库文件集成到 Java 应用程序中的技术方案。它允许开发者通过编程方式直接启动、配置和管理 Tomcat,无需依赖独立安装的 Tomcat 服务器,适用于构建轻量级、自包含的 Web 应用或微服务。
版本特性(11.0.3)
- Servlet/JSP 规范支持
支持 Servlet 6.0 和 JSP 4.0 规范(基于 Jakarta EE 10 平台)。 - 轻量级嵌入
通过tomcat-embed-core
等依赖包实现核心功能集成,无需完整 Tomcat 安装。 - Java 版本要求
最低要求 Java 17 及以上版本。 - 性能优化
改进的 HTTP/2 支持、连接器性能调优及内存管理优化。
核心优势
- 简化部署
应用与服务器一体化,直接打包为可执行 JAR 文件,适合云原生场景。 - 灵活配置
通过代码动态配置端口、上下文路径、SSL 等参数,无需server.xml
文件。 - 开发便捷
与 Spring Boot、Micronaut 等框架无缝集成,快速构建独立 Web 服务。 - 资源占用低
仅加载必要的组件,启动速度快,适合资源受限环境。
典型应用场景
- 微服务架构中的独立服务节点
- 快速原型开发或测试环境
- 命令行工具集成 Web 接口
- 需要定制化 Web 容器行为的场景
添加jsp支持
修改pom.xml,新增jsp依赖
<?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.lhstack.tomcat</groupId>
<artifactId>tomcat-demo</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<maven.compiler.source>21</maven.compiler.source>
<maven.compiler.target>21</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<!-- https://mvnrepository.com/artifact/org.apache.tomcat.embed/tomcat-embed-core -->
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-core</artifactId>
<version>11.0.3</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.tomcat.embed/tomcat-embed-jasper -->
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-jasper</artifactId>
<version>11.0.3</version>
</dependency>
</dependencies>
<repositories>
<repository>
<id>aliyun</id>
<name>阿里云</name>
<url>https://maven.aliyun.com/repository/public</url>
</repository>
</repositories>
</project>
修改代码,添加创建webapp
package com.lhstack.tomcat;
import jakarta.servlet.*;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.apache.catalina.Context;
import org.apache.catalina.Wrapper;
import org.apache.catalina.connector.Connector;
import org.apache.catalina.startup.Tomcat;
import org.apache.tomcat.util.descriptor.web.FilterDef;
import org.apache.tomcat.util.descriptor.web.FilterMap;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
public class TomcatApplication {
public static void main(String[] args) throws Throwable {
Tomcat tomcat = new Tomcat();
//2025-02-15新增 新增webapp,指定路径
Context context = tomcat.addWebapp("", System.getProperty("user.dir") + "/webapp");
//添加Servlet
Wrapper wrapper = Tomcat.addServlet(context, "main", new HttpServlet() {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setHeader("Content-Type", "text/plain;charset=UTF-8");
resp.getWriter().println("hello world");
}
});
wrapper.setAsyncSupported(true);
//2025-02-15新增 修改为test,避免和webapp默认的index.jsp出现冲突
wrapper.addMapping("/test");
FilterDef characterEncodingFilterDef = new FilterDef();
characterEncodingFilterDef.setAsyncSupported("true");
characterEncodingFilterDef.setFilterName("CharacterEncodingFilter");
characterEncodingFilterDef.setFilter(new GenericFilter() {
@Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
req.setCharacterEncoding(StandardCharsets.UTF_8);
res.setCharacterEncoding(StandardCharsets.UTF_8);
chain.doFilter(req,res);
}
});
context.addFilterDef(characterEncodingFilterDef);
FilterMap characterEncodingFilterMap = new FilterMap();
characterEncodingFilterMap.addURLPattern("/*");
characterEncodingFilterMap.setFilterName("CharacterEncodingFilter");
context.addFilterMap(characterEncodingFilterMap);
Connector connector = tomcat.getConnector();
connector.setPort(8080);
tomcat.start();
tomcat.getServer().await();
}
}
创建webapp目录,在webapp目录下面新增index.jsp
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
${pageContext.request.requestURI}
</body>
</html>
启动,通过浏览器访问
添加websocket支持
pom文件新增websocket依赖
<?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.lhstack.tomcat</groupId>
<artifactId>tomcat-demo</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<maven.compiler.source>21</maven.compiler.source>
<maven.compiler.target>21</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<!-- https://mvnrepository.com/artifact/org.apache.tomcat.embed/tomcat-embed-core -->
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-core</artifactId>
<version>11.0.3</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.tomcat.embed/tomcat-embed-jasper -->
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-jasper</artifactId>
<version>11.0.3</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.tomcat.embed/tomcat-embed-websocket -->
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-websocket</artifactId>
<version>11.0.3</version>
</dependency>
</dependencies>
<repositories>
<repository>
<id>aliyun</id>
<name>阿里云</name>
<url>https://maven.aliyun.com/repository/public</url>
</repository>
</repositories>
</project>
代码中增加websocket相关东西
package com.lhstack.tomcat;
import jakarta.servlet.*;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.apache.catalina.Context;
import org.apache.catalina.Wrapper;
import org.apache.catalina.connector.Connector;
import org.apache.catalina.startup.Tomcat;
import org.apache.tomcat.util.descriptor.web.FilterDef;
import org.apache.tomcat.util.descriptor.web.FilterMap;
import org.apache.tomcat.websocket.server.WsSci;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.Collections;
public class TomcatApplication {
public static void main(String[] args) throws Throwable {
Tomcat tomcat = new Tomcat();
//2025-02-15新增 新增webapp,指定路径
Context context = tomcat.addWebapp("", System.getProperty("user.dir") + "/webapp");
//2025-02-15 添加websocket支持和websocket连接监听器
context.addServletContainerInitializer(new WsSci(), Collections.singleton(WebSocketListener.class));
//添加Servlet
Wrapper wrapper = Tomcat.addServlet(context, "main", new HttpServlet() {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setHeader("Content-Type", "text/plain;charset=UTF-8");
resp.getWriter().println("hello world");
}
});
wrapper.setAsyncSupported(true);
//2025-02-15新增 修改为test,避免和webapp默认的index.jsp出现冲突
wrapper.addMapping("/test");
FilterDef characterEncodingFilterDef = new FilterDef();
characterEncodingFilterDef.setAsyncSupported("true");
characterEncodingFilterDef.setFilterName("CharacterEncodingFilter");
characterEncodingFilterDef.setFilter(new GenericFilter() {
@Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
req.setCharacterEncoding(StandardCharsets.UTF_8);
res.setCharacterEncoding(StandardCharsets.UTF_8);
chain.doFilter(req,res);
}
});
context.addFilterDef(characterEncodingFilterDef);
FilterMap characterEncodingFilterMap = new FilterMap();
characterEncodingFilterMap.addURLPattern("/*");
characterEncodingFilterMap.setFilterName("CharacterEncodingFilter");
context.addFilterMap(characterEncodingFilterMap);
Connector connector = tomcat.getConnector();
connector.setPort(8080);
tomcat.start();
tomcat.getServer().await();
}
}
WebSocketListener
package com.lhstack.tomcat;
import jakarta.websocket.*;
import jakarta.websocket.server.ServerEndpoint;
@ServerEndpoint(value = "/ws")
public class WebSocketListener {
@OnOpen
public void onOpen(Session session){
System.out.println("客户端上线: " + session.getId());
}
@OnClose
public void onClose(Session session){
System.out.println("客户端下线: " + session.getId());
}
@OnError
public void onError(Session session,Throwable e){
System.out.println("连接异常: " + session.getId() + ",error: " + e.getMessage());
}
@OnMessage
public void onMessage(String msg,Session session){
System.out.println("收到客户端: " + session.getId() + ",发送的消息: " + msg);
}
}
启动项目并测试
结尾
源码
今天写了如何在嵌入式tomcat中支持jsp和添加webapp以及如何添加websocket支持,相信经过两天的学习,可以使用嵌入式tomcat完成一些简单的业务了
嵌入式Tomcat学习-第二天
https://blog.lhstack.xyz/archives/tomcat-secondday