TL; DR:調用HttpServletResponse.getStatus
& HttpStatus.valueOf(HttpServletResponse.getStatus)).name()
時@ExceptionHandler
函數返回200 OK
而不是400 Bad Request
爲MissingServletParameterException
。 MissingServletParameterException
僅作爲示例使用,其他例外情況也會發生。春@ExceptionHandler返回錯誤代碼的HTTPStatus
你好,
我遇到的問題是,我想Raygun(崩潰報告系統)與我們的Java /春季啓動應用程序集成。我發現最簡單的方法是創建一個會顯示錯誤信息給用戶,以及將異常傳遞到Raygun自定義異常處理程序。
本來,我試圖實施這裏建議用我自己的Raygun實現增加https://spring.io/blog/2013/11/01/exception-handling-in-spring-mvc
@ControllerAdvice
class GlobalDefaultExceptionHandler {
public static final String DEFAULT_ERROR_VIEW = "error";
private static ApiAccessToken accessToken = new ApiAccessToken();
private static String databaseName = null;
@ExceptionHandler(value = Exception.class)
public ModelAndView
defaultErrorHandler(HttpServletRequest req, Exception e) throws Exception {
// If the exception is annotated with @ResponseStatus rethrow it and let
// the framework handle it
if (AnnotationUtils.findAnnotation(e.getClass(), ResponseStatus.class) != null) {
throw e;
}
// Otherwise setup and send the user to a default error-view.
ModelAndView mav = new ModelAndView();
mav.addObject("exception", e);
mav.addObject("url", req.getRequestURL());
mav.setViewName(DEFAULT_ERROR_VIEW);
// Display the error message to the user, and send the exception to Raygun along with any user details provided.
RaygunClient client = new RaygunClient("<MyRaygunAPIKey>");
if (accessToken.getUsername() != null && accessToken.getDatabaseName() != null) {
ArrayList tags = new ArrayList<String>();
tags.add("username: " + accessToken.getUsername());
tags.add("database: " + accessToken.getDatabaseName());
client.Send(e, tags);
accessToken = null;
return mav;
} else if (databaseName != null) {
ArrayList tags = new ArrayList<String>();
tags.add("database: " + databaseName);
client.Send(e, tags);
databaseName = null;
return mav;
} else {
client.Send(e);
return mav;
}
}
我這個遇到的問題是,我們有公共和私有API端點。私有API端點用於我們的iOS應用程序,而公共API端點沒有前端。它們旨在讓企業能夠融入自己的系統(PowerBI,郵差,定製集成等)。所以沒有可以使用ModelAndView重定向到的視圖。
相反,我已經決定做的是不是使用的ModelAndView,我只是在已格式化模仿Spring的默認JSON的錯誤消息的字符串。
@ExceptionHandler(value = Exception.class)
public @ResponseBody String defaultErrorHandler(HttpServletRequest req, HttpServletResponse resp, Exception e) throws Exception {
// Create a customised error message that imitates the Spring default Json error message
StringBuilder sb = new StringBuilder("{ \n")
.append(" \"timestamp\": ").append("\"").append(DateTime.now().toString()).append("\" \n")
.append(" \"status\": ").append(resp.getStatus()).append(" \n")
.append(" \"error\": ").append("\"").append(HttpStatus.valueOf(resp.getStatus()).name()).append("\" \n")
.append(" \"exception\": ").append("\"").append(e.getClass().toString().substring(6)).append("\" \n")
.append(" \"message\": ").append("\"").append(e.getMessage()).append("\" \n")
.append(" \"path\": ").append("\"").append(req.getServletPath()).append("\" \n")
.append("}");
String errorMessage = String.format(sb.toString());
// Display the error message to the user, and send the exception to Raygun along with any user details provided.
RaygunClient client = new RaygunClient("<MyRaygunAPIKey>");
if (accessToken.getUsername() != null && accessToken.getDatabaseName() != null) {
ArrayList tags = new ArrayList<String>();
tags.add("username: " + accessToken.getUsername());
tags.add("database: " + accessToken.getDatabaseName());
client.Send(e, tags);
accessToken = null;
return errorMessage;
} else if (databaseName != null) {
ArrayList tags = new ArrayList<String>();
tags.add("database: " + databaseName);
client.Send(e, tags);
databaseName = null;
return errorMessage;
} else {
client.Send(e);
return errorMessage;
}
}
與此唯一的問題是,當我故意導致異常被拋出,它的200 OK
HTTP狀態這顯然是不正確的返回。
例如,這是defaultErrorHandler()
註釋掉(發送沒什麼Raygun):
{
"timestamp": "2017-07-18T02:59:45.131+0000",
"status": 400,
"error": "Bad Request",
"exception":
"org.springframework.web.bind.MissingServletRequestParameterException",
"message": "Required String parameter ‘foo’ is not present",
"path": "/api/foo/bar/v1"
}
而這與它沒有被註釋掉(發送例外Raygun):
{
"timestamp": "2017-07-25T06:21:53.895Z"
"status": 200
"error": "OK"
"exception": "org.springframework.web.bind.MissingServletRequestParameterException"
"message": "Required String parameter 'foo' is not present"
"path": "/api/foo/bar/V1"
}
任何幫助或建議我做錯了將不勝感激。感謝您的時間。
你嘗試這樣'@ResponseStatus(HttpStatus.CONFLICT)'近方法的聲明? –
是的,不幸的是它仍然返回200 OK狀態。 –
嘗試刪除'@ ResponseBody'並添加'@ ResponseStatus'。如果它不起作用,請在調試模式下檢查您的代碼是否正在運行,因爲可以通過其他方式處理異常。 –