Java Spring:根据XSD模式验证REST控制器

Java Spring:根据XSD模式验证REST控制器,java,xml,spring,validation,xsd,Java,Xml,Spring,Validation,Xsd,目前,我使用以下代码创建了RestController package be.smartask.api; import be.smartask.api.model.NumberValue; import be.smartask.api.model.TextValue; import be.smartask.api.model.Translations; import org.springframework.http.HttpStatus; import org.springframework.

目前,我使用以下代码创建了RestController

package be.smartask.api;

import be.smartask.api.model.NumberValue;
import be.smartask.api.model.TextValue;
import be.smartask.api.model.Translations;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;


/**
 * @author Glenn Van Schil
 *         Created on 21/01/2016
 */
@CrossOrigin
@RestController
@RequestMapping(path = "/values")
public class Controller {

    @RequestMapping(method = RequestMethod.POST, headers = "Value-Type=text")
    ResponseEntity<?> createAttribute(@RequestBody TextValue value) {
        System.out.println(value.getCode());
        for (Translations.Translation translation : value.getTranslations().getTranslation()) {
            System.out.println(translation.getLang());
            System.out.println(translation.getValue());
        }
        return new ResponseEntity<>(HttpStatus.CREATED);
    }

    @RequestMapping(method = RequestMethod.POST, headers = "Value-Type=number")
    ResponseEntity<?> createAttribute(@RequestBody NumberValue value) {
        System.out.println(value.getMinValue());
        System.out.println(value.getMaxValue());
        return new ResponseEntity<>(HttpStatus.CREATED);
    }
}
包be.smartask.api;
导入be.smartask.api.model.NumberValue;
导入be.smartask.api.model.TextValue;
导入be.smartask.api.model.Translations;
导入org.springframework.http.HttpStatus;
导入org.springframework.http.ResponseEntity;
导入org.springframework.web.bind.annotation.*;
/**
*@作者格伦·范希尔
*创建于2016年1月21日
*/
@交叉起源
@RestController
@请求映射(路径=“/values”)
公共类控制器{
@RequestMapping(method=RequestMethod.POST,headers=“Value Type=text”)
ResponseEntity createAttribute(@RequestBody TextValue){
System.out.println(value.getCode());
for(Translations.Translation:value.getTranslations().getTranslation()){
System.out.println(translation.getLang());
System.out.println(translation.getValue());
}
返回新的ResponseEntity(HttpStatus.CREATED);
}
@RequestMapping(method=RequestMethod.POST,headers=“Value Type=number”)
ResponseEntity createAttribute(@RequestBody NumberValue值){
System.out.println(value.getMinValue());
System.out.println(value.getMaxValue());
返回新的ResponseEntity(HttpStatus.CREATED);
}
}
这很好用,我可以发布如下数字值:

<numberValue id="id" minValue="0" maxValue="10"/>

但是当我向NumberValue方法发布TextValue时

<textvalue code="LUXE">
    <translations>
        <translation lang="en">luxury car</translation>
    </translations>
</textvalue>

豪华轿车
它仍然有效。它只将minValue和maxValue保留为0,0

我的问题是:当主体与xsd文件中定义的不完全相同时,如何强制执行400:Bad请求(或类似的请求)?所谓定义,是指xml标记的名称不相同,或者缺少所需的xs:attribute,…

我的xsd文件:


更新 根据Sheetal Mohan Sharma的回答,我在spring配置中添加了以下内容

<?xml version="1.0" ?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xmlns:p="http://www.springframework.org/schema/p"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd


http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd">

    <context:component-scan base-package="be.smartask.api"/>

    <mvc:annotation-driven/>

    <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"/>

    <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
        <property name="messageConverters">
            <list>
                <ref bean="marshallingHttpMessageConverter"/>
                <bean class="org.springframework.http.converter.StringHttpMessageConverter"/>
            </list>
        </property>
    </bean>

    <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>
    </bean>
    <bean id="marshallingHttpMessageConverter"
          class="org.springframework.http.converter.xml.MarshallingHttpMessageConverter"
          p:marshaller-ref="jaxb2Marshaller" p:unmarshaller-ref="jaxb2Marshaller"/>

    <bean id="jaxb2Marshaller" class="org.springframework.oxm.jaxb.Jaxb2Marshaller">
        <property name="schema" value="classpath:schema/xsd/smartaskRead.xsd"/>
        <property name="classesToBeBound">
            <list>
                <value>be.smartask.api.model.NumberValue</value>
                <value>be.smartask.api.model.TextValue</value>
            </list>
        </property>
    </bean>
</beans>

be.smartask.api.model.NumberValue
be.smartask.api.model.TextValue

但是NumberValue仍然接受TextValue…

您可以看看如何使用jaxb封送器和解封器 使用消息转换器和jaxmashaller检查XSD。如果验证失败,将抛出错误,但可能不是特定的。检查下面的链接

<bean id="marshallingHttpMessageConverter"
class="org.springframework.http.converter.xml.MarshallingHttpMessageConverter"p:marshaller-ref="jaxb2Marshaller" p:unmarshaller-ref="jaxb2Marshaller" />

