没有注释的 Jersey 验证

Jersey validation without annotations

我有一个基于 Jersey 的应用程序,我想为输入添加验证。

@POST
@Produces(APPLICATION_JSON) @Consumes(APPLICATION_JSON)
public SomeResponce myMethod(@Valid MyBean myBean)

问题是我的bean是由protostuff生成的,我无法添加验证注解。我找到了如何在没有 annotation/xml 的情况下验证 bean 的方法: http://docs.jboss.org/hibernate/stable/validator/reference/en-US/html_single/#section-programmatic-api

但我对 Jersey 非常不熟悉,无法在文档中找到如何在不使用 bean 中的注释的情况下将此自定义验证器添加到 Jersey。有什么办法吗?

球衣版本 - 2.8

一个简单的方法(也可能用于球衣)是在引用的 xml 文件中 configure hibernate validator via XML. Place the validation.xml file in the META-INF folder and create constraint-mappings

src/main/resources/META-INF/validation.xml(validation.xml 必须位于类路径中的 META-INF 文件夹中):

<validation-config
        xmlns="http://jboss.org/xml/ns/javax/validation/configuration" version="1.1">
    <constraint-mapping>META-INF/mapping.xml</constraint-mapping>
</validation-config>

src/main/resources/META-INF/mapping.xml :

<constraint-mappings
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://jboss.org/xml/ns/javax/validation/mapping validation-mapping-1.1.xsd"
        xmlns="http://jboss.org/xml/ns/javax/validation/mapping" version="1.1">

    <default-package>com.example</default-package>
    <bean class="MyBean" ignore-annotations="true">
        <field name="name">
            <constraint annotation="javax.validation.constraints.Size">
                <element name="max">5</element>
            </constraint>
            <constraint annotation="javax.validation.constraints.NotNull">
            </constraint>
        </field>
    </bean>
</constraint-mappings>

src/main/java/com/example/MyBean.java :

package com.example;

public class MyBean {

    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

src/main/java/com/example/MyResource.java :

package com.example;
import javax.validation.Valid;
import javax.ws.rs.*;
import javax.ws.rs.core.MediaType;

@Path("/api")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
public class MyResource {

    @POST
    public String postIt(@Valid MyBean bean) {
        return bean.getName();
    }
}

使用 MessageBodyReader 提供 "custom" 反序列化。此自定义将简单地向标准解串器(unmarshaller)提供一个 XSD 模式,它将验证您的所有类型。这将在进入您的方法之前发生。这是一个简单的例子:

@Provider
@Consumes("application/xml")
public class MyMsgBodyReader implements MessageBodyReader {

@Override
public boolean isReadable(Class type, java.lang.reflect.Type genericType, Annotation[] annotations, MediaType mediaType) {
    return type.isAnnotationPresent(XmlRootElement.class);
}

@Override
public Object readFrom(Class type, Type genericType, Annotation[] annotations, MediaType mediaType, MultivaluedMap httpHeaders, InputStream entityStream) throws IOException, WebApplicationException {

    try {
        JAXBContext ctx = JAXBContext.newInstance(type);
        Unmarshaller unmarhsaller = ctx.createUnmarshaller();

        SchemaFactory sf = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
        URL schemaFile = HelloWolrd.class.getResource("XSD_FILE_LOCATION");
        if (schemaFile != null) {
            Schema schema = sf.newSchema(schemaFile);
            unmarhsaller.setSchema(schema);
        }
        else {
           System.out.println("not validating xml");
        }

        return unmarhsaller.unmarshal(entityStream);
    }
    catch (JAXBException e) {
        logger.log(e.toString(), Level.WARNING);
    }

    return null;
    }
}

有了这个添加,您现在可以简单地:

@Path("HelloWolrd")
public class HelloWorld{

    @POST
    @Produces(MediaType.APPLICATION_XML)
    @Consumes(MediaType.APPLICATION_XML)
    public Response query(HelloRequest rqst) {
        System.out.println(rqst.getSomeField()); // <-- ALREDAY validated
    } 
}