2016-09-10 59 views
0

這裏是我的用例:澤西島:是否有可能重寫澤西過濾器()的返回類型?

我已經實現了一個澤西篩選器public void filter(ContainerRequestContext requestContext){ //do stuff },它將攔截所有到我已註冊的澤西島端點的傳入請求。基於一些驗證我做的傳入請求頭的,我已經能夠通過以下拒絕的請求:

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

這是我怎麼一直在做它,它很適合我。但是,現在我需要訪問實際請求端點本身內的requestContext中的某些信息。我知道這是可以做到像這樣:

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

的問題是,如果我做了以上^訪問端點上的請求信息,我不能再放棄在過濾器的要求,如果過濾器驗證失敗因爲我得到以下錯誤:

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

看來,如果你定義任何類型的參數上可以在ContainerRequestContext內訪問您的新澤西州的端點,它不會讓你的過濾器內中止過濾器鏈。

一個解決方法(我還沒有嘗試過,但假設將工作),將這樣做:而不是試圖中止過濾器內的請求,如果過濾器驗證失敗,我可以添加自定義標頭請求。然後,在端點本身上,我可以檢查是否設置了該標題。如果設置了,我知道過濾器驗證失敗,然後我可以構建一個Response對象並返回該對象。如果沒有設置,我知道過濾器驗證成功,我可以繼續處理請求。

但是,爲了避免必須在每個澤西島端點上手動執行此檢查(因此需要過濾器),只需在過濾器處停止請求並返回/中止響應即可。我認爲這是整個過濾器的重點。但是,澤西島過濾器方法的返回類型是void,我似乎無法覆蓋它。

任何人都有解決我的困境?

+0

也許會做一些像[this](http:// stackoverflow。com/a/27666797/2587435)而不是獲取整個請求上下文 –

+0

謝謝,但我最終弄清楚我做錯了什麼。將寫在一個答案。 – bscott

回答

0

找出問題的根源是什麼。我的過濾器是一個響應濾波器,看起來像下面這樣:

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); 
     } 
    } 
} 

正如你可以從上面的代碼例子看,我已經定義的響應頭之前,我甚至去請求驗證檢查。通過這樣做,澤西假設我現在處於'響應處理階段'。當我已經爲響應設置標題時,它不會讓我中止請求。

可能有其他方法可以解決這個問題,但我通過將我的過濾器分成兩個過濾器(兩個獨立的類)來解決它。

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"); 
    } 
} 

我現在可以通過@Context@CookieParam@HeaderParam等參數代入我的資源類的功能,而不會得到java.io.IllegalStateException。當我的requestValidationFailed檢查返回true並且永遠不會調用資源函數時,過濾器鏈也會成功中止。