JAX-RS(或 Quarkus)使用子资源进行反向路由

问题描述 投票:0回答:1

我有一个

ContainerRequestFilter
,它为我的 JAX-RS/Quarkus 应用程序中调用的每个端点收集一些指标。这需要访问每个资源上的
@Path
注释中指定的 URI 模式(“/api/users/{userId}”,而不是像“/api/users/1711”这样的已解析 URL)

我使用以下代码,该代码对于简单资源非常有效,但对于嵌套资源则失败:

class MyFilter implements ContainerRequestFilter {

    @Context
    ResourceInfo resourceInfo

    ...

    private String getUri() {
        var uriBuilder = UriBuilder.fromResource(resourceInfo.getResourceClass());
        var pathAnnotationOnMethod = resourceInfo.getResourceMethod().getAnnotation(Path.class);
        if (pathAnnotationOnMethod != null) {
            uriBuilder = uriBuilder.path(resourceInfo.getResourceMethod());
        }
        return uriBuilder.toTemplate();
    }
}

此方法不适用于如下所示的嵌套资源:

@Path("api/users") class UsersResource { @Inject UserResource userResource; @Inject UserAccessService userAccessService; @Context ResourceContext resourceContext; @Path("{id}") public UserResource user(@PathParam("id") long userId) { userAccessService.ensureAccessTo(userId); return resourceContext.initResource(userResource); } } @RequestScoped class UserResource { @GET public Response getUser(@PathParam("id") long userId) { ... } }
它抛出一个异常,抱怨 

UserResource

 没有 
@Path
 注释。

所以我的问题是:如何解析嵌套(子)资源的 URL 模式?

java jax-rs quarkus
1个回答
0
投票
这就是我解决的方法:

/** * Quarkus (or RESTEasy) doesn't make it easy to get the URI template including the * subresource. This custom class is used to track which subresource were invoked on * our way to the endpoint. */ @RequestScoped public class SubresourcesTracked { private UriBuilder uriBuilder = null; public Optional<UriBuilder> getUriBuilder() { return Optional.ofNullable(uriBuilder); } public UriBuilder computeUriBuilderIfAbsent(Supplier<UriBuilder> supplier) { if (uriBuilder == null) { uriBuilder = supplier.get(); } return uriBuilder; } }
@InterceptorBinding
@Target({ ElementType.TYPE, ElementType.METHOD })
@Retention(value = RetentionPolicy.RUNTIME)
public @interface TrackingSubresource {
}
/**
 * Quarkus (or RESTEasy) doesn't make it easy to get the URI template including the
 * subresource. This custom class is used to track which subresource were invoked on
 * our way to the endpoint.
 */
@Interceptor
@TrackingSubresource
public class TrackingSubresourceInterceptor {

    @Inject
    SubresourcesTracked subresourcesTracked;

    @AroundInvoke
    public Object aroundInvoke(InvocationContext context) throws Exception {
        var method = context.getMethod();
        var uriBuilder = subresourcesTracked.computeUriBuilderIfAbsent(() -> {
            var resource = method.getDeclaringClass();
            Path pathAnnotationOnResource = resource.getAnnotation(Path.class);
            return UriBuilder.fromPath(pathAnnotationOnResource.value());
        });

        var pathAnnotationOnMethod = method.getAnnotation(Path.class);
        if (pathAnnotationOnMethod != null) {
            uriBuilder.path(pathAnnotationOnMethod.value());
        }

        return context.proceed();
    }
}
在请求过滤器中:

@Inject SubresourcesTracked subresourcesTracked; private String getUri() { var uriBuilder = subresourcesTracked.getUriBuilder().map(UriBuilder::toTemplate).map(UriBuilder::fromPath).orElseGet(() -> UriBuilder.fromResource(resourceInfo.getResourceClass())); var path = resourceInfo.getResourceMethod().getAnnotation(Path.class); if (path != null) { uriBuilder = uriBuilder.path(resourceInfo.getResourceMethod()); } return uriBuilder.toTemplate(); }
    
© www.soinside.com 2019 - 2024. All rights reserved.