如何在Jersey调用之前获取与URI匹配的资源方法?

Pau*_*ora 18 java jersey jersey-1.0

我正在尝试实现一个ContainerRequestFilter对请求参数进行自定义验证的方法.我需要查找将与URI匹配的资源方法,以便我可以从方法的参数中删除自定义注释.

根据这个答案,我应该能够注入ExtendedUriInfo然后使用它来匹配方法:

public final class MyRequestFilter implements ContainerRequestFilter {

    @Context private ExtendedUriInfo uriInfo;

    @Override
    public ContainerRequest filter(ContainerRequest containerRequest) {

        System.out.println(uriInfo.getMatchedMethod());

        return containerRequest;
    }
}
Run Code Online (Sandbox Code Playgroud)

getMatchedMethod显然会返回null,直到实际调用该方法为止(此时对我来说进行验证为时已晚).

Method在调用资源方法之前,如何检索与给定URI匹配的内容?


对于那些感兴趣的人,我正在尝试推出我自己的必需参数验证,如JERSEY-351中所述.

Chr*_*ler 20

实际上,您应该尝试注入ResourceInfo自定义请求过滤器.我已经尝试过RESTEasy,它在那里工作.优点是您针对JSR接口而不是Jersey实现进行编码.

public class MyFilter implements ContainerRequestFilter
{
    @Context
    private ResourceInfo resourceInfo;

    @Override
    public void filter(ContainerRequestContext requestContext)
            throws IOException
    {
        Method theMethod = resourceInfo.getResourceMethod();
        return;
    }
}
Run Code Online (Sandbox Code Playgroud)

  • [`ResourceInfo`](http://docs.oracle.com/javaee/7/api/javax/ws/rs/container/ResourceInfo.html)类是jax-rs 2.0的一部分.上面的内容不适用于泽西岛1.x. (5认同)
  • 我在我的AuthenticationFilter(它实现了ContainerRequestFilter)中尝试了这个,但是我一直得到getResourceMethod()的`null`.这只适用于非PreMatching提供商吗? (2认同)

Pau*_*ora 13

我想出了如何使用Jersey解决我的问题.显然没有办法将请求的URI与调用该方法之前匹配的方法相匹配,至少在Jersey 1.x中是这样.但是,我能够使用a 为每个单独的资源方法ResourceFilterFactory创建一个ResourceFilter- 这样这些过滤器可以提前了解目标方法.

这是我的解决方案,包括对所需查询参数的验证(使用Guava和JSR 305):

public final class ValidationFilterFactory implements ResourceFilterFactory {

    @Override
    public List<ResourceFilter> create(AbstractMethod abstractMethod) {

        //keep track of required query param names
        final ImmutableSet.Builder<String> requiredQueryParamsBuilder =
                ImmutableSet.builder();

        //get the list of params from the resource method
        final ImmutableList<Parameter> params =
                Invokable.from(abstractMethod.getMethod()).getParameters();

        for (Parameter param : params) {
            //if the param isn't marked as @Nullable,
            if (!param.isAnnotationPresent(Nullable.class)) {
                //try getting the @QueryParam value
                @Nullable final QueryParam queryParam =
                        param.getAnnotation(QueryParam.class);
                //if it's present, add its value to the set
                if (queryParam != null) {
                    requiredQueryParamsBuilder.add(queryParam.value());
                }
            }
        }

        //return the new validation filter for this resource method
        return Collections.<ResourceFilter>singletonList(
                new ValidationFilter(requiredQueryParamsBuilder.build())
        );
    }

    private static final class ValidationFilter implements ResourceFilter {

        final ImmutableSet<String> requiredQueryParams;

        private ValidationFilter(ImmutableSet<String> requiredQueryParams) {
            this.requiredQueryParams = requiredQueryParams;
        }

        @Override
        public ContainerRequestFilter getRequestFilter() {
            return new ContainerRequestFilter() {
                @Override
                public ContainerRequest filter(ContainerRequest request) {

                    final Collection<String> missingRequiredParams =
                            Sets.difference(
                                    requiredQueryParams,
                                    request.getQueryParameters().keySet()
                            );

                    if (!missingRequiredParams.isEmpty()) {

                        final String message =
                                "Required query params missing: " +
                                Joiner.on(", ").join(missingRequiredParams);

                        final Response response = Response
                                .status(Status.BAD_REQUEST)
                                .entity(message)
                                .build();

                        throw new WebApplicationException(response);
                    }

                    return request;
                }
            };
        }

        @Override
        public ContainerResponseFilter getResponseFilter() {
            return null;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

并且在ResourceFilterFactoryJersey中注册为servlet的init参数web.xml:

<init-param>
    <param-name>com.sun.jersey.spi.container.ResourceFilters</param-name>
    <param-value>my.package.name.ValidationFilterFactory</param-value>
</init-param>
Run Code Online (Sandbox Code Playgroud)

在启动时,ValidationFilterFactory.create将调用Jersey检测到的每种资源方法.

感谢这篇文章让我走上正轨:如何在Jersey ContainerResponseFilter中获取资源注释