Gui*_*let 5 java rest jax-rs jersey jersey-2.0
在Jersey 2中,如何将过滤器绑定到Resource的所有方法以及其子资源的所有方法?
例如,如果我有以下2个资源:
import javax.inject.Singleton;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import org.glassfish.jersey.server.model.Resource;
@Path("/myresource/{id: \\d+}")
@Produces(MediaType.APPLICATION_JSON)
@Singleton
class RootResource {
@GET
@Produces(MediaType.APPLICATION_JSON)
public Response get(@PathParam("id") Long id) {
return Response.ok().build();
}
@Path("/sub")
public Resource getSubResource() {
return Resource.from(SubResource.class);
}
}
@Produces(MediaType.APPLICATION_JSON)
@Singleton
class SubResource {
@GET
@Path("/{subid: \\d+}")
public Response get(@PathParam("id") Long id, @PathParam("subid") Long subid) {
return Response.ok().build();
}
}
Run Code Online (Sandbox Code Playgroud)
我想过滤RootResource.get(Long)和SubResource.get(Long, Long).但如果我有其他资源,则不应过滤这些资源.
使用DynamicFeature,我们只有类和方法的信息.
import javax.ws.rs.container.DynamicFeature;
import javax.ws.rs.container.ResourceInfo;
import javax.ws.rs.core.FeatureContext;
public class MyFeature implements DynamicFeature {
@Override
public void configure(ResourceInfo resourceInfo, FeatureContext context) {
// Here how can I find out that SubResource is actually a sub-resource of RootResource
}
}
Run Code Online (Sandbox Code Playgroud)
我的想法是,我希望能够过滤掉一组id的所有调用(id的集合是动态的),或多或少像这样:
import java.io.IOException;
import javax.ws.rs.container.ContainerRequestContext;
import javax.ws.rs.container.ContainerRequestFilter;
public class MyFilter implements ContainerRequestFilter {
@Override
public void filter(ContainerRequestContext requestContext) throws IOException {
for(Object resource:requestContext.getUriInfo().getMatchedResources()) {
if(resource instanceof RootResource) {
Long id = Long.valueOf(requestContext.getUriInfo().getPathParameters().getFirst("id"));
// ...
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
但我想避免搜索匹配的资源.这可能吗?
我不是100%确定我理解这个问题,但似乎你想要限制哪些资源应该通过过滤器.为此,您可以简单地使用名称绑定.
基本步骤:
创建@NameBinding注释
@NameBinding
@Target({METHOD, TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface Filtered {
}
Run Code Online (Sandbox Code Playgroud)注释过滤器
@Filtered
@Provider
public class MyFilter implements ContainerRequestFilter {
Run Code Online (Sandbox Code Playgroud)注释要过滤的任何根资源,资源方法,子资源类
好吧,经过一些游戏后,我想出了几个解决方案..其中很好,但它完成了工作.
请记住,configure在DynamicFeature我们拥有的每个资源(方法)中都会调用它.
获取正在检查的方法并获取其声明类(在子资源中的方法的情况下,声明类将是子资源类)
Class<?> possibleSubResource =
resourceInfo.getResourceMethod().getDeclaringClass();
Run Code Online (Sandbox Code Playgroud)Resource从您的根资源构建临时
Resource resource = Resource.from(SomeResource.class);
Run Code Online (Sandbox Code Playgroud)迭代其子资源,检查它是否是资源定位器
for (Resource childResource : resource.getChildResources()) {
if (childResource.getResourceLocator() != null) {
Run Code Online (Sandbox Code Playgroud)如果是资源定位器获取返回类型.
ResourceMethod sub = childResource.getResourceLocator();
Class responseClass = sub.getInvocable().getRawResponseType();
Run Code Online (Sandbox Code Playgroud)然后检查步骤4中的响应类型是否= =步骤1中的声明类.
if (responseClass == possibleSubResource) {
context.register(SomeFilter.class);
}
Run Code Online (Sandbox Code Playgroud)为了使上述工作,你实际上需要从locator方法返回子资源类型,而不是a Resource.(您可以尝试使其工作Resource,但我无法弄清楚)
@Path("{id}")
public SomeSubResource getSubResource() {
return new SomeSubResource();
}
Run Code Online (Sandbox Code Playgroud)
这是有效的完整代码(不是经过测试的:-)
@Override
public void configure(ResourceInfo resourceInfo, FeatureContext context) {
Class<?> resourceClass = resourceInfo.getResourceClass();
if (resourceClass == SomeResource.class) {
context.register(SomeFilter.class);
}
Class<?> possibleSubResource = resourceInfo.getResourceMethod().getDeclaringClass();
Resource resource = Resource.from(SomeResource.class);
for (Resource childResource : resource.getChildResources()) {
if (childResource.getResourceLocator() != null) {
ResourceMethod sub = childResource.getResourceLocator();
Class responseClass = sub.getInvocable().getRawResponseType();
if (responseClass == possibleSubResource) {
context.register(SomeFilter.class);
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
为了实现这一点,我们将基于以下假设:定义子资源的是它是注释,@Path并且没有Http方法注释
获取正在检查的方法并获取其声明类(在子资源中的方法的情况下,声明类将是子资源类)
Class<?> possibleSubResource =
resourceInfo.getResourceMethod().getDeclaringClass();
Run Code Online (Sandbox Code Playgroud)遍历Method根资源类中的s
for (Method method : SomeResource.class.getDeclaredMethods()) {
Run Code Online (Sandbox Code Playgroud)检查方法是否具有Http方法注释
boolean isHttpPresent = false;
for (Class annot : Arrays.asList(GET.class, POST.class, PUT.class, DELETE.class)) {
if (method.isAnnotationPresent(annot)) {
isHttpPresent = true;
break;
}
}
Run Code Online (Sandbox Code Playgroud)检查方法是否具有@Path注释.如果是,并且它没有Http方法注释,那么我们注册过滤器
if (method.isAnnotationPresent(Path.class) && !isHttpPresent) {
Class subResourceClass = method.getReturnType();
if (subResourceClass == possibleSubResource) {
context.register(SomeFilter.class);
}
}
Run Code Online (Sandbox Code Playgroud)这是完整的代码
@Override
public void configure(ResourceInfo resourceInfo, FeatureContext context) {
Class<?> resourceClass = resourceInfo.getResourceClass();
if (resourceClass == SomeResource.class) {
context.register(SomeFilter.class);
}
Class<?> possibleSubResource = resourceInfo.getResourceMethod().getDeclaringClass();
for (Method method : SomeResource.class.getDeclaredMethods()) {
boolean isHttpPresent = false;
for(Class annot : Arrays.asList(GET.class,POST.class,PUT.class, DELETE.class)){
if (method.isAnnotationPresent(annot)) {
isHttpPresent = true;
break;
}
}
if(method.isAnnotationPresent(Path.class) && !isHttpPresent){
Class subResourceClass = method.getReturnType();
if (subResourceClass == possibleSubResource) {
context.register(SomeFilter.class);
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
同样,这些解决方案都没有经过严格的测试,但是我尝试过的少数几个案例都可以使用.就个人而言,我只是选择名字绑定,但也许这是泽西队可以提出的问题.这(子资源,当根资源注册的自动注册),并似乎喜欢的事,应该开箱,或至少能够被配置.
| 归档时间: |
|
| 查看次数: |
3084 次 |
| 最近记录: |