2014-05-25 48 views
26

我有以下代碼:如何在Tomcat上返回JAX-RS(Jersey)中的HTTP 404 JSON/XML響應?

@Path("https://stackoverflow.com/users/{id}") 
public class UserResource { 

    @Autowired 
    private UserDao userDao; 

    @GET 
    @Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON}) 
    public User getUser(@PathParam("id") int id) { 
     User user = userDao.getUserById(id); 
     if (user == null) { 
      throw new NotFoundException(); 
     } 
     return user; 
    } 

如果我請求不存在,像/users/1234用戶,以「Accept: application/json」,該代碼返回HTTP 404響應像預期,但返回Content-Type套到text/html和html的正文消息。註釋@Produces被忽略。

這是代碼問題還是配置問題?

回答

26

,因爲捕獲的異常是通過使用預定義(默認)的JAX-RS運行時處理您的@Produces註釋被忽略ExceptionMapper如果你想在你可以創建一個特定的異常的情況下,以自定義返回的消息你擁有ExceptionMapper來處理它。在你的情況,你需要一個處理NotFoundException異常,查詢「接受」報頭響應的請求類型:

@Provider 
public class NotFoundExceptionHandler implements ExceptionMapper<NotFoundException>{ 

    @Context 
    private HttpHeaders headers; 

    public Response toResponse(NotFoundException ex){ 
     return Response.status(404).entity(yourMessage).type(getAcceptType()).build(); 
    } 

    private String getAcceptType(){ 
     List<MediaType> accepts = headers.getAcceptableMediaTypes(); 
     if (accepts!=null && accepts.size() > 0) { 
      //choose one 
     }else { 
      //return a default one like Application/json 
     } 
    } 
} 
+0

我測試過了。我繼續拋出NotFoundException,但現在使用ExceptionMapper將該異常映射爲設置狀態碼和媒體類型。有用! 在此之前,我試圖返回一個等效的響應,而不是拋出NotFoundException,但我有相同的結果,一個文本/ HTML 404響應。 這是因爲如果我的應用程序拋出NotFoundException默認(隱式)ExceptionMapper進來並覆蓋響應,我返回到HTML響應? 謝謝! – IJR

+1

嘗試不同的解決方案後,這是最好和正確的解決方案。映射* NotFoundException *不是強制性的。只需使用Exception並執行您所需的操作 – Valijon

+0

@Provider非常重要 –

0

即404由服務器返回的,因爲它預期你會通過的東西下面的表格

/users/{id} 

,但你把它當作

/users/user/{id} 

哪些資源是不存在的所有

嘗試訪問資源爲/users/1234

編輯:

在你想爲User響應的情況下創建一個像

class RestResponse<T>{ 
private String status; 
private String message; 
private List<T> objectList; 
//gettrs and setters 
} 

現在一個類,你可以創建如下

RestResponse<User> resp = new RestResponse<User>(); 
resp.setStatus("400"); 
resp.setMessage("User does not exist"); 

和你的休息方法的簽名會像下面

public RestResponse<User> getUser(@PathParam("id") int id) 

雖然萬一成功回覆你可以設置之類的東西

RestResponse<User> resp = new RestResponse<User>(); 
List<User> userList = new ArrayList<User>(); 
userList.add(user);//the user object you want to return 
resp.setStatus("200"); 
resp.setMessage("User exist"); 
resp.setObjectList(userList); 
+0

URI請求更新,我輸入URI時出錯。正確的URI是users/1234在html中獲得404響應,但不是在JSON中。我的問題不是響應代碼,而是響應格式(內容類型)。 – IJR

+0

從生產中移除MediaType.APPLICATION_XML並嘗試,並確保在用戶不存在的情況下給出正確的消息。通常我們會創建一個休息響應,其中包含用戶請求的狀態和消息,當有人嘗試訪問資源時,我們會返回相同的響應 –

+0

我嘗試從註釋@Produces中移除MediaType.APPLICATION_XML,並得到相同的結果,404響應與文本/ HTML內容類型。這就像Tomcat被重寫的內容類型和正文消息... – IJR

11

您可以使用Response回報。實施例下面:

@GET 
@Path("{id}") 
@Produces(MediaType.APPLICATION_JSON) 
public Response get(@PathParam("id") Long id) { 
    ExampleEntity exampleEntity = getExampleEntityById(id); 

    if (exampleEntity != null) { 
     return Response.ok(exampleEntity).build(); 
    } 

    return Response.status(Status.NOT_FOUND).build(); 
} 
-1

這爲我用JAX-RS:

jsonText = "{\n" + " \"account\": {\n" + "  \"billing_account\": \"" + ipResponse.getResult().getParentGUID() + "\",\n" + "}" + ",\n" + "}"; 
parser = new JSONParser(); 

//build our JSON response object 
try { 
    jSONObject = (JSONObject) parser.parse(jsonText); 
    return Response.status(200).entity(jSONObject.toJSONString()).build(); 
} catch (ParseException e) { 
    e.printStackTrace(); 
    jsonEText = "{\n" + " \"account\": {\n" + "  \"billing_account\": \"" + e.getMessage() + "\",\n" + "}" + ",\n" + "}"; 
    jSONObject = (JSONObject) parser.parse(jsonEText); 
    return Response.status(404).entity(jSONObject.toJSONString()).build(); 
} 

我還需要來註釋該方法以作爲@Produces(MediaType.APPLICATION_JSON)指示@Tiago。