【问题标题】:JAX-RS custom pathparam validatorJAX-RS 自定义路径参数验证器
【发布时间】:2012-06-16 06:56:35
【问题描述】:

我目前正在试验一些 RESTful JAX,我想验证自定义输入。通常正则表达式会很好,但我需要进行更广泛的检查(约 10 种不同的正则表达式模式)。我在搜索 jaxrs 验证时找到了this page。我注意到它说的是“草稿”,但我想我会试一试。

我的参数注释是这样写的:

@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = FooBarValidator.class)
public @interface FooBarParam
{
}

验证器如下所示:

@Provider
public class FooBarValidator
        implements ConstraintValidator<FooBar, Long>
{
    @Override
    public void initialize(FooBar constraintAnnotation)
    {
    }

    @Override
    public boolean isValid(Long value, ConstraintValidatorContext context)
    {
        // validation goes here, this is a test validation
        return (value > 50);
    }
}

Web 服务如下所示:

@javax.ejb.Stateless
@Path("test")
public class testRS
{
    @GET
    @Path("foobar/{fooBar: [0-9]+}")
    @Produces(MediaType.APPLICATION_JSON)
    @Consumes(MediaType.TEXT_PLAIN)
    public String testService(@FooBar @PathParam("fooBar") Long fooBar)
    {
        return "tested with: " + fooBar;
    }
}

但是,如果我使用浏览器使用“http://localhost:8080/jaxtest/rest/test/foobar/11”调用我的 Web 服务,则会调用 Web 服务,并且会显示“tested with: 11” . Web 服务工作正常,只是没有调用验证器。

我已经尝试在验证器类和注释接口中设置断点,但没有命中。

由于参考文档中的“草稿”标题,我偷偷地怀疑我正在做一些不可能的事情。因此,如果我做错了什么或有其他选择,我很高兴听到。

【问题讨论】:

标签: glassfish jersey jax-rs resteasy bean-validation


【解决方案1】:

感谢@PiotrKochański 给我的提示,我已经成功完全实现了我想要的。最大的问题是我必须使用 Glassfish。默认情况下,Glassfish 使用 Jersey 来处理 JAX 内容。

我花了 10 多个小时的努力才完成这项工作,所以对于任何偶然发现此问题的人来说,这可以节省时间。

首先,使用 Maven,这会让您的生活变得如此轻松。

第二步,将 JBoss repo 添加到你的 pom.xml

<repositories>
    <repository>
        <id>jboss-public-repository-group</id>
        <name>JBoss Public Maven Repository Group</name>
        <url>https://repository.jboss.org/nexus/content/groups/public-jboss/</url>
        <layout>default</layout>
        <releases>
            <enabled>true</enabled>
            <updatePolicy>never</updatePolicy>
        </releases>
        <snapshots>
            <enabled>true</enabled>
            <updatePolicy>never</updatePolicy>
        </snapshots>
    </repository>
</repositories>

第三步,给pom.xml添加依赖

<!-- Needed for validator interceptors -->
<dependency>
    <groupId>org.jboss.seam.rest</groupId>
    <artifactId>seam-rest</artifactId>
    <version>3.1.0.Final</version>
</dependency>
<!-- JBoss' RS implementation -->
<dependency>
    <groupId>org.jboss.resteasy</groupId>
    <artifactId>resteasy-jaxrs</artifactId>
    <version>2.3.4.Final</version>
</dependency>
<!-- Because I use JSON I need RESTeasy be able to handle this --> 
<dependency>
    <groupId>org.jboss.resteasy</groupId>
    <artifactId>resteasy-jettison-provider</artifactId>
    <version>2.3.4.Final</version>
</dependency>
<!-- This is THE part that integrates validation in RESTeasy -->
<dependency>
    <groupId>org.jboss.resteasy</groupId>
    <artifactId>resteasy-hibernatevalidator-provider</artifactId>
    <version>2.3.4.Final</version>
</dependency>

最后一个依赖项花了我很长时间。 The docs @PiotrKochański pointed to 没有提到这一点。但是在another version of the docs 我发现了这个:

API 实现和 RESTEasy 之间的集成是通过 resteasy-hibernatevalidator-provider 组件完成的。为了集成,我们需要在类路径中添加resteasy-hibernatevalidator-provider和hibernate-validator。使用 maven 只需包含以下依赖项:

<dependency>
    <groupId>org.jboss.resteasy</groupId>
    <artifactId>resteasy-hibernatevalidator-provider</artifactId>
    <version>2.3-RC1</version>
</dependency>

第四步是将其添加到 web.xml

<context-param>
    <param-name>resteasy.scan</param-name>
    <param-value>true</param-value>
</context-param>
<context-param>
    <param-name>resteasy.servlet.mapping.prefix</param-name>
    <param-value>/rest</param-value>
</context-param>
<listener>
    <listener-class>org.jboss.resteasy.plugins.server.servlet.ResteasyBootstrap</listener-class>
</listener>
<servlet>
    <servlet-name>REST Service</servlet-name>
    <servlet-class>org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>REST Service</servlet-name>
    <url-pattern>/rest/*</url-pattern>
</servlet-mapping>

第五步是这样修改网络服务类:

@javax.ejb.Stateless
@Path("test")
public class testRS
{
    @GET
    @Path("foobar/{fooBar}")
    @Produces(MediaType.APPLICATION_JSON)
    @org.jboss.resteasy.spi.validation.ValidateRequest
    public String testService(@FooBar @PathParam("fooBar") Long fooBar)
    {
        return "tested with: " + fooBar;
    }
}

第六步,将@interface修改为:

@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = FooBarValidator.class)
public @interface FooBarParam
{
    String message() default "{constraint.FooBar}";
    Class<?>[] groups() default {};
    Class<? extends Payload>[] payload() default {};
}

也是一种奖励;我遇到了a presentation about Bean Validation by Emmanuel Bernard,我想我可以分享一下,因为这解释了很多有趣的东西。

【讨论】:

    【解决方案2】:

    您找到的页面是关于应该进入 JAX-RS 2.0 的提案之一(这不是最终版本,也没有实现)。该计划是让 JAX-RS 2.0 与 Bean Validation 集成 - 但正如我所说,这还没有实现。

    目前,如果要验证输入,可以将参数声明为 String(而不是 Long),并将验证作为资源方法的一部分进行。如果验证通过,则转换为 Long。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-10-07
      • 2011-06-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-08-14
      相关资源
      最近更新 更多