How to get resource method matched to URI before Jersey invokes it?(如何在 Jersey 调用它之前获取与 URI 匹配的资源方法?)
问题描述
我正在尝试实现 ContainerRequestFilter 对请求的参数进行自定义验证.我需要查找将与 URI 匹配的资源方法,以便我可以从方法的参数中抓取自定义注释.
I'm trying to implement a ContainerRequestFilter that does custom validation of a request's parameters. I need to look up the resource method that will be matched to the URI so that I can scrape custom annotations from the method's parameters.
基于 this answer 我应该能够注入 ExtendedUriInfo 然后用它来匹配方法:
Based on this answer I should be able to inject ExtendedUriInfo and then use it to match the method:
public final class MyRequestFilter implements ContainerRequestFilter {
@Context private ExtendedUriInfo uriInfo;
@Override
public ContainerRequest filter(ContainerRequest containerRequest) {
System.out.println(uriInfo.getMatchedMethod());
return containerRequest;
}
}
但是 getMatchedMethod 显然返回 null,一直到该方法被实际调用(此时我进行验证为时已晚).
But getMatchedMethod apparently returns null, all the way up until the method is actually invoked (at which point it's too late for me to do validation).
在调用资源方法之前,如何检索将与给定 URI 匹配的 Method?
How can I retrieve the Method that will be matched to a given URI, before the resource method is invoked?
对于那些感兴趣的人,我正在尝试推出自己的必需参数验证,如 JERSEY 中所述-351.
For those interested, I'm trying to roll my own required parameter validation, as described in JERSEY-351.
推荐答案
我想出了如何仅使用 Jersey 来解决我的问题.至少在 Jersey 1.x 中,显然没有办法将请求的 URI 与在调用该方法之前将匹配的方法相匹配.但是,我能够使用 ResourceFilterFactory 为每个单独的资源方法创建一个 ResourceFilter - 这样这些过滤器可以提前知道目标方法.
I figured out how to solve my problem using only Jersey. There's apparently no way to match a request's URI to the method that will be matched before that method is invoked, at least in Jersey 1.x. However, I was able to use a ResourceFilterFactory to create a ResourceFilter for each individual resource method - that way these filters can know about the destination method ahead of time.
这是我的解决方案,包括对所需查询参数的验证(使用 Guava 和 JSR 305):
Here's my solution, including the validation for required query params (uses Guava and 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;
}
}
}
并且 ResourceFilterFactory 在 Jersey 中注册为 web.xml 中 servlet 的 init 参数:
And the ResourceFilterFactory is registered with Jersey as an init param of the servlet in web.xml:
<init-param>
<param-name>com.sun.jersey.spi.container.ResourceFilters</param-name>
<param-value>my.package.name.ValidationFilterFactory</param-value>
</init-param>
在启动时,Jersey 检测到的每个资源方法都会调用 ValidationFilterFactory.create.
At startup, ValidationFilterFactory.create gets called for each resource method detected by Jersey.
感谢这篇文章让我走上了正轨:如何在 Jersey ContainerResponseFilter 中获取资源注释
Credit goes to this post for getting me on the right track: How can I get resource annotations in a Jersey ContainerResponseFilter
这篇关于如何在 Jersey 调用它之前获取与 URI 匹配的资源方法?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!
本文标题为:如何在 Jersey 调用它之前获取与 URI 匹配的资源方法?
- Eclipse 插件更新错误日志在哪里? 2022-01-01
- Java包名称中单词分隔符的约定是什么? 2022-01-01
- 将log4j 1.2配置转换为log4j 2配置 2022-01-01
- Jersey REST 客户端:发布多部分数据 2022-01-01
- Safepoint+stats 日志,输出 JDK12 中没有 vmop 操作 2022-01-01
- 从 finally 块返回时 Java 的奇怪行为 2022-01-01
- Spring Boot连接到使用仲裁器运行的MongoDB副本集 2022-01-01
- C++ 和 Java 进程之间的共享内存 2022-01-01
- 如何使用WebFilter实现授权头检查 2022-01-01
- value & 是什么意思?0xff 在 Java 中做什么? 2022-01-01
