嵌入式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

image-awfp.png

<!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>

启动,通过浏览器访问

image-tdav.png

添加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相关东西

image-eung.png

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);
    }
}

启动项目并测试

image-pydq.png

image-kpze.png

image-zbzr.png

结尾

源码
今天写了如何在嵌入式tomcat中支持jsp和添加webapp以及如何添加websocket支持,相信经过两天的学习,可以使用嵌入式tomcat完成一些简单的业务了


嵌入式Tomcat学习-第二天
https://blog.lhstack.xyz/archives/tomcat-secondday
作者
lhstack
发布于
2025年02月15日
许可协议