2017-06-13 58 views
0

我正在使用Dropwizard,它在內部使用Jersey。我在控制器上有兩種方法:Jersey 2.x - PUT和GET的衝突路由優先級

PUT /garbage/[id1,id2,...idN]旨在獲取路徑參數,該參數是表示要更新的資源的數字ID的列表。我在這裏使用基於正則表達式的PathParam。我在這個例子中欺騙了正則表達式,因爲我不認爲它很重要,但重點是一個數字ID應該匹配正則表達式。

GET /garbage/[id]提取有關單個垃圾的數據。

雖然方法不同,但澤西似乎感到困惑。當我查詢類似的東西

curl localhost:8080/garbage/1 

澤西島給我一個405錯誤。如果我將PUT從圖片中取出(例如,破壞路徑參數regex,或者完全刪除它),GET端點工作正常。

我假設在JAX-RS 3.7.2中有一些細節我錯過了這解釋了爲什麼會出現這種情況,但我無法弄清楚它是什麼。

下面的代碼:

@Path("/garbage") 
@Produces(MediaType.APPLICATION_JSON) 
public class GarbageController { 
    private static final Logger LOG = LoggerFactory.getLogger(GarbageController.class); 

    @PUT 
    @Path("/{params: [\\d,]+}") 
    @Consumes(MediaType.APPLICATION_JSON) 
    @Timed 
    public Response updateGarbage(@PathParam("params") List<PathSegment> params) { 
     LOG.warn("updateGarbage"); 
     return Response.status(Response.Status.OK).build(); 
    } 

    @GET 
    @Path("/{garbageId}") 
    public Response getGarbageById(@PathParam("garbageId") long garbageId) { 
     LOG.warn("getGarbage"); 
     return Response.status(Response.Status.OK).build(); 
    } 
} 

回答

0

@PathSegment的主要目的是處理URI是檢索矩陣參數有用的片段。例如下面的方法:

@GET 
@Path("/book/{id}") 
public String getBook(@PathParam("id") PathSegment id) {...} 

應該能夠處理這個請求:

GET /book;name=EJB 3.0;author=Bill Burke 

因爲@PathSegment截取整個URL片段GET方法似乎被忽略。你可以用一個簡單的字符串分割處理的PUT請求逗號分隔的編號:

@PUT 
@Path("/{params}") 
@Consumes(MediaType.APPLICATION_JSON) 
@Timed 
public Response updateGarbage(@PathParam("params") String params) { 
    LOG.warn("updateGarbage ", params.split(",")); 
    return Response.status(Response.Status.OK).build(); 
} 

您還可以更改請求格式query parameters或實施Converter/Provider處理自定義對象。他們都應該解決GET未實現的問題。

我相信這不是GET和PUT之間的路由優先級的情況,而是這與@Consumes註釋有關,它不能用於GET請求。無論是DW忽略此端點還是將其轉換爲默認的POST方法,這將解釋GET請求的405響應。

+1

感謝您的回答!不幸的是,@消費者不是問題。我已經嘗試過,沒有\ @Consumes,它對行爲沒有影響。 (我最初在沒有\ @Consumes的情況下編寫了這段代碼,然後將它添加爲一個隨機實驗,然後忘記刪除它,我將返回並從示例代碼中刪除\ @Consumes以清除它。) –

0

我想到了這一點,雖然我沒有追蹤到澤西島足夠深的知道它爲什麼起作用。解決方案是重寫@GET方法以使用與@PUT相同的正則表達式語法。 Jersey將處理方法簽名中的類型轉換,並注意如果類型轉換失敗(即GET /garbage/xyz),它將返回404。

@PUT 
@Path("/{params: .+}") 
@Consumes(MediaType.APPLICATION_JSON) 
public Response updateGarbage(@PathParam("params") List<PathSegment> params) { 
    LOG.warn("updateGarbage"); 
    return Response.status(Response.Status.OK).build(); 
} 

@GET 
@Path("/{params: .+}") 
public Response getGarbageById(@PathParam("params") long garbageId) { 
    LOG.warn("getGarbage {}", garbageId); 
    return Response.status(Response.Status.OK).build(); 
}