异常:java.lang.NoClassDefFoundError: javax/xml/bind/DatatypeConverter
异常本质
jjwt-0.9.1 在生成签名时,需要调用 javax.xml.bind.DatatypeConverter.printBase64Binary(...)
做 Base64 编码。
JDK 9+ 开始 JAXB(java.xml.bind)被移出默认类路径,于是出现
java.lang.NoClassDefFoundError: javax/xml/bind/DatatypeConverter
。
一句话:老版本 jjwt 依赖了 JDK 8 自带、但 JDK 9+ 不再默认提供的 JAXB API。
最简修复方案(继续使用 jjwt-0.9.x)
在 pom.xml
把 JAXB 显式加回来:
<!-- 适用于 JDK 9/11/17/21 -->
<dependency><groupId>javax.xml.bind</groupId><artifactId>jaxb-api</artifactId><version>2.3.1</version>
</dependency>
<!-- 如果还缺实现,再加一个实现包 -->
<dependency><groupId>org.glassfish.jaxb</groupId><artifactId>jaxb-runtime</artifactId><version>2.3.9</version>
</dependency>
刷新 Maven → 重启 → DatatypeConverter
能找到,异常消失。
根治方案(推荐)
jjwt-0.9.1 已停止维护,官方 0.10+ 以后改用自己实现的 Base64,彻底去掉 JAXB 依赖。
- 升级依赖(Spring Boot 3.x 示例,jjwt 0.12.5)
<dependency><groupId>io.jsonwebtoken</groupId><artifactId>jjwt-api</artifactId><version>0.12.5</version>
</dependency>
<dependency><groupId>io.jsonwebtoken</groupId><artifactId>jjwt-impl</artifactId><version>0.12.5</version><scope>runtime</scope>
</dependency>
<dependency><groupId>io.jsonwebtoken</groupId><artifactId>jjwt-jackson</artifactId><version>0.12.5</version><scope>runtime</scope>
</dependency>
- 工具类微调(API 变化)
// 生成
String token = Jwts.builder().setClaims(claims).signWith(SignatureAlgorithm.HS256, jwtProperties.getAdminSecretKey().getBytes(StandardCharsets.UTF_8)).setExpiration(new Date(System.currentTimeMillis() + jwtProperties.getAdminTtl())).compact();// 解析
Claims claims = Jwts.parserBuilder().setSigningKey(jwtProperties.getAdminSecretKey().getBytes(StandardCharsets.UTF_8)).build().parseClaimsJws(token).getBody();
升级后无论 JDK 8 还是 JDK 21 都不再需要 JAXB。
快速判断选哪种
场景 | 做法 |
---|---|
项目即将下线 / 懒得改代码 | 加 jaxb-api 依赖,5 分钟搞定 |
长期维护 / 想跑 JDK 17+ | 直接升 jjwt 0.12.x(或 1.0 GA) |
把依赖改完、重新打包,日志里就不会再出现 DatatypeConverter
的 ClassNotFoundException
了。