Spring 4.2.4 REST Controller接收XML请求并XSD校验实现咨询
Spring 4.2.4.RELEASE 实现带XSD校验的XML请求REST接口完整方案
我来帮你搞定这个需求,从完善JAXB实体类,到自定义XSD校验的消息转换器,再到配置和异常处理,一步步来:
1. 完善Dummy类的JAXB注解
首先把你的Dummy类补全,JAXB要求必须有无参构造器,同时要明确字段与XML元素的映射关系:
@XmlRootElement(name = "dummy") @XmlAccessorType(XmlAccessType.FIELD) // 直接用字段映射,无需依赖getter/setter public class Dummy { @XmlElement(name = "id", required = true) // 指定XML元素名,标记为必填项 private Integer id; @XmlElement(name = "name", required = true) private String name; // JAXB必须的无参构造器 public Dummy() {} // 补上getter和setter,方便业务逻辑调用 public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } }
2. 自定义带XSD校验的JAXB消息转换器
Spring默认的Jaxb2RootElementHttpMessageConverter不支持XSD校验,我们需要扩展它,加入Schema校验逻辑:
import org.springframework.http.converter.xml.Jaxb2RootElementHttpMessageConverter; import javax.xml.bind.JAXBContext; import javax.xml.bind.JAXBException; import javax.xml.bind.Unmarshaller; import javax.xml.validation.Schema; import javax.xml.validation.SchemaFactory; import org.xml.sax.SAXException; import java.io.IOException; import java.io.InputStream; public class ValidatingJaxb2HttpMessageConverter extends Jaxb2RootElementHttpMessageConverter { private Schema schema; // 构造器传入本地XSD文件路径(示例路径:resources/xsd/dummy.xsd) public ValidatingJaxb2HttpMessageConverter(String xsdResourcePath) throws SAXException, IOException { try (InputStream xsdStream = getClass().getClassLoader().getResourceAsStream(xsdResourcePath)) { if (xsdStream == null) { throw new IOException("XSD file not found at path: " + xsdResourcePath); } SchemaFactory schemaFactory = SchemaFactory.newInstance(javax.xml.XMLConstants.W3C_XML_SCHEMA_NS_URI); this.schema = schemaFactory.newSchema(new org.xml.sax.InputSource(xsdStream)); } } @Override protected Unmarshaller createUnmarshaller(JAXBContext jaxbContext) throws JAXBException { Unmarshaller unmarshaller = super.createUnmarshaller(jaxbContext); // 给反序列化器设置校验用的Schema unmarshaller.setSchema(schema); return unmarshaller; } }
3. 配置Spring MVC消息转换器
在Spring的Java配置类中,注册我们自定义的转换器,替换默认的JAXB转换器:
import org.springframework.context.annotation.Configuration; import org.springframework.http.converter.HttpMessageConverter; import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; import javax.xml.sax.SAXException; import java.io.IOException; import java.util.List; @Configuration public class WebMvcConfig extends WebMvcConfigurerAdapter { @Override public void configureMessageConverters(List<HttpMessageConverter<?>> converters) { try { // 实例化自定义转换器,传入你的XSD文件路径 ValidatingJaxb2HttpMessageConverter validatingConverter = new ValidatingJaxb2HttpMessageConverter("xsd/dummy.xsd"); converters.add(validatingConverter); } catch (SAXException | IOException e) { throw new RuntimeException("Failed to initialize XSD-validating JAXB converter", e); } } }
如果使用XML配置方式,可替换为以下配置:
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"> <property name="messageConverters"> <list> <bean class="com.yourpackage.ValidatingJaxb2HttpMessageConverter"> <constructor-arg value="xsd/dummy.xsd"/> </bean> </list> </property> </bean>
4. 优化Controller方法
原Controller方法已可用,但建议明确指定consumes和produces,表明只处理XML请求并返回XML响应:
import org.springframework.http.MediaType; import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.*; @RestController public class DummyController { @RequestMapping( value = "/insert", method = RequestMethod.POST, consumes = MediaType.APPLICATION_XML_VALUE, produces = MediaType.APPLICATION_XML_VALUE ) @ResponseStatus(HttpStatus.CREATED) public Dummy insert(@RequestBody Dummy dummy) { // 这里可添加业务逻辑,比如将dummy对象保存到数据库 return dummy; // 返回的对象会自动序列化为XML响应 } }
5. 全局异常处理(可选但推荐)
当XML不符合XSD规则时,会抛出UnmarshalException,添加全局异常处理器可返回友好的错误提示:
import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ExceptionHandler; import javax.xml.bind.UnmarshalException; @ControllerAdvice public class GlobalXmlValidationExceptionHandler { @ExceptionHandler(UnmarshalException.class) public ResponseEntity<String> handleXmlValidationFailure(UnmarshalException ex) { // 提取校验的具体错误信息 String errorMsg = "XML validation failed: " + ex.getLinkedException().getMessage(); return new ResponseEntity<>(errorMsg, HttpStatus.BAD_REQUEST); } }
内容的提问来源于stack exchange,提问作者Neok
相关产品推荐
相关产品推荐

