java - 使用 CXF 作为实现限制查询参数 JAX-RS 的值

标签 java spring rest jax-rs cxf

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

@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 的查询参数 sort 的值。

是否有任何现有的 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 拦截器来拦截 API 调用。我使用反射来处理 FooImpl.getFooDetails 参数。但我面临的问题是拦截器查看 FooImpl.getFooDetails 方法,但没有在方法参数上找到注释 @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();
                }
            }
        }

    }
}

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

P.S:我将 CXF 用作 JAX-RS 的实现,并将 spring 用作容器。

更新:

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

最佳答案

注解继承

根据 §3.6 注释继承 部分 JAX-RS specification ,建议始终重复注解,而不是依赖注解继承。

引用这个answer获取完整报价。

@QueryParam可以应用于不同的目标

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

  • 资源方法参数
  • 资源类字段
  • 资源类 bean 属性

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

使用 Bean 验证

出于验证目的,您应该考虑 Bean Validation .考虑一个 @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)

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

@Provider 
public class ConstraintViolationExceptionMapper 
        implements ExceptionMapper<ConstraintViolationException> {

    @Override
    public Response toResponse(ConstraintViolationException exception) {
        ...
    } 
}

关于java - 使用 CXF 作为实现限制查询参数 JAX-RS 的值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44264138/

相关文章:

java - 在 JavaFX 应用程序中将 Spring Security 附加功能与 Spring Boot 结合使用

java - Chrome 没有缓存

security - Paypal 和微软 WebAPI : best security approach

api - Not Acceptable Accept header 的 HTTP 响应

Java:使用反射从数字实例化枚举

java - JSF 中 "Back"导航链接的最佳实践

java - 部署spring项目出错

java - 使用 Jersey 编写 REST Web 服务时使用 ServletContainer

java - 如何在功能文件中的表格单元格内写入对象?

java - 处理mysql中包含逗号的数字