Spring MVC中OrderList对象XML序列化无转换器问题求助
在Spring MVC应用中返回OrderList类型对象作为XML格式HTTP响应时,收到如下警告:
WARN 21264 --- [nio-8080-exec-2] .w.s.m.s.DefaultHandlerExceptionResolver : Resolved [org.springframework.http.converter.HttpMessageNotWritableException: No converter for [class com.gcu.model.OrderList] with preset Content-Type 'null']
OrderList是标注了JAXB注解的POJO,用于XML序列化,内部包含OrderModel列表,代码如下:
package com.gcu.model; import jakarta.xml.bind.annotation.XmlElement; import jakarta.xml.bind.annotation.XmlRootElement; import java.util.ArrayList; import java.util.List; @XmlRootElement(name = "orders") public class OrderList { private List<OrderModel> orders = new ArrayList<OrderModel>(); public void setOrders(List<OrderModel> orders) { this.orders = orders; } @XmlElement(name = "order") public List<OrderModel> getOrders() { return orders; } }
当前相关依赖:
<dependency> <groupId>jakarta.xml.bind</groupId> <artifactId>jakarta.xml.bind-api</artifactId> <version>3.0.0</version> </dependency> <dependency> <groupId>com.sun.xml.bind</groupId> <artifactId>jaxb-impl</artifactId> <version>2.3.3</version> <scope>runtime</scope> </dependency>
REST服务实现代码:
package com.gcu.business; import org.springframework.web.bind.annotation.RestController; import com.gcu.model.OrderList; import com.gcu.model.OrderModel; import java.util.List; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; @RestController @RequestMapping("/service") public class OrdersRestService { @Autowired private OrdersBusinessInterface service; @GetMapping(path = "/getjson", produces = { MediaType.APPLICATION_JSON_VALUE }) public List<OrderModel> getOrdersAsJson() { return service.getOrders(); } @GetMapping(path="/getorder/{id}", produces = { MediaType.APPLICATION_JSON_VALUE }) public ResponseEntity<?> getOrder(@PathVariable("id") String id) { try { OrderModel order = service.getOrder(id); if (order == null) { return new ResponseEntity<>(HttpStatus.NOT_FOUND); } else { return new ResponseEntity<>(order, HttpStatus.OK); } } catch (Exception e) { e.printStackTrace(); return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR); } } @GetMapping(path = "/getxml", produces = { MediaType.APPLICATION_XML_VALUE }) public OrderList getOrdersAsXml() { OrderList orders = new OrderList(); orders.setOrders(service.getOrders()); return orders; } }
解决方案
1. 修复JAXB依赖版本不兼容问题
你使用的jakarta.xml.bind-api:3.0.0属于Jakarta EE 9规范(包名从javax.xml.bind改为jakarta.xml.bind),但配套的实现jaxb-impl:2.3.3是Java EE 8版本,两者不兼容,导致Spring无法找到正确的XML转换器。
将依赖替换为Jakarta EE 9兼容的JAXB实现:
<!-- Jakarta XML Binding API --> <dependency> <groupId>jakarta.xml.bind</groupId> <artifactId>jakarta.xml.bind-api</artifactId> <version>3.0.2</version> </dependency> <!-- Jakarta XML Binding 实现 --> <dependency> <groupId>com.sun.xml.bind</groupId> <artifactId>jaxb-impl</artifactId> <version>3.0.2</version> <scope>runtime</scope> </dependency> <!-- 可选:JAXB运行时核心依赖 --> <dependency> <groupId>com.sun.xml.bind</groupId> <artifactId>jaxb-core</artifactId> <version>3.0.2</version> <scope>runtime</scope> </dependency>
2. 确保OrderModel类正确标注JAXB注解
OrderList包含OrderModel列表,必须确保OrderModel也添加了JAXB序列化注解,否则XML转换器无法处理嵌套对象:
package com.gcu.model; import jakarta.xml.bind.annotation.XmlRootElement; @XmlRootElement(name = "order") public class OrderModel { private String id; private String productName; // getter和setter方法 public String getId() { return id; } public void setId(String id) { this.id = id; } public String getProductName() { return productName; } public void setProductName(String productName) { this.productName = productName; } }
3. 手动配置JAXB消息转换器(自动配置失效时使用)
如果Spring Boot没有自动注册Jaxb2RootElementHttpMessageConverter,可以手动创建配置类添加转换器:
package com.gcu.config; import org.springframework.context.annotation.Configuration; import org.springframework.http.converter.HttpMessageConverter; import org.springframework.http.converter.xml.Jaxb2RootElementHttpMessageConverter; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; import java.util.List; @Configuration public class WebMvcConfig implements WebMvcConfigurer { @Override public void configureMessageConverters(List<HttpMessageConverter<?>> converters) { converters.add(new Jaxb2RootElementHttpMessageConverter()); } }
完成以上步骤后,重启应用,访问/service/getxml接口即可正常返回XML格式的OrderList响应。
内容的提问来源于stack exchange,提问作者Isaac Luth

