尧图网络科技YAOTU DIGITAL 获取报价
获取报价
首页 / 资讯中心 / 文章详情

Spring Boot 3中Jakarta依赖安装配置与javax迁移实战

发布时间:2026/9/29 17:01:30

资讯中心
01
ARTICLE

Spring Boot 3中Jakarta依赖安装配置与javax迁移实战

Spring Boot 3中Jakarta依赖安装配置与javax迁移实战
看到这个标题我第一反应是愣了下“Spring Boot的jak安装配置”是个什么玩法后来结合上下文才反应过来——大概率说的是Jakarta更具体一点是 Spring Boot 3.x 时代里以jakarta.*开头的那批官方依赖包。这个“jak”简称在不少技术社区里就是这么叫的叫久了大家也都懂是指哪一套东西。如果你最近在折腾 Spring Boot 3.x或者正在把一个 Spring Boot 2.x 老项目往上迁移十有八九会被javax改成jakarta这件事恶心过。这篇文章就把我实际踩坑、翻源码、翻依赖关系后整理出来的“Jakarta 依赖安装与配置”完整经验分享出来。不讲空话直接上实操重点关注为什么会有这档子事、哪些地方必须改、哪些坑最容易踩。1. 为什么Spring Boot会扯上Jakartajavax与jakarta的前世今生想搞懂“jak安装配置”到底在配什么先得弄清楚javax和jakarta这两兄弟的关系。这不是简单的改名游戏背后牵扯到整个 Java 企业级开发生态的一次大地震。1.1 一次改名引发的连锁反应很多同学写 Java 写了好几年其实根本没分清 Java SE 和 Java EE。简单说Java SE 是标准版就是你们学的集合、多线程、IO 这些基础。Java EE 是企业版是在标准版之上又加了一堆服务端规范比如 Servlet、JSP、EJB、JMS、Validation以前这些规范类的包名统一都是以javax.*开头。为什么叫javax因为当年 Sun 公司Java 的亲爹注册了javax这个命名空间作为 Java EE 扩展包的前缀。后来 Oracle 收购了 SunJava EE 也跟着到了 Oracle 手里。2017 年Oracle 把 Java EE 捐给了 Eclipse 基金会但“Java”这个商标还在 Oracle 手里Eclipse 基金会不能用“Java EE”这个名字继续命名于是改名叫做Jakarta EE。这就麻烦了包名和商标深度绑定。javax.servlet、javax.validation这些包名里有“Java”的含义Oracle 不可能把商标授权给 Eclipse 基金会永久使用。于是从 Jakarta EE 9 开始所有javax.*的规范包全部改名为jakarta.*比如javax.servlet变成了jakarta.servletjavax.validation变成了jakarta.validationjavax.annotation变成了jakarta.annotation。你可能会问为什么不直接保留javax呢这就是大厂之间的商标权博弈咱们做开发的改变不了只能跟着适配。1.2 为什么Spring Boot 3是分水岭Spring Boot 2.x 时期底层依赖的是 Spring Framework 5.x对应的还是 Java EE 8 规范所以用的依然是javax.*包。到了 Spring Boot 3.x底层升级到了 Spring Framework 6.x对应的是Jakarta EE 9/10规范于是 Spring Boot 官方把所有代码里的javax.*引用全部切换成了jakarta.*。所以判断一个 Spring Boot 项目是哪个“时代”不用看什么文档直接看版本号Spring Boot 版本底层框架使用的 Servlet API包名前缀2.4.xSpring Framework 5.3.xjavax.servlet 4.xjavax.*2.7.x最后的javax时代Spring Framework 5.3.xjavax.servlet 4.xjavax.*3.0.xSpring Framework 6.0.xjakarta.servlet 5.0jakarta.*3.1.x/3.2.x/3.3.x/3.4.xSpring Framework 6.xjakarta.servlet 6.0jakarta.*网上很多老项目升级到 Spring Boot 3.x 后编译报错天天被javax困扰本质就是代码里引用的是旧规范包名而新框架已经不认了。1.3 一个工程里两套包名并存的混乱景象现实中我还真见过一个项目里同时出现javax和jakarta的奇葩情况。比如一个 Spring Boot 2.x 项目代码里用了javax.servlet.Filter写过滤器然后又通过第三方 Maven 依赖引入了某个只支持 Jakarta 的组件结果编译都过不去。最典型的是 2020 年前后那批用 Gradle 构建的 Spring Boot 项目。当时 Spring Boot 插件版本比较老依赖管理用的是javax系列。如果你现在把build.gradle里的 Spring Boot 版本升到 3.x但代码和第三方依赖没跟上就会出现“一半 javax、一半 jakarta、哪里都不对”的混乱场面。这也是“jak安装配置”这类搜索词在社区里突然火起来的主要原因。2. 环境准备与依赖安装把Jakarta依赖正确装进项目搞清楚背景后下面进入实操环节。所谓“安装”对于 Java 项目来说不是像安装软件那样双击下一步而是在构建工具里正确引入和管理依赖。Maven 和 Gradle 是两条主流路线我都说下。2.1 先确认自己的Spring Boot版本再动手别一上来就到处找“jakarta依赖”先把项目的 Spring Boot 版本确认好否则你装的依赖和框架根本不匹配。怎么确认Maven 项目看pom.xml里的parent节点parent groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-parent/artifactId version3.3.5/version relativePath/ /parent如果这里的 version 是3.x那你就是在 Jakarta 时代所有代码里的javax相关引用必须改掉。Gradle 项目看build.gradle里的插件声明plugins { id org.springframework.boot version 3.3.5 id io.spring.dependency-management version 1.1.6 }如果你的项目是 2.x 老版本不建议直接一步跳到 3.x我后面会说推荐路径。注意Spring Boot 2.7.x 是 2.x 系列的最后一个版本也是 javax 到 jakarta 的过渡版。如果你实在没法快速升级至少先升到 2.7.x 把无关问题清理干净再做 3.x 的迁移。2.2 Maven工程添加Jakarta依赖的实操步骤如果你的项目已经在 Spring Boot 3.x 下基本的核心依赖其实不用你手动加Spring Boot 的 starter 已经帮你管理好了。比如spring-boot-starter-web在 3.x 版本里会自动引入jakarta.servlet-api、jakarta.annotation-api等。真正需要手动添加的主要是那些 Spring Boot 没有默认管理、但你又用得上的 Jakarta 规范接口。比如你要写参数校验Validation需要加dependency groupIdjakarta.validation/groupId artifactIdjakarta.validation-api/artifactId version3.0.2/version /dependency注意Spring Boot 3.x 的依赖管理 BOMBill of Materials材料清单里已经管理了jakarta.validation-api的版本所以上面可以不写version让 Spring Boot 自动决定dependency groupIdjakarta.validation/groupId artifactIdjakarta.validation-api/artifactId /dependency如果你只是写纯 Servlet 相关的过滤器、监听器不需要引入完整的 starter可以单独加jakarta.servlet-api但要注意 scope 要设成provided因为这个包在 Tomcat/Jetty 等 Servlet 容器里已经自带了打进业务 JAR 反而容易出问题dependency groupIdjakarta.servlet/groupId artifactIdjakarta.servlet-api/artifactId scopeprovided/scope /dependency2.3 Gradle工程添加Jakarta依赖的方式Gradle 项目的操作逻辑和 Maven 一样的只是语法变成 Groovy/Kotlin DSL。你的build.gradle里可以这样声明dependencies { implementation org.springframework.boot:spring-boot-starter-web implementation jakarta.validation:jakarta.validation-api compileOnly jakarta.servlet:jakarta.servlet-api }如果你是 2020 年前后那批“老 Gradle 项目”有个特殊情况当时的build.gradle里可能没有用io.spring.dependency-management插件而是手工管理了一堆版本号。这种项目升级到 Spring Boot 3.x 后强烈建议先把依赖管理切到 Spring Boot BOM否则jakarta.*的版本就没人帮你统一管了特别容易版本冲突。Kotlin DSL 的写法也顺便贴一下dependencies { implementation(org.springframework.boot:spring-boot-starter-web) implementation(jakarta.validation:jakarta.validation-api) compileOnly(jakarta.servlet:jakarta.servlet-api) }这里有个实战小技巧加完依赖后在项目根目录执行./gradlew dependencies --configuration runtimeClasspath能看到当前运行时完整的依赖树。要是发现jakarta相关包缺了或者出现多个冲突版本一眼就能看出来。3. 核心配置实操从javax到jakarta的完整改造依赖装好了接下来是最费劲但也是最核心的一步把项目里的javax相关代码全部改成jakarta。这一步如果纯手工改大型项目会改到崩溃但有方法可循。3.1 代码里最该改的三个地方import、注解、接口第一大硬伤是 import 语句。你的项目里凡是出现import javax.*开头的绝大部分要替换成import jakarta.*。常见替换对照表如下旧包javax新包jakarta典型用途javax.servlet.*jakarta.servlet.*Servlet、过滤器、请求响应javax.servlet.http.*jakarta.servlet.http.*HttpServletRequest、Cookiejavax.validation.*jakarta.validation.*Bean ValidationValid、NotNulljavax.annotation.*jakarta.annotation.*PostConstruct、Resource等javax.persistence.*jakarta.persistence.*JPA实体注解如果是Spring Data JPAjavax.transaction.*jakarta.transaction.*Transactional在部分场景下的导入javax.el.*jakarta.el.*EL表达式JSP时涉及实际动手替换的时候有三类最容易漏掉第一注解里的隐含依赖。比如PostConstruct很多人在jakarta.annotation.PostConstruct和javax.annotation.PostConstruct之间搞混。Spring Boot 2.x 用的是javax3.x 必须用jakarta。如果你同时引入了一些老组件IDE 自动导入时可能给你导成javax版运行时直接NoClassDefFoundError。第二方法签名里的 Servlet 类型。比如自定义过滤器时doFilter(ServletRequest request, ServletResponse response, FilterChain chain)这段签名里的ServletRequest和ServletResponse接口也必须从jakarta.servlet导入。这个我见过太多人改了 import但方法参数类型是直接用 IDEA 全名导的结果还是javax.servlet。第三字符串常量里硬编码的类名。比如有些老代码用反射Class.forName(javax.servlet.http.HttpServletRequest)加载类或者配置文件里写死了javax.*的类路径这些不会因为你改了 import 就自动变必须手动全局搜索替换。3.2 拦截器、过滤器与监听器最容易踩坑的位置Web 三大组件过滤器、拦截器、监听器是改造重灾区。我拿过滤器举例改造前后对比非常清晰。改造前Spring Boot 2.xjavax 时代import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; public class XssFilter implements Filter { Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) { // 处理逻辑 chain.doFilter(request, response); } }改造后Spring Boot 3.xjakarta 时代import jakarta.servlet.Filter; import jakarta.servlet.FilterChain; import jakarta.servlet.ServletRequest; import jakarta.servlet.ServletResponse; public class XssFilter implements Filter { Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) { // 处理逻辑 chain.doFilter(request, response); } }代码逻辑一个字都不用动但类名变了你的 import 就得全换。这就是包名迁移的“暴力美学”——改的东西不深但到处都是。我实际维护过的一个项目还同时处理了“全局过滤器处理上传 PDF 文件时的 XSS 攻击”这种需求。当时的情况是上传的 PDF 文件名里可能被注入恶意脚本全局过滤器要在文件流进入业务层之前做拦截检查。这个场景里过滤器要检查MultipartFile而MultipartFile的父接口ServletRequest同样从javax切到了jakarta所以升级时只要你把整条链上的引用都换成jakarta功能上完全不用动逻辑照样跑。再说拦截器。HandlerInterceptor本身是 Spring 的接口包名在 Spring Framework 6 里也从javax.servlet底层切到了jakarta.servlet。你自定义拦截器时preHandle方法长这样import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; public class AuthInterceptor implements HandlerInterceptor { Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) { // 鉴权逻辑 return true; } }监听器也类似ServletContextListener、HttpSessionListener这些接口全部在jakarta.servlet下。3.3 配置文件与第三方组件的联动调整代码改完之后很多同学以为就结束了结果一启动又报错。因为你可能还有配置文件没动。第一个问题application.yml 里的配置项Spring Boot 2.x 里常见的一个配置server: servlet: context-path: /api这个配置项在 3.x 里依然是有效的server.servlet.*前缀没变不需要改。但要注意server.servlet.*里有几个子项在 3.x 中被移到了server.tomcat.*下面比如server.servlet.session.timeout变成了server.servlet.session.timeout这个没变别慌。真正变的是 Tomcat 相关的线程池配置从server.tomcat.threads.max变成了server.tomcat.threads.max这个也没变。说实话Spring Boot 3 在配置兼容性上做得不错大多数配置项不用动但如果你用了第三方组件就不一定了。第二个问题第三方组件老版本不认 Jakarta比如老项目里整合 ActiveMQ用的依赖是dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-activemq/artifactId /dependency这个 starter 本身在 3.x 里有对应版本没问题。但你如果还在用很老的 ActiveMQ 5.x 客户端它内部可能会引用javax.jms.*的包而 Spring Boot 3 里默认 JMS API 已经变成jakarta.jms。这时候不升级 ActiveMQ 客户端版本运行时就报NoClassDefFoundError: javax/jms/ConnectionFactory。所以升级后的核心思路是第三方库优先选官方兼容 Jakarta 的版本。JMS 就升到 ActiveMQ 5.18数据库驱动用新版 MySQL Connector/J 8.0.33Redis 客户端用 Lettuce它早就兼容了这个思路比你在代码里去适配老库要省事得多。第三个问题自定义 starter 或公共模块如果你公司内部有公共 starter那个依赖里如果还写着javax.annotation-api、javax.validation-api这类坐标你要么重新发布一个 Jakarta 兼容版本要么在项目中用exclude排除掉旧的javax坐标否则 Maven 会把两套依赖同时带进 classpath那场景又将回到我说过的“两套包名并存”的混乱状态。4. 常见报错与排查技巧实录这块是我最想认真写的部分。网络上一堆教程讲完“怎么替换”就不管了但真实项目中你会发现替换完之后还有一大波花式报错等着你。下面这些是我实际操作中踩过、也帮别人查过的问题。4.1 报错一ClassNotFoundException 或 NoClassDefFoundErrorjavax.* 相关这个报错出现的场景非常典型你改完代码、启动项目控制台一大堆java.lang.ClassNotFoundException: javax.servlet.Filter。排查思路三步走第一步先确认 Spring Boot 版本和代码里的 import 是否匹配。如果版本是 3.x代码里还有javax这个报错必然出现。第二步检查是不是有第三方依赖里嵌了旧的javax.*类。可以执行依赖树分析mvn dependency:tree -Dincludesjavax.*如果看到一堆javax.servlet-api、javax.validation-api出现在依赖树里说明有老库在偷渡旧坐标。解决方法是排除掉dependency groupIdcom.example/groupId artifactIdsome-old-lib/artifactId exclusions exclusion groupIdjavax.servlet/groupId artifactIdservlet-api/artifactId /exclusion /exclusions /dependencyGradle 工程则用implementation(com.example:some-old-lib) { exclude group: javax.servlet, module: servlet-api }第三步检查容器类库是否冲突。有时你项目里同时挂着 Tomcat 8javax和 Tomcat 10jakarta的依赖在 IDE 里 classpath 顺序不对也会让 JVM 加载到旧类。这种情况直接检查 IDE 的依赖面板把低版本旧类移除。4.2 报错二NoSuchBeanDefinitionException 或循环依赖注入失败Spring Boot 3 里发生过一个非常隐蔽的问题某个Configuration类实现了某个Servlet规范里的接口比如ServletContextInitializer。Spring Boot 2.x 会自动在启动时发现并注册 Bean但 3.x 里由于包名从javax切到jakarta如果你的配置类还实现的是javax.servlet.ServletContextInitializerSpring Boot 根本不会把它当作 Servlet 容器初始化器处理导致容器配置丢失后面各种 Bean 初始化全乱套。这类报错的排查思路很直接使用 IDE 的 Find Usages搜索项目里所有implements或extends的接口逐个确认它们的包名是javax还是jakarta。重点看WebFilter、WebListener、WebServlet注解标注的类这些注解在 Spring Boot 3 里必须用jakarta.servlet.annotation.*下的版本。过滤器如果要被 Spring 管理 Bean建议直接用 Spring 的OncePerRequestFilter这个类在 Spring Framework 6 里已经自动适配了jakarta.servlet从源码层面帮你规避了直接实现Filter接口的 import 问题。4.3 报错三老Gradle项目升级后构建文件全部飘红聊到 2020 年前后那批用 Gradle 构建的 Spring Boot 早期项目有个常见的尴尬情况是build.gradle是老的 Groovy DSL而且没有 Spring 官方依赖管理插件而是自己手工写了 version map。这种项目在升级到 Spring Boot 3.x 时插件类名、依赖坐标、任务名称全变了。这类项目我建议不要直接升 3.x而是按下面路径走第一步先把 Gradle Wrapper 升到 7.6.4 或 8.xSpring Boot 3.x 要求 Gradle 7.5 或 8.x具体看官方文档。老版本 Gradle 直接 load 新版插件百分百报错。第二步引入io.spring.dependency-management插件让 Spring Boot BOM 接管依赖版本plugins { id java id org.springframework.boot version 3.3.5 id io.spring.dependency-management version 1.1.6 }第三步把dependencies里的compile关键字改成implementationruntime改成runtimeOnly。这是 Gradle 7 之后的重要变化老项目不改直接任务失败。第四步跑一遍./gradlew clean build根据报错信息逐个排除版本冲突。这里有个经验老 Gradle 项目的build.gradle文件本身一般没有太多花活最难搞的还是版本之间埋的暗坑。我整理了一张速查表老配置写法现在推荐写法原因compile org.springframework.boot:spring-boot-starter-webimplementation org.springframework.boot:spring-boot-starter-webGradle 7 移除 compile 配置testCompiletestImplementation同上手动指定 spring-boot 版本号数组用 dependency-management 插件统一管理BOM 自动对齐版本Gradle 5.x/6.x Wrapper升级到 7.6.4 或 8.xSpring Boot 3 插件要求新 Gradle4.4 实操排查清单升级后一个都不能少最后送上一份我在项目里验证过的排查清单每次迁移完照着打勾就行[ ]pom.xml或build.gradle中 Spring Boot 版本确认在 3.x[ ] 全局搜索javax.servlet并确认已替换为jakarta.servlet[ ] 全局搜索javax.validation并确认已替换为jakarta.validation[ ] 全局搜索javax.annotation并确认已替换为jakarta.annotation[ ] 检查pom.xml/build.gradle中是否还有javax.*坐标依赖比如javax.servlet-api[ ] 第三方库里是否有老版本冲突mvn dependency:tree或gradlew dependencies[ ] 自定义过滤器和拦截器的 import 已更新且都已被 Spring 扫描到[ ] 启动项目观察控制台日志没有ClassNotFoundException、NoClassDefFoundError[ ] 跑一遍核心业务接口尤其是文件上传、参数校验、WebSocket、消息队列这些容易受规范包影响的模块我在实际项目里带团队做过一次交易系统的 Spring Boot 2.7 到 3.3 迁移代码量大概十几万行最终真正花时间的地方不是改 import而是排查那些老第三方库对javax的隐性依赖。个人建议别指望纯手工替换用 IDE 的全局替换把 import 批量改掉然后再用上面这份清单逐项核对。迁移前一定用 Git 打个基线标签万一中途问题太多随时能退回来别硬扛着在崩溃边缘重启项目。最后再分享一个小技巧如果你不确定某个库到底支不支持 Jakarta直接看它的包名或者 Maven 中央仓库里有没有jakarta前缀的 GAV 坐标。支持的就是jakarta.*开头不支持的很可能还是javax。这比去翻官网上百页的 Release Notes 要快得多。
02
RELATED NEWS

相关资讯

更多网站建设与数字化升级内容

03
WHY YAOTU

想打造同款高转化官网?

懂行业、懂生意,从建站到增长一站式陪跑

◈

场景化定制

不做模板站,围绕你的业务场景量身设计,小众不撞款。

◐

营销型架构

以转化目标组织内容与路径,让官网真正带来询盘。

▲

全周期服务

设计、开发、运营、运维一体,上线只是开始。

免费获取你的建站方案

留下需求,专属顾问 24 小时内为你输出方案建议。