前阵子帮人做中间件选型,项目组拿出一份“非正式清单”,上面写着:TongWeb 7.0 装一遍、TongWeb 6.0 再装一遍,Spring Boot 2.7 的项目跑不动就降到 2.6,实在不行再问厂商。这种“试了再说”的做法在中小项目里非常普遍,但中间件版本选购一旦靠试,后面就是环境差异、XML 解析异常、Servlet 规范冲突这些坑排队等着你。TongWeb 版本选购看似只挑一个版本号,实际上是在给应用运行时的规范支持、JDK 兼容、嵌入式集成方式、乃至授权成本一次性划线。这篇指南就是围绕“按应用场景选版本”这个核心问题展开的,覆盖传统 WAR 部署、Spring Boot 嵌入式、微服务、信创环境和高可用集群几种典型场景,适合正在做国产中间件选型的架构师、开发、运维和项目负责人参考。
1. TongWeb 版本演进:先摸清 5.0、6.0、7.0 这几代的家底
1.1 5.0:老项目的钉子户
TongWeb 5.0 是很多政企老系统里最常见的版本,基于 Java EE 5 规范,只支持 Servlet 2.5、JSP 2.0 这类比较老的技术栈。它能在这些年还活着,主要不是因为技术好,而是因为太多 2008 到 2015 年间建设的业务系统在它上面跑得稳如老狗,没有人愿意承担迁移成本。
如果你手里的项目是存量系统维护,或者要复刻一套和老环境完全一致的新环境,那 5.0 依然可以纳入备选。但要有心理准备:它只支持 JDK 1.4、5、6 的部署环境,放到现在的主流服务器上会遇到不少问题。2020 年之后的新服务器普遍预装更高版本 JDK,而老版本 TongWeb 在高版本 JDK 上启动时经常抛安全策略异常或 JSP 编译失败。
从选购角度看,5.0 的定位非常明确:只服务存量,不服务新建项目。任何新业务,哪怕是内部小工具,都不要再用 5.0 起新环境了。
1.2 6.0:兼容性宽,但功能开始显老
TongWeb 6.0 是承上启下的一代,对 Java EE 6/7 规范的支持比较完整,能够运行 Servlet 3.0/3.1 的 Web 应用,也支持 EJB、JMS、JPA 这些企业级特性。它的最大好处是 JDK 环境兼容跨度大,从 JDK 6 到 JDK 8 都可以跑,这在信创改造早期帮了不少团队解决了“老 JDK 迁不动”的尴尬。
但 6.0 的问题在国产化替代浪潮中暴露得也最明显:对 Spring Boot 嵌入式部署的支持非常弱,官方资料也少,基本只能走标准部署模式。如果你要带的业务是典型 Spring Boot 单体应用,却被迫在 6.0 上打 WAR 包,那会丢掉很多 Spring Boot 自带的优化,比如内嵌容器自动配置、actuator 健康检查等,运维复杂度会明显上升。
6.0 现在更适合什么场景?我倾向于传统 Servlet/JSP 项目,特别是那些依赖 JSP 自定义标签库、EJB 无状态会话 Bean 的老项目。这类应用在 6.0 上迁移成本最低,踩坑最少。为了安全性,尽量选择 6.0 发布较晚的小版本,因为它早年的某些版本内置的 JDK 策略文件过旧,会导致 HTTPS 双向认证时抛证书路径异常。
1.3 7.0:当前选型的主战场
TongWeb 7.0 是当前官方主推的版本,也是绝大多数新项目选型时的默认答案。它完整支持 Java EE 8 规范,包含 Servlet 4.0、JSP 2.3、Bean Validation 2.0、JPA 2.2、JMS 2.0 等。硬件生态覆盖面也明显扩大,对鲲鹏、飞腾、兆芯、海光这些国产 CPU 都有适配,操作系统层面支持麒麟、统信 UOS、EulerOS 等。
7.0 还有一个非常关键的变化:开始区分标准版和嵌入式版本。标准版负责完整应用服务器功能,嵌入式版本则是为了替换 Spring Boot 默认内置容器而存在的,可以用极小的代价让现有 Spring Cloud 项目在TongWeb上运行。这个变化直接影响了选型方式,后面一节我会单独展开。
我个人的建议是,所有新建项目优先锁定 7.0。但注意“7.0”不是终点,它是一个版本族,下面还有 7.0.0、7.0.1、7.0.9 之类的小版本。选的时候不要只看大版本号,要跟厂商要最新的 release notes,优先挑发布超过半年、修复了明显并发问题的稳定小版本,而不是追最新。
| 对比维度 | TongWeb 5.0 | TongWeb 6.0 | TongWeb 7.0 |
|---|---|---|---|
| 规范基准 | Java EE 5 | Java EE 6/7 | Java EE 8 |
| Servlet版本 | 2.5 | 3.0/3.1 | 4.0 |
| 支持JDK | 1.4 / 5 / 6 | 6 / 7 / 8 | 8 / 11 / 17 |
| 标准部署 | 支持 | 支持 | 支持 |
| 嵌入式Spring Boot | 不支持 | 基本不支持 | 支持,分版本适配 |
| 国产芯片适配 | 有限 | 部分 | 完整 |
| 典型定位 | 存量维护 | 传统Servlet/JSP项目 | 新建项目、微服务、信创 |
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 传统 Web 应用选型:标准部署模式怎么挑版本
2.1 什么时候应该走标准部署
并不是所有项目都需要嵌入式容器。很多系统仍然以传统方式交付:开发打 WAR 包,运维在中间件管理控制台里发布,整个过程和 Tomcat、WebLogic 时代几乎没有区别。如果你的应用满足下面任意一条,我建议优先走标准部署模式,而不是把应用和容器绑在一起:
- 客户运维团队只熟悉 Web 管理控制台,不喜欢搞 DevOps 流水线;
- 系统里有多个 Web 应用需要在一个服务器进程里同时对外提供服务;
- 应用依赖共享数据源、共享 JNDI 资源,或者要求统一配置虚拟主机;
- 需要用到 EJB、JMS 等 Java EE 容器级能力。
这些场景下,选型逻辑很简单:能用 7.0 就用 7.0,涉及老项目迁移且代码里大量用了 JSP、自定义 Tag 库时,可以评估 6.0。但凡是新项目,即使是传统 WAR 交付,我也坚持用 7.0,因为它对高并发线程池、异步 Servlet、HTTP/2 的支持更好,这些在 5.0、6.0 上要么没有,要么实现很不成熟。
2.2 部署与管理工作台:标准版选型要注意这些细节
标准部署模式下,版本选择会直接影响运维体验。TongWeb 7.0 的管理控制台比 6.0 完善不少,应用发布流程更接近现代应用服务器:可以一边发布应用一边保留旧版本,发布失败时可以回滚,这一点对生产环境非常关键。如果你在 6.0 上做过发布,估计碰过“应用包上传到一半,管理台假死”的尴尬,7.0 在这块的健壮性好很多。
端口配置上要注意一个细节:TongWeb 默认 HTTP 端口是 8080,管理控制台端口是 9060,HTTPS 端口是 8443。多个实例部署在同一台物理机时,这些端口都要错开,建议在项目初始化阶段就规定命名规范,比如每个实例独占一段连续端口区间,否则后面维护成本很高。
另外强烈建议在标准部署模式下把 JVM 参数显式配置到启动脚本里。TongWeb 7.0 的启动参数文件是 bin/exstart.sh 或 bin/setEnv.sh,网上很多教程说改 catalina.sh,这在老 Tomcat 习惯下没错,但 TongWeb 有自己独立的参数入口,别按 Tomcat 的路子硬套。堆内存设置一般给到物理内存的 50% 到 60%,如果物理内存只有 8G,建议 -Xms3g -Xmx3g,不要堆内存过高导致系统本身没有余量。元空间 -XX:MaxMetaspaceSize 可以设 512M,JSP 编译频繁的应用适当调到 768M。
2.3 web.xml 报错——一个典型的版本不匹配场景
很多人在 TongWeb 上部署老应用时会遇到一个非常典型的报错:应用启动时抛出 org.xml.sax.SAXParseException,提示 web.xml 中引用了一个未知的 schema location。
这个问题的本质不是 XML 文件写错了,而是web.xml 头部的命名空间版本和 TongWeb 实际支持的 Servlet 规范版本不匹配。举例来说,如果项目里 web.xml 的 web-app 标签带了 http://xmlns.jcp.org/xml/ns/javaee 且版本属性是 4.0,但你部署到的是 TongWeb 6.0(只支持 Servlet 3.1),容器解析 XML 时就会直接抛异常。
排查思路是这样:先看Tomcat/WebLogic上是否正常,如果正常,说明 Java 代码本身没有规范依赖问题,纯粹是 XML schema 版本让 TongWeb 解析器不满意。解决办法很直接,把 web.xml 头部的 version 改为目标版本支持的数值,或者直接删掉命名空间让容器按自身默认规则解析。比如要部署到 TongWeb 6.0,就把:
xml复制<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
改成 version="3.1" 并对应 web-app_3_1.xsd。如果应用本身没有用到 Servlet 4.0 的特性,这个改动完全不会有副作用。不过更省事的做法是:直接选 TongWeb 7.0,因为 7.0 的解析器兼容性更好,对 web.xml 4.0 和 3.1 都能接受。版本选购把这一步做对,后面能省掉非常多的 XML 解析类问题。
3. 嵌入式模式选型:Spring Boot 项目的版本坑
3.1 嵌入式版本和标准版不是同一个选型维度
Spring Boot 项目的中间件选型思路,和传统 WAR 部署完全不同。Spring Boot 默认用的是内嵌容器,比如 Tomcat、Jetty、Undertow,应用以可执行 JAR 的方式启动,根本不经过外部应用服务器。TongWeb 要做嵌入式替换,就必须提供一套完整的 spring-boot-starter 依赖和一个能替代内嵌 Tomcat 的容器实现。
所以选购的时候一定要区分:你买的标准版授权和嵌入式版本授权,可能是两条完全不同的技术线。标准版是完整应用服务器,嵌入式版本从接口上更像 Tomcat 的替代品,只是它具备 TongWeb 的国密、可信、管理功能。因此不要以为“我已经买了 TongWeb 7.0,所以 Spring Boot 项目直接加依赖就能跑”,要明确找厂商要对应的嵌入式集成包或 starter。
3.2 Spring Boot 版本太高的兼容问题
“tongweb, springboot版本太高”这个问题在网络上被搜索得很频繁,它也确实是嵌入式模式里最常见的坑。根本原因在于 Spring Boot 的不同次版本对应的 Servlet API 版本不一样,而 TongWeb 的嵌入式版本是基于某个具体的 Servlet 规范做适配的。
官方兼容矩阵的思路大致是:
| Spring Boot 版本 | 底层Servlet API | 适配的TongWeb嵌入式版本 |
|---|---|---|
| 2.1.x - 2.3.x | Servlet 4.0 (javax.servlet) | 7.0.0 系列 |
| 2.4.x - 2.5.x | Servlet 4.0 (javax.servlet) | 7.0.1 系列 |
| 2.6.x - 2.7.x | Servlet 4.0 (javax.servlet) | 7.0.3 及以上 |
| 3.0.x - 3.2.x | Servlet 6.0 / Jakarta EE 10 | 需单独确认专用适配版本 |
如果项目里 Spring Boot 版本高出嵌入式包支持范围,最常见的现象是:应用能启动,但访问任何接口时抛 NoClassDefFoundError 或 NoSuchMethodError,比如 javax.servlet.ServletRegistration 的某个方法找不到,或者过滤器注册时直接报 ClassCastException。
遇到这个问题,我的经验是先不要急着去找“万能兼容包”,而是明确当前项目技术栈:如果 Spring Boot 2.7 用的是 javax 命名空间,那就优先找 TongWeb 官方提供的对应 Spring Boot 2.7 的集成版本;如果官方只适配到 2.5,那就把 Spring Boot 降级到官方支持范围,而不是强行用一个未经适配的高版本。项目业务代码没有用到新版本特性时,降级成本通常很低。
3.3 Spring Boot 3、Jakarta 命名空间怎么破
Spring Boot 3.0 之后,Servlet API 的包名从 javax.servlet 切换成了 jakarta.servlet。这个切换不是简单换一下 import 就行,它会牵扯到所有过滤器、监听器、拦截器,以及第三方组件中的 javax 引用。TongWeb 7.0 标准版是基于 Java EE 8 规范的,底层用的仍然是 javax.servlet,所以它并不能直接内嵌到 Spring Boot 3 的可执行 JAR 里。
面对 Spring Boot 3 项目,真正稳妥的方案往往不是嵌入式,而是把应用打成 WAR 包,部署到 TongWeb 标准版上,通过 TongWeb 的 Jakarta EE 兼容能力去适配。这里要特别提醒:迁移前必须在 POC 环境里验证标签库、依赖注入、JPA 配置等是否都兼容,不要等到生产割接时才发现 JNDI 数据源名称对不上。
如果你非常迫切需要用嵌入式方式跑 Spring Boot 3,一定要先问厂商要“TongWeb 7.0 对 jakarta.servlet 的适配说明”,不要凭想象直接引入老版本 starter。根据我观察到的实际情况,很多团队为了把 Spring Boot 3 嵌入 TongWeb,花了大量时间改包名和依赖,最终仍然因为某几个 Java EE 接口冲突而放弃,性价比极低。
3.4 微服务场景下的版本关注点
微服务架构里,每个服务独立部署、独立伸缩,中间件版本选择逻辑又会变。如果你采用的是服务网格或注册中心模式,每个 Spring Boot 服务都内嵌容器,那选型重点是:
- 需要统一所有服务的 Spring Boot 版本,因为 TongWeb 嵌入式版本的兼容矩阵是跟着 Spring Boot 走的,不同微服务用不同 Spring Boot 版本,会导致中间件基线的维护成本成倍上升;
- 优先选一个已被多个项目验证过的组合,比如 Spring Boot 2.7.x + TongWeb 7.0 对应嵌入式版本,别在生产环境用“刚刚发布的小版本”;
- 考虑镜像构建的便利性,TongWeb 嵌入式版本应尽可能打进 Docker/OCI 镜像,所以制品的体积、基础镜像的 glibc 兼容性都要提前评估。
我见过不少团队在微服务引入国产中间件时,坚持让每个服务都独立安装一份完整版 TongWeb,这其实是对嵌入式模式的误解。完整版 TongWeb 体积大、启动慢、资源占用高,用它来跑几百个微服务实例,光磁盘和内存成本就会翻几倍。正确的做法是,网关、配置中心这类基础组件统一部署完整版 TongWeb 标准实例,业务微服务全部走嵌入式版本,这样既能保证关键通道的稳定,又能控制整体资源开销。
4. 信创生产与高可用集群:版本对齐比什么都重要
4.1 从 CPU、OS 到 JDK 的版本对齐
信创环境是 TongWeb 的主场,但选版本时最容易栽跟头的反而不是 TongWeb 本身,而是周边基础软件版本对齐。很多项目组拿到授权后,在 x86 服务器上测试通过了,一拿到鲲鹏机器上就发现启动报 Invalid CPU type 或某些 JNI 库加载失败,原因往往是选择的 TongWeb 安装包不匹配目标 CPU 架构。
在信创环境里,TongWeb 7.0 的安装包通常会区分 x86_64 和 aarch64 两种版本,部分发布包还会针对特定国产芯片做编译优化。所以第一步就要向厂商确认:你的服务器是 Intel/AMD 还是鲲鹏/飞腾?操作系统是麒麟 V10 SP1 还是统信 UOS 20?这些信息必须在下单授权前就写清楚,否则后续安装包拿错了,运维只能对着 ./startserver.sh 干瞪眼。
JDK 版本更是一个大坑。信创生态里常见的 JDK 有:阿里 Dragonwell、华为毕昇 JDK、腾讯 Kona JDK,以及各个 Linux 发行版自带的 OpenJDK。TongWeb 7.0 对 JDK 8 和 11 的支持比较成熟,如果你用的是毕昇 JDK 11 跑在鲲鹏 CPU 上,建议先用官方文档确认默认 GC 参数是否合适,必要时显式指定并行 GC 或 G1 分区。不要因为 JDK 是 11 就觉得“一定没问题”,不同厂商的 JDK 在 TLS、证书库、国密算法支持上可能存在细微差异。
4.2 集群、会话保持与负载均衡
高可用场景里,版本选择直接决定了后续的集群运维难度。TongWeb 7.0 提供完整的集群方案,支持单机多实例集群和多机分布式集群,通过集群间的会话复制,让用户在访问故障时自动切换到另一台节点而不丢失登录状态。
选型时要重点确认几个能力:
- 会话复制是分布式缓存缓存模式还是全量广播模式,前者对网络带宽占用更小,后者实现简单但只适合四五台以内的小集群;
- 是否支持粘滞会话,即负载均衡把同一个用户的请求始终转发到同一后端实例,这个能力对无状态化不彻底的老应用特别重要;
- 与管理控制台的集成情况,是否能在控制台上直接查看节点间的心跳、会话同步延迟和节点线程池状态。
如果采购的是老版本 TongWeb 5.0、6.0,集群功能也能用,但配置方式更偏手工,通常需要在 cluster.conf 这类文件里手工填节点列表,且会话复制效率不高。生产环境新建集群,我建议直接选择 7.0,并且把会话失效时长、心跳间隔这些参数写进项目基线文档里,不然每次维护集群都要翻手册。
4.3 资源规划与性能参数
从传统 Tomcat 迁移到 TongWeb 时,很多参数不能照抄。最大的区别在于 HTTP 线程池模型:Tomcat 默认使用 NIO 连接器,而 TongWeb 7.0 在标准模式下也有一些配套的线程配置。部署后建议把核心线程数和最大线程数单独调一次,别用默认值。
一个基础的起步配置可以这样:
bash复制# 在 exstart.sh 或 setEnv.sh 中设置 JVM 参数
JAVA_OPTS="-Xms4096m -Xmx4096m -XX:MaxMetaspaceSize=512m"
# 并行 GC,适合多核机器
JAVA_OPTS="$JAVA_OPTS -XX:+UseParallelGC"
# 必要的调试参数,生产环境可去除
JAVA_OPTS="$JAVA_OPTS -Djava.awt.headless=true"
并发量评估阶段,建议先用 jmeter 做负载测试,重点观察 GC 频率和 Full GC 的停顿时间。如果压测时发现吞吐量上不去,优先检查是不是线程池被业务代码里的同步锁拖住了,而不是急着把线程数调大。堆内存里的每 1000 个并发请求大约需要多少空间,不同业务差别很大,唯一的验证方式是压测,不要凭空拍脑袋。
5. 版本矩阵与避坑清单:选型前过一遍
5.1 一张表看清版本组合
把前文所有讨论汇总成一张场景推荐表,方便选型时直接参考:
| 应用类型 | 推荐版本 | 部署模式 | 核心考量 |
|---|---|---|---|
| 存量 Java EE 5 老系统 | 5.0(仅存量维护)或升级6.0 | 标准WAR部署 | JDK版本能否匹配新环境 |
| 传统 Servlet/JSP 项目 | 6.0 或 7.0 | 标准WAR部署 | JSP编译、JNDI、虚拟主机 |
| Spring Boot 2.1 - 2.5 单体 | 7.0 嵌入式(对应版本) | 可执行JAR | 检查官方适配的Spring Boot区间 |
| Spring Boot 2.6 - 2.7 项目 | 7.0 嵌入式(新小版本) | 可执行JAR | 优先验证Filter和Interceptor |
| Spring Boot 3 项目 | 7.0 标准版 | WAR部署 | Jakarta命名空间适配 |
| 微服务多实例项目 | 7.0 嵌入式 | 容器镜像 | 统一Spring Boot版本基线 |
| 信创 ARM 环境 | 7.0 aarch64 版本 | 标准或嵌入式 | CPU架构、国产JDK对齐 |
| 高可用集群 | 7.0 标准版 | 标准多实例 | 会话复制、粘滞会话、负载均衡 |
这个表不是万能答案,但它能覆盖绝大多数实际选型场景。遇到表里找不到的组合,原则是:以厂商官方兼容矩阵为准,并以 POC 实测结果作为最终决策依据。中间件选型最怕的就是不查文档、不做 POC、靠社区零星博客判断。
5.2 授权、支持与选型流程建议
版权与授权因素在选型中经常被低估。TongWeb 是商业中间件,不同大版本的授权模式差异很大。采购前必须问清楚三个问题:
- 授权是按物理机 CPU 数量计算,还是按容器实例数计算?
- 是否包含长期的技术支持和安全补丁更新?
- 老版本(如 5.0、6.0)是否还有补丁维护?如果没有,即使它功能满足,也不建议新项目使用。
我在实际项目里有一条经验:不要为了省授权费在新建项目里选择 EOL(生命周期终止)版本。中间件是承上启下的基础设施,它一旦出安全问题,影响的不是单个接口,而是所有部署其上的应用。一个“免费但没人维护”的中间件,后续每个安全通告都可能变成加班通知。
选型流程方面,我建议按下面这个顺序走:
- 第一步,梳理应用技术栈:JDK 版本、Spring Boot 版本、是否依赖 Java EE 容器能力、是否用到国密算法;
- 第二步,根据技术栈确定候选版本和部署模式,列出需要验证的风险点;
- 第三步,在开发环境搭建和线上一致的验证环境,把应用、配置、数据源全量跑一遍;
- 第四步,做一轮基础压测,记录吞吐量和GC情况;
- 第五步,再进采购流程,把版本、补丁级别、授权方式写进合同。
这五步看着繁琐,但能把 90% 的选型后悔问题消灭在正式采购前。
回到文首那个朋友的问题,最后我的建议是:新项目直接列 TongWeb 7.0,Spring Boot 项目先确认嵌入式版本支持矩阵;老项目除非有明确的升级计划,否则不要为了“新”而强行换版本。中间件版本选购的本质不是追求最新,而是追求“应用栈与容器栈在规范和兼容性上的最大公约数”,把这一点想透了,版本的判断就不会偏。
