JAX-RS接口返回Response时出现application/xml类型MessageBodyWriter未找到错误
问题根因
你遇到的这个问题本质是Java泛型擦除导致的:
- 当你方法直接返回
Collection<Department>时,JAX-RS可以从方法签名的返回类型中获取到完整的泛型信息,JAXB的MessageBodyWriter可以识别到集合内的元素是带@XmlRootElement注解的Department类,因此可以正常序列化XML。 - 当你用
Response包装返回结果时,泛型信息会在运行时被擦除,JAX-RS只能识别到entity是Collection类型,无法获知集合内的具体元素类型,因此找不到对应的XML序列化器,就会抛出MessageBodyWriter not found异常。
解决方法
以下三个方案均可解决问题,按优先度推荐:
方案1:使用GenericEntity保留泛型信息
JAX-RS提供了GenericEntity类专门解决泛型擦除问题,修改你的接口返回逻辑即可:
import javax.ws.rs.core.GenericEntity; @GET public Response getDepartments() { Collection<Department> departments = repo.getAll(); if(!departments.isEmpty()) { // 用GenericEntity包裹集合,保留运行时泛型信息 GenericEntity<Collection<Department>> entity = new GenericEntity<Collection<Department>>(departments) {}; return Response.status(Status.FOUND).entity(entity).build(); } return Response.status(Status.NOT_FOUND).entity("Nothing Found").build(); }
方案2:自定义集合包装类
给Department集合定义一个带@XmlRootElement的包装类,明确告诉JAXB序列化结构:
import javax.xml.bind.annotation.XmlRootElement; import java.util.Collection; @XmlRootElement(name = "departments") public class DepartmentList { private Collection<Department> department; public DepartmentList() {} public DepartmentList(Collection<Department> department) { this.department = department; } public Collection<Department> getDepartment() { return department; } public void setDepartment(Collection<Department> department) { this.department = department; } }
返回时把集合塞进包装类再放入Response即可:
return Response.status(Status.FOUND).entity(new DepartmentList(departments)).build();
方案3:补充Jersey JAXB依赖
部分Jersey版本需要显式引入JAXB的媒体支持依赖,在你的pom.xml中添加以下依赖即可,注意版本要和项目中其他Jersey依赖版本保持一致:
<dependency> <groupId>org.glassfish.jersey.media</groupId> <artifactId>jersey-media-jaxb</artifactId> <version>你的Jersey版本号</version> </dependency>
内容的提问来源于stack exchange,提问作者S.Gopinath
相关产品推荐
相关产品推荐