<bean id="jaxb2Marshaller">
    <property name="schema" value="classpath:/mySchema.xsd"/>
    <property name="classesToBeBound">
        <list>
            <value>com.xyz.RequestPojo</value>
            <value>com.xyz.ResponsePojo</value>
        </list>
    </property>
</bean>

com.xyz.RequestPojo
com.xyz.ResponsePojo

很少有好的例子-而且

我们甚至通过在XSD文件中提供名称空间来实现API版本控制

config.xml

<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xsi:schemaLocation="
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd
        http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.2.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsd">

    <context:component-scan base-package="be.smartask.api"/>

    <context:annotation-config/>

    <mvc:cors>
        <mvc:mapping path="/**"/>
    </mvc:cors>

    <mvc:annotation-driven>
        <mvc:message-converters>
            <bean id="marshallingHttpMessageConverter"
                  class="org.springframework.http.converter.xml.MarshallingHttpMessageConverter">
                <property name="marshaller" ref="jaxb2Marshaller"/>
                <property name="unmarshaller" ref="jaxb2Marshaller"/>
            </bean>
        </mvc:message-converters>
    </mvc:annotation-driven>

    <bean id="jaxb2Marshaller" class="org.springframework.oxm.jaxb.Jaxb2Marshaller">
        <property name="schemas">
          <list>
            <value>classpath:/schema/xsd/v1/smartAsk.xsd</value>
            <value>classpath:/schema/xsd/v2/smartAsk.xsd</value>
          </list>
        </property>
        <property name="packagesToScan">
          <list>
            <value>be.smartask.api.model.smartask.v1</value>
            <value>be.smartask.api.model.smartask.v2</value>
          </list>
        </property>
    </bean>

    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/view/"/>
        <property name="suffix" value=".jsp"/>
    </bean>
</beans>

类路径:/schema/xsd/v1/smartAsk.xsd
类路径:/schema/xsd/v2/smartAsk.xsd
be.smartask.api.model.smartask.v1
be.smartask.api.model.smartask.v2
首先提供模式位置,然后生成xsd对象的包位置,最后使用新创建的Jaxb2Marshaller覆盖marshallingHttpMessageConverter

如果您计划在API中进行一些版本控制,那么最好提供一个名称空间,以便封送员知道将哪个xsd文件用于哪个包

<xs:schema xmlns="smartask:v1"
       xmlns:xs="http://www.w3.org/2001/XMLSchema"
       xmlns:xsd="http://www.w3.org/2001/XMLSchema"
       xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
       xmlns:annox="http://annox.dev.java.net"
       attributeFormDefault="unqualified"
       elementFormDefault="qualified"
       targetNamespace="smartask:v1"
       jaxb:version="2.1"
       jaxb:extensionBindingPrefixes="annox">

<xs:schema xmlns="smartask:v2"
       xmlns:xs="http://www.w3.org/2001/XMLSchema"
       xmlns:xsd="http://www.w3.org/2001/XMLSchema"
       xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
       xmlns:annox="http://annox.dev.java.net"
       attributeFormDefault="unqualified"
       elementFormDefault="qualified"
       targetNamespace="smartask:v2"
       jaxb:version="2.1"
       jaxb:extensionBindingPrefixes="annox">


在我们的例子中是“smartask:v1”和“smartask:v2”

我可以看到它们使用了Jaxb2Marshaller和ContentNegotiatingViewResolve,但我不知道如何在我的例子中使用它,因为它们没有使用任何xsd或其他类型的模式。他们只检查它是否是有效的xml、json、pdf、htmlOke,我现在对它的工作原理有了更好的了解,非常感谢!但是我在属性上有错误。它说它无法解决属性模式和classesToBeBound。类路径问题可能是-您是否有所有必需的依赖项以及xml中正确的版本和名称空间?JAXB提供了两种方法——“contextPath”和“classesToBeBound”,其中任何一种都可以工作。第8.5节我有错误的JAXB版本,但现在这个问题已经解决了!不幸的是,仍然没有根据我的xsd进行验证,但现在出现了什么错误?你看到我分享的“几个好例子-这里和这里”了吗?你找到了一个有效的解决方案了吗?是的,我会发布answer@MaciejPapież您可以在下面找到我们的解决方案。:)
<xs:schema xmlns="smartask:v1"
       xmlns:xs="http://www.w3.org/2001/XMLSchema"
       xmlns:xsd="http://www.w3.org/2001/XMLSchema"
       xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
       xmlns:annox="http://annox.dev.java.net"
       attributeFormDefault="unqualified"
       elementFormDefault="qualified"
       targetNamespace="smartask:v1"
       jaxb:version="2.1"
       jaxb:extensionBindingPrefixes="annox">

<xs:schema xmlns="smartask:v2"
       xmlns:xs="http://www.w3.org/2001/XMLSchema"
       xmlns:xsd="http://www.w3.org/2001/XMLSchema"
       xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
       xmlns:annox="http://annox.dev.java.net"
       attributeFormDefault="unqualified"
       elementFormDefault="qualified"
       targetNamespace="smartask:v2"
       jaxb:version="2.1"
       jaxb:extensionBindingPrefixes="annox">