2014-10-07 99 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

相关问题