Java加载XML文件时触发HTTP 500错误问题排查
问题根因
报错和业务代码、REST接口逻辑无关,核心是项目运行时缺少JAXB(XML序列化/反序列化组件)的实现包,导致REST客户端把接口返回的XML解析成List<Stationss>对象时抛出类找不到异常。你使用的Tomcat 10对应Jakarta EE 9环境,从Java 9开始JAXB就被移出JDK默认类库,仅引入JAXB接口包没有实现包时就会触发该错误。
问题场景
- 大学Java课程项目,JSP页面调用REST客户端拉取登车站点列表,已确认REST接口可正常返回XML数据
- 运行环境:Apache Tomcat/10.0.16,Jersey作为REST客户端,JAXB处理XML和Java对象转换
- 访问JSP页面时返回500内部服务器错误,报错触发点为JSP中调用
RestClient.getStations()的代码行
相关代码片段
1. 站点列表加载JSP代码
<%@page import="Controllers.RestClient"%> <%@page import="java.util.List"%> <%@page import="Model.Stationss"%> <%@page import="javax.xml.bind.JAXBException"%> <%@page contentType="text/html" pageEncoding="UTF-8"%> <!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>JSP Page</title> </head> <body> <label for="Origin">登车站点:</label> <select name ="StartStation" id="stations"> <% List<Stationss> listS = RestClient.getStations(); for (int i = 0; i < listS.size(); i++) { out.print("<option value = " + i + ">" + listS.get(i).getName() + "</option>"); } %> </select><br> </body> </html>
2. REST客户端逻辑代码
package Controllers; import java.util.List; import Model.Stationss; import java.util.ArrayList; import javax.ws.rs.client.Client; import javax.ws.rs.client.ClientBuilder; import javax.ws.rs.client.Invocation; import javax.ws.rs.client.WebTarget; import javax.ws.rs.core.GenericType; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; import javax.xml.bind.JAXBException; public class RestClient { public static List<Stationss> getStations() { System.out.print("test"); String link = "http://localhost:8080"; String path = "/Service/webresources/pkg.service.stations"; Client client = ClientBuilder.newBuilder().build(); WebTarget target = client.target(link).path(path); Invocation.Builder invocation = target.request(MediaType.APPLICATION_XML); System.out.print(link); System.out.print(path); Response response = invocation.get(Response.class); System.out.print(response); List<Stationss> list = response.readEntity(new GenericType<List<Stationss>>() { }); System.out.print(list); return list; } }
3. Stationss模型类代码
package Model; import javax.persistence.Transient; import javax.xml.bind.annotation.XmlRootElement; @XmlRootElement public class Stationss { private int id; private String name; private int zone; Gate gates = new Gate(zone); public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getZone() { return zone; } public void setZone(int zone) { this.zone = zone; } public Gate getGates() { return gates; } public void setGates(Gate gates) { this.gates = gates; } public Stationss() { } public Stationss(int id, String name, int zone) { this.id = id; this.name = name; this.zone = zone; } @Transient public CheckTicket enter(String xml) { return gates.enter(xml); } @Transient public boolean exit(String xml) { return gates.exit(xml); } }
核心报错链路
HTTP Status 500 – Internal Server Error
- 第一层异常:JSP执行到
List<Stationss> listS = RestClient.getStations();时抛出Jasper解析异常- 第二层异常:REST客户端调用
response.readEntity反序列化XML返回值时抛出HTTP 500 Internal Server Error- 第三层异常:JAXB组件抛出
Implementation of JAXB-API has not been found on module path or classpath.- 最终根因:抛出
java.lang.ClassNotFoundException: com.sun.xml.bind.v2.ContextFactory,类路径下找不到JAXB的实现类
修复步骤
- 给项目补全JAXB实现依赖:
- 如果你用Maven管理项目,在pom.xml中加入以下依赖,版本和Jakarta EE环境匹配即可:
<!-- JAXB接口包 --> <dependency> <groupId>jakarta.xml.bind</groupId> <artifactId>jakarta.xml.bind-api</artifactId> <version>3.0.1</version> </dependency> <!-- JAXB实现包 --> <dependency> <groupId>com.sun.xml.bind</groupId> <artifactId>jaxb-impl</artifactId> <version>3.0.2</version> <scope>runtime</scope> </dependency>
- 如果你手动导包,直接下载对应版本的
jaxb-impl-3.0.2.jar放到项目的WEB-INF/lib目录下即可。 - 依赖补全后如果仍报类找不到错误,检查所有JAXB相关的import语句,Tomcat10对应的Jakarta命名空间为
jakarta.xml.bind.*,把原有javax.xml.bind.*的导入全部替换,同时确认引入的Jersey依赖为3.x以上的Jakarta版本,不要混用javax和jakarta命名空间的包。 - 重新构建部署项目后即可正常解析返回的站点列表。
内容的提问来源于stack exchange,提问作者WMusquim
相关产品推荐
相关产品推荐

