Glassfish 4.1切换Jackson替代Moxy/Jaxb后抛出MessageBodyWriter缺失异常求助
我之前在GlassFish 4.1上也碰到过一模一样的坑!切换Jackson替代默认MOXy/JAXB后,异常处理这块确实容易出现找不到text/xml或text/plain类型的MessageBodyWriter的问题,给你几个亲测有效的解决方案:
原因分析
默认情况下,GlassFish的MOXy会负责XML和纯文本类型的序列化处理,但Jackson默认只专注于JSON格式。当系统抛出异常需要返回text/xml或text/plain类型响应时,没有对应的Writer来处理,就会触发MessageBodyProviderNotFoundException。
方案1:添加Jackson的XML支持依赖
给项目引入Jackson的XML数据绑定模块,让Jackson具备处理XML格式的能力,这样它会自动注册对应的MessageBodyWriter。
如果用Maven,添加以下依赖(注意版本尽量和GlassFish自带的Jackson版本匹配,GlassFish 4.1自带的是2.3.x系列):
<dependency> <groupId>com.fasterxml.jackson.dataformat</groupId> <artifactId>jackson-dataformat-xml</artifactId> <version>2.3.3</version> </dependency>
添加后,Jackson就能同时处理JSON和XML类型的响应,异常返回XML格式时就不会再报错。
方案2:自定义ExceptionMapper手动处理响应
创建一个自定义的异常映射器,接管所有异常的响应生成,手动指定返回的媒体类型并构造响应内容,完全绕开自动序列化的问题。
示例代码:
import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; import javax.ws.rs.ext.ExceptionMapper; import javax.ws.rs.ext.Provider; @Provider public class GlobalExceptionMapper implements ExceptionMapper<Throwable> { @Override public Response toResponse(Throwable exception) { // 处理text/plain类型响应 String errorContent = exception.getMessage() != null ? exception.getMessage() : "服务器内部错误"; return Response.status(Response.Status.INTERNAL_SERVER_ERROR) .type(MediaType.TEXT_PLAIN) .entity(errorContent) .build(); // 如果需要返回XML,可手动构造XML字符串 // String xmlContent = String.format("<error><message>%s</message></error>", errorContent); // return Response.status(Response.Status.INTERNAL_SERVER_ERROR) // .type(MediaType.TEXT_XML) // .entity(xmlContent) // .build(); } }
记得给类加上@Provider注解,让JAX-RS自动发现并使用这个映射器。
方案3:保留MOXy处理XML,仅用Jackson处理JSON
如果你只是想替换JSON的序列化实现,没必要完全移除MOXy。可以在JAX-RS应用配置类中指定Jackson为JSON的专属Provider,让MOXy继续负责XML格式的处理。
示例配置类:
import javax.ws.rs.ApplicationPath; import javax.ws.rs.core.Application; import java.util.HashSet; import java.util.Set; @ApplicationPath("/api") public class ApiApplication extends Application { @Override public Set<Class<?>> getClasses() { Set<Class<?>> classes = new HashSet<>(); // 注册Jackson的JSON Provider classes.add(com.fasterxml.jackson.jaxrs.json.JacksonJsonProvider.class); // 添加你的资源类 classes.add(UserResource.class); classes.addOrderResource.class; return classes; } }
这种方式下,MOXy依然会处理XML类型的MessageBodyWriter,Jackson只处理JSON,完美兼容原有逻辑。
额外注意点
- 尽量保证Jackson版本与GlassFish 4.1自带版本一致,避免类加载冲突;
- 如果是手动部署Jackson jar包到服务器,注意不要覆盖服务器自带的相关依赖,可调整类加载优先级。
内容的提问来源于stack exchange,提问作者TouDick

