簡體   English   中英

澤西島異步ContainerRequestFilter

[英]Jersey Async ContainerRequestFilter

我有一個Jersey REST API,並且正在使用ContainerRequestFilter來處理授權。 我還在所有端點上使用@ManagedAsync ,以便我的API可以處理數千個並發請求。

我的授權過濾器命中了一個遠程服務,但是運行過濾器時,Jersey尚未將當前線程添加到其內部ExecutorService ,因此我完全失去了異步優勢。

我可以告訴Jersey我希望這個ContainerRequestFilter是異步的嗎?

@Priority(Priorities.AUTHORIZATION)
public class AuthorizationFilter implements ContainerRequestFilter
{
    @Inject
    private AuthorizationService authSvc;

    @Override
    public void filter(ContainerRequestContext requestContext) throws IOException
    {
        String authToken = requestContext.getHeaderString(HttpHeaders.AUTHORIZATION);

        // HITS A REMOTE SERVER
        AuthorizationResponse authResponse = authSvc.authorize(authToken);

        if (!authResponse.isAuthorized())
        {
            requestContext.abortWith(Response.status(Response.Status.UNAUTHORIZED)
                    .entity("unauthorized!")
                    .build());
        }
    }
}

這是一個示例資源:

@Path("/stuff")
@Produces(MediaType.APPLICATION_JSON)
public class StuffResource
{
    @GET
    @Path("/{id}")
    @ManagedAsync
    public void getById(@PathParam("id") long id, @Suspended final AsyncResponse ar)
    {
        Stuff s;

        // HIT THE DATABASE FOR STUFF

        ar.resume(s);
    }
}

更新剛剛收到澤西隊球員的回音,從2.7開始,這是不可能的。 只有資源方法本身被異步調用,而不是過濾器。 仍然歡迎任何建議。

從2.7開始,它尚未內置在Jersey中。

如果您有任何過濾器或攔截器可以進行任何認真的工作(如命中遠程授權服務),則@ManagedAsync將無用。 它們可能會增加將來異步運行過濾器的功能,但現在您只能靠自己了。

更新 -還有其他方法...

經過漫長而危險的旅程之后,我發現了一個短期使用的非常棘手的解決方案。 以下是我嘗試過的內容以及失敗/起作用的原因的摘要。

Guice AOP-失敗

我使用Guice進行DI(使Guice注入與Jersey一起工作本身就是一項壯舉 !),所以我認為我可以使用Guice AOP解決該問題。 盡管Guice注入有效,但是Guice無法使用Jersey 2創建資源類,因此Guice AOP無法與資源類方法一起使用。 如果您拼命嘗試讓Guice使用Jersey 2創建資源類, 請不要浪費時間,因為它不會起作用 這是一個眾所周知的問題

HK2 AOP- 推薦解決方案

HK2最近發布了AOP功能,有關如何使其工作的詳細信息,請參閱此問題

監控 -也有效

這不是出於膽小,在Jersey docs中完全不建議這樣做。 您可以注冊ApplicationEventListener並重寫onRequest以返回一個RequestEventListener ,以偵聽RESOURCE_METHOD_START並調用身份驗證/授權服務。 此事件是從@ManagedAsync線程觸發的,這是這里的全部目標。 需要注意的是, abortWith方法是一種禁止操作的方法,因此它不能像普通的ContainerRequestFilter那樣工作。 相反,如果auth失敗,則可以引發異常,然后注冊ExceptionMapper來處理您的異常。 如果有人足夠大膽嘗試一下,請告訴我,我將發布代碼。

我不確定這是否是您想要的,但是,您是否研究過Spring的OncePerRequestFilter 我目前正在將其用於我的授權層,其中每個請求都經過某個過濾器,該過濾器根據將我的過濾器映射到URL的方式擴展了OncePerRequestFilter 以下是我的使用方式的快速概述:

Dropwizard中資源的身份驗證/授權

我對這些過濾器的異步調度部分不是很清楚,但我希望此鏈接至少可以為您要實現的目標提供一些啟示!

我們使用Spring安全性進行身份驗證/授權。 我使用帶有空路徑的子資源定位器解決了該問題,如下所示:

@Path("/customers")
public class CustomerResource {
    @Inject
    private CustomerService customerService;

    @Path("")
    public CustomerSubResource delegate() {
        final Authentication auth = SecurityContextHolder.getContext().getAuthentication();
        return new CustomerSubResource(auth);
    }

    public class CustomerSubResource {
        private final Authentication auth;           

        public CustomerSubResource(final Authentication auth) {
            this.auth = auth;
        }

        @POST
        @Path("")
        @Produces(MediaType.APPLICATION_JSON)
        @Consumes(MediaType.APPLICATION_JSON)
        @ManagedAsync
        public void createCustomer(final Customer customer, @Suspended final AsyncResponse response) {
            // Stash the Spring security context into the Jersey-managed thread
            SecurityContextHolder.getContext().setAuthentication(this.auth);

            // Invoke service method requiring pre-authorization
            final Customer newCustomer = customerService.createCustomer(customer);

            // Resume the response
            response.resume(newCustomer);
        }
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM