简体   繁体   English

Jersey:是否可以覆盖Jersey filter()的返回类型?

[英]Jersey: Is it possible to override return type of Jersey filter()?

Here's my use case: 这是我的用例:

I have implemented a Jersey filter public void filter(ContainerRequestContext requestContext){ //do stuff } that will intercept all incoming requests to any Jersey endpoints I have registered. 我已经实现了Jersey过滤器public void filter(ContainerRequestContext requestContext){ //do stuff } ,它将拦截对我注册的任何Jersey终结点的所有传入请求。 Based on some validation I do of the incoming request headers, I have been able to reject a request via the following: 基于对传入请求标头的验证,我可以通过以下方式拒绝请求:

Response response = Response.status(status).entity(errorMsg).build();
requestContext.abortWith(response);

This is how I have been doing it and it has worked for me. 这就是我一直在做的事情,对我有用。 However, now I need to access certain information in the requestContext within the actual requested endpoint itself. 但是,现在我需要在实际请求的端点本身内的requestContext中访问某些信息。 I know this can be done like so: 我知道可以这样做:

@Path("/path")
@GET
public ReturnType endpoint(@Context ContainerRequestContext requestContext,
                           @CookieParam("cookieId") String cookieValue,
                           @HeaderParam("headerId") String headerValue, etc..){
    //do stuff
}

The problem is, if I do the above^ to access the request information on the endpoint, I can no longer abort the request in the filter if the filter validation fails because I get the following error: 问题是,如果我执行上述操作^以访问端点上的请求信息,则由于过滤器验证失败,我将无法再中止过滤器中的请求,因为我收到以下错误:

java.lang.IllegalStateException: The request cannot be aborted as it is
already in the response processing phase.

It seems that if you define any kind of parameters on your Jersey endpoints that can be accessed within the ContainerRequestContext, it will not allow you to abort the filter chain within the filter. 看来,如果您在Jersey端点上定义了可以在ContainerRequestContext中访问的任何类型的参数,它将不允许您中止过滤器中的过滤器链。

One work around (that I haven't tried yet but assuming will work), would be to do this: Instead of attempting to abort the request within the filter if the filter validation fails, I can just add a custom header to the request. 一种解决方法(我还没有尝试过,但假设可以使用)将是这样做的:如果过滤器验证失败,则不必尝试在过滤器中终止请求,我可以向请求添加一个自定义标头。 Then, on the endpoint itself, I can do a check to see if that header is set. 然后,在端点本身上,我可以进行检查以查看是否设置了该标头。 If it's set, I know the filter validation failed, and then I can build a Response object and return that. 如果已设置,我知道过滤器验证失败,然后可以构建一个Response对象并将其返回。 If it's not set, I know the filter validation succeeded, and I can go ahead and process the request. 如果未设置,则表明过滤器验证成功,并且可以继续处理请求。

However, to avoid having to do this check manually on every single Jersey endpoint I have (hence the point of filters), it would be nice to just stop the request at the filter and return/abort the response right there. 但是,为避免必须在我拥有的每个Jersey终结点上手动进行此检查(因此需要过滤器),最好在过滤器处停止请求并在此返回/中止响应。 I thought that was the whole point of filters in the first place. 我认为这首先是过滤器的重点。 However, the return type of the Jersey filter method is void , and I can't seem to override that. 但是,Jersey过滤器方法的返回类型为void ,我似乎无法覆盖它。

Anyone have a solution to my dilemna? 有人能解决我的难题吗?

Figured out what the root of the issue was. 找出问题的根源。 My filter was a response filter that looked like the following: 我的过滤器是一个响应过滤器,如下所示:

class ResponseFilter implements ContainerResponseFilter{
    public void filter(ContainerRequestContext requestContext,
                       ContainerResponseContext responseContext){
        MultivaluedMap<String, Object> headers = responseContext.getHeaders();
        headers.add("Access-Control-Allow-Origin", "http://localhost:9000");
        headers.add("Access-Control-Allow-Methods", "GET, POST, DELETE, PUT");
        headers.add("Access-Control-Allow-Headers", "Content-Type" );
        headers.add("Access-Control-Allow-Credentials", "true" );
        if(requestValidationFailed){
            Response response = Response.status(status).entity(error).build();
            requestContext.abortWith(response);
        }
    }
}

As you can see from the above code example, I'm already defining the response headers before I even get to the request validation check. 从上面的代码示例中可以看到,我什至在进行请求验证检查之前就已经定义了响应头。 By doing this, Jersey assumes I'm now in the 'response processing phase'. 通过这样做,Jersey假设我现在处于“响应处理阶段”。 It makes sense that it won't let me abort the request when I'm already setting headers for a response. 有道理的是,当我已经设置了响应头时,它不会让我中止请求。

There might be other ways to solve this, but I solved it by splitting my filter into two filters (two separate classes). 可能还有其他方法可以解决此问题,但是我通过将过滤器分为两个过滤器(两个单独的类)解决了这一问题。

class RequestFilter implements ContainerRequestFilter{
    public void filter(ContainerRequestContext requestContext){
        if(requestValidationFailed){
            Response response = Response.status(status).entity(error).build();
            requestContext.abortWith(response);
        }
}

class ResponseFilter implements ContainerResponseFilter{
    public void filter(ContainerRequestContext requestContext,
                       ContainerResponseContext responseContext){
        MultivaluedMap<String, Object> headers = responseContext.getHeaders();
        headers.add("Access-Control-Allow-Origin", "http://localhost:9000");
        headers.add("Access-Control-Allow-Methods", "GET, POST, DELETE, PUT");
        headers.add("Access-Control-Allow-Headers", "Content-Type" );
        headers.add("Access-Control-Allow-Credentials", "true" );
    }
}

I can now pass @Context , @CookieParam , @HeaderParam , etc. parameters into my resource class functions without getting the java.io.IllegalStateException . 我现在可以将@Context@CookieParam@HeaderParam等参数传递到我的资源类函数中,而无需获取java.io.IllegalStateException The filter chain also gets successfully aborted when my requestValidationFailed check returns true and the resource function is never called. 当我的requestValidationFailed检查返回true且从不调用资源函数时,过滤器链也成功中止。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM