当前位置: 首页 > 知识库问答 >
问题:

以CXF为实现限制查询参数JAX-RS的值

应瀚
2023-03-14

我有一个用例,我需要限制可以作为查询参数传递的值。

@Path("/foo")
public interface Foo {

    @GET
    @Path("/details/id/{id}")
    void getFooDetails(@PathParam("id") String id, @QueryParam("sort") String sortDirection);
}

public class FooImpl {
    public void getFooDetails(String id, String sortDir) {
        //Implementation
    }
}

在上面的例子中,我想限制可以通过API传递给ASC, DESC的查询参数的值。

是否有任何现有的CXF注释,我可以用来限制参数上的值?我没有找到任何,所以我尝试了以下解决方案。

我的方法:

@Target({ElementType.PARAMETER, ElementType.METHOD, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
public @interface ValueSet {

    String[] allowedValues();
}

修改后的界面如下所示。

@Path("/foo")
public interface Foo {

    @GET
    @PathParam("/details/id/{id}")
    void getFooDetails(@PathParam("id") String id, @QueryParam("sort") @ValueSet(allowedValues = {"ASC", "DESC"}) String sortDirection);
}

我写了一个CXF拦截器来拦截应用编程接口的调用。我使用反射来获取efimpl.get的Foo细节params的句柄。但是我面临的问题是拦截器查看了Fooimpl.get的Foo细节方法,并且没有在方法params上找到注释@QueryParam,因为@QueryParam在基本方法上,并且注释没有被继承。

拦截器实现:

@Provider
public class ParamValidationInterceptor extends AbstractPhaseInterceptor<Message> {

    public ParamValidationInterceptor() {
        super(Phase.PRE_INVOKE);
        super.addBefore(someInterceptor);
    }

    @Override
    public void handleMessage(Message message) throws Fault {

        UriInfo uriInfo = new UriInfoImpl(message);
        MultivaluedMap<String, String> queryParams = uriInfo.getQueryParameters();
        Method methodToInvoke = (Method) message.get("org.apache.cxf.resource.method");
        Parameter[] parameters = methodToInvoke.getParameters();
        for (Parameter parameter : parameters) {

            if (parameter.isAnnotationPresent(ValueSet.class)) {
                ValueSet valueSet = parameter.getAnnotation(ValueSet.class);
                QueryParam queryParam = parameter.getAnnotation(QueryParam.class);
                Object invokedVal = queryParams.get(queryParam.value());

                String[] allowedValues = valueSet.allowedValues();

                if (!Arrays.asList(allowedValues).contains(invokedVal)) {
                    throw new CustomException();
                }
            }
        }

    }
}

有人能提出前进的道路吗?如果有人能提出替代方法,那就太好了。

另外:我将CXF用作JAX-RS的实现,spring用作容器。

更新:

就像@Cássio Mazzochi Molin和@Andy McCright建议的那样,我将使用@Pattern注释。但是我很想知道为什么JAX-RS注释没有从接口中继承,尽管规范说它们将被继承。

共有2个答案

汪志业
2023-03-14

也许这只是一个输入错误,但CXF可能无法识别getFooDetails方法(在接口上),因为它是用@PathParam而不是@Path注释的。

我没有使用您的ValueSet方法,而是使用了BeanValidation,但下面的代码对我适用。

Foo.java

@Path("/foo")
public interface Foo {

    @GET
    @Path("/details/id/{id}")
    Response getFooDetails(
            @PathParam("id") @Pattern(regexp="[0-9]*") String id,
            @QueryParam("sort") @Pattern(regexp = "ASC|DESC") String sortDirection);
}

傻瓜mpl.java

public class FooImpl implements Foo {

    @Override
    public Response getFooDetails(String id, String sortDirection) {
        Integer idInt = Integer.parseInt(id);
        if ("ASC".equals(sortDirection) || sortDirection == null) {
            ...
        } else if ("DESC".equals(sortDirection)) {
            ...
        }
        return ...;
    }

我已经在基于CXF 3.1.11的WebSphere Liberty 17.0.0.2上完成了这项工作。

希望这有帮助安迪

楚宪
2023-03-14

根据JAX-RS规范的§3.6注释继承部分,建议总是重复注释,而不是依赖注释继承。

完整的报价请参考这个答案。

请记住,@QueryParam注释可以应用于:

  • 资源方法参数

因此,手动验证可能很棘手。

出于验证目的,您应该考虑Bean验证。考虑一个带有允许值的@Pattern注释:

@Pattern(regexp = "ASC|DESC")

只需注释资源方法参数:

@GET
@Path("foo")
public Response getFoos(@QueryParam("sort") 
                        @Pattern(regexp = "ASC|DESC") String sortDirection) {
    ...
}

如果您更喜欢不区分大小写的值,请使用:

@Pattern(regexp = "ASC|DESC", flags = Pattern.Flag.CASE_INSENSITIVE)

如果给定值无效,将抛出ConstraintViolationExctive。要处理此类异常并返回自定义响应,可以使用ExceptionMapper

@Provider 
public class ConstraintViolationExceptionMapper 
        implements ExceptionMapper<ConstraintViolationException> {

    @Override
    public Response toResponse(ConstraintViolationException exception) {
        ...
    } 
}
 类似资料:
  • 我将rest服务配置为通过Variant实现内容协商。在jersey上一切正常,但在apache cxf上有些问题。 找不到类ContentType:Application/XML的消息正文编写器 当我将响应构造为xml类型时,似乎找不到正确的正文编写器。

  • 问题内容: 我有一个JAX-RS资源,它的参数如JSON字符串所示: 在这里使用JSON的原因是,在实际用例中查询对象可能非常复杂。 我想将JSON字符串转换为Java对象,在示例中为dto: JAX-RS是否支持从作为查询参数传递的JSON到Java对象的这种转换? 问题答案: 是的,您可以执行此操作,但是您需要自己编写转换代码。幸运的是,这很容易,您只需要编写一个具有公共构造函数的类即可进行转

  • 但是附件总是空的。有什么建议吗?提前谢了。

  • 在GET操作中,我们对查询参数的长度是否还有任何限制。前面我想我用的是255,这似乎增加了,但我不知道增加的限制是什么。 我面临的问题是,我尝试GETendpoint,如http://localhost:8080/data/ids=<5000 comma seaprated ids>,但失败了 但是具有500个ID(如http://localhost:8080/data/ids=<500 comm

  • 问题内容: 使用JAX-RS和(java8)时出现问题。 我想使用JSON将这样的对象传递到JAX-RS方法中: 我得到的异常是: :没有合适的构造找到型[简单的类型,类在[来源不能实例从JSON对象(需要添加/启用类型信息)::] ; 行:2,列:3] 如何创建某种将json-dates映射到的拦截器?我尝试实现a ,但是如果is是另一个类中的 字段 ,则我必须为每个持有a的类编写一个(据我所知