2014-10-07 126 views
8

如果在Spring Boot Web應用程序中發生異常,我如何自定義響應狀態碼和響應正文中的數據?Spring Boot自定義http錯誤響應?

我已經創建了一個Web應用程序,如果由於某些內部狀態不正常而導致意外發生,則會引發自定義異常。因此,觸發錯誤的請求的響應機身看起來是這樣的:

HTTP/1.1 500 Internal Server Error 
{ 
    "timestamp": 1412685688268, 
    "status": 500, 
    "error": "Internal Server Error", 
    "exception": "com.example.CustomException", 
    "message": null, 
    "path": "/example" 
} 

現在,我想改變狀態代碼,並設置在響應正文中的字段。掠過我想到的一個解決辦法是這樣的:

@ControllerAdvice 
class CustomResponseEntityExceptionHandler extends ResponseEntityExceptionHandler { 

    @ExceptionHandler 
    @ResponseStatus(HttpStatus.BAD_REQUEST) 
    @ResponseBody 
    ErrorMessage handleBadCredentials(CustomException e) { 
     return new ErrorMessage("Bad things happened"); 
    } 
} 

@XmlRootElement 
public class ErrorMessage(
    private String error; 

    public ErrorMessage() { 
    } 

    public ErrorMessage(String error) { 
     this.error = error; 
    } 

    public String getError() { 
     return error; 
    } 

    public void setError(String error) { 
     this.error = error; 
    } 
) 

然而,創建(涉嫌)完全不同的反應:

HTTP/1.1 400 Bad Request 
{ 
    "error": "Bad things happened" 
} 
+2

使您無論做,不想自定義響應? – zeroflagL 2014-10-07 13:22:42

+0

@zeroflagL最好我想定製Spring Boot生成的響應(如果可能的話)。實現完整的自定義解決方案(如問題中提供的解決方案)可行,但在不同項目之間重複使用的可能性較低。 – matsev 2014-10-07 13:44:17

+1

如果自定義解決方案可重複使用,完全取決於您。 FWIW:resposne正文由'DefaultErrorAttributes#getErrorAttributes'組裝。你可以將這個類注入到你的'CustomResponseEntityExceptionHandler'中。 – zeroflagL 2014-10-07 14:05:04

回答

7

HTTP響應狀態代碼可以通過使用HttpServletResponse.sendError(int)方法改變,例如

@ExceptionHandler({IllegalArgumentException.class, NullPointerException.class}) 
void handleBadRequests(HttpServletResponse response) throws IOException { 
    response.sendError(HttpStatus.BAD_REQUEST.value()); 
} 

更多信息可以在我的blog post發現:

@ExceptionHandler 
void handleIllegalArgumentException(IllegalArgumentException e, HttpServletResponse response) throws IOException { 
    response.sendError(HttpStatus.BAD_REQUEST.value()); 
} 

或者,如果你有兩個或兩個以上的異常產生相同的響應狀態,你可以聲明在@ExceptionHandler註釋異常類型。

5

如@zeroflagL所述,Spring Boot在org.springframework.boot.autoconfigure.web.DefaultErrorAttributes中構造「標準」錯誤響應體。與您的需求類似,我想要充分利用所有這些,但只需增加一些由我的例外提供的「類型」字段。

我通過實施Component來做到這一點,其分類爲DefaultErrorAttributes。 Spring Boot自動將其拾起並用於我的默認值。

@Component 
public class ExtendedErrorAttributes extends DefaultErrorAttributes { 
    @Override 
    public Map<String, Object> getErrorAttributes(RequestAttributes requestAttributes, boolean includeStackTrace) { 
     final Map<String, Object> errorAttributes = super.getErrorAttributes(requestAttributes, includeStackTrace); 

     final Throwable error = super.getError(requestAttributes); 
     if (error instanceof TypeProvider) { 
      final TypeProvider typeProvider = (TypeProvider) error; 
      errorAttributes.put("type", typeProvider.getTypeIdentifier()); 
     } 

     return errorAttributes; 
    } 
} 

就這樣,我得到了增強JSON響應體,如

{ 
    "timestamp": 1488058582764, 
    "status": 429, 
    "error": "Too Many Requests", 
    "exception": "com.example.ExternalRateLimitException", 
    "message": "DAILY_LIMIT: too many requests", 
    "path": "/api/lookup", 
    "type": "DAILY_LIMIT" 
} 
+0

很好的答案!如果您不想泄露這些類型的細節,也可以輕鬆修改它以從生產部署中的錯誤響應中移除「異常」屬性。 – Andrew 2017-08-12 20:34:41

相關問題