在服務器端出現異常,或者客戶端請求出錯時,直接返回異常信息對用戶來說是非常不友好的,我們需要對異常信息進行統一處理
1、使用 @ControllerAdvice 註解
使用 @ControllerAdvice 註解的控制層的全局統一異常處理
@ControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(Exception.class)
public ModelAndView customException(Exception e) {
ModelAndView mav = new ModelAndView();
// 跳轉到錯誤頁面
mav.setViewName("error");
return mav;
}
}
@ControllerAdvice 表示這是一個控制器增強類,當控制器發生異常且符合類中定義的攔截異常類,將會被攔截
@ExceptionHandler 則是定義攔截的異常類,可以是自定義異常類,例如:
@ExceptionHandler(value = MyException.class)
@ResponseBody
public JSONObject myErrorHandler(MyException exception) {
JSONObject res = new JSONObject();
res.put("code", exception.getCode());
res.put("msg", exception.getMsg());
return res;
}
當然,我們可以不返回頁面,只返回異常信息
使用 @ControllerAdvice 只能捕獲 Controller 層的異常,前提是 Controller 層沒有對異常做 catch 處理
2、實現 ErrorController 接口
以下是網上一位博主給出的示例代碼,博客地址爲:https://blog.csdn.net/king_is_everyone/article/details/53080851
@Controller
@RequestMapping(value = "error")
@EnableConfigurationProperties({ServerProperties.class})
public class ExceptionController implements ErrorController {
private ErrorAttributes errorAttributes;
@Autowired
private ServerProperties serverProperties;
/**
* 初始化ExceptionController
*
* @param errorAttributes
*/
@Autowired
public ExceptionController(ErrorAttributes errorAttributes) {
Assert.notNull(errorAttributes, "ErrorAttributes must not be null");
this.errorAttributes = errorAttributes;
}
/**
* 定義404的ModelAndView
*
* @param request
* @param response
* @return
*/
@RequestMapping(produces = "text/html", value = "404")
public ModelAndView errorHtml404(HttpServletRequest request, HttpServletResponse response) {
response.setStatus(getStatus(request).value());
Map<String, Object> model = getErrorAttributes(request, isIncludeStackTrace(request, MediaType.TEXT_HTML));
return new ModelAndView("error/404", model);
}
/**
* 定義404的JSON數據
*
* @param request
* @return
*/
@RequestMapping(value = "404")
@ResponseBody
public ResponseEntity<Map<String, Object>> error404(HttpServletRequest request) {
Map<String, Object> body = getErrorAttributes(request, isIncludeStackTrace(request, MediaType.TEXT_HTML));
HttpStatus status = getStatus(request);
return new ResponseEntity<Map<String, Object>>(body, status);
}
/**
* 定義500的ModelAndView
*
* @param request
* @param response
* @return
*/
@RequestMapping(produces = "text/html", value = "500")
public ModelAndView errorHtml500(HttpServletRequest request, HttpServletResponse response) {
response.setStatus(getStatus(request).value());
Map<String, Object> model = getErrorAttributes(request, isIncludeStackTrace(request, MediaType.TEXT_HTML));
return new ModelAndView("error/500", model);
}
/**
* 定義500的錯誤JSON信息
*
* @param request
* @return
*/
@RequestMapping(value = "500")
@ResponseBody
public ResponseEntity<Map<String, Object>> error500(HttpServletRequest request) {
Map<String, Object> body = getErrorAttributes(request, isIncludeStackTrace(request, MediaType.TEXT_HTML));
HttpStatus status = getStatus(request);
return new ResponseEntity<Map<String, Object>>(body, status);
}
/**
* 確定是否應包含stacktrace屬性
*
* @param request the source request
* @param produces the media type produced (or {@code MediaType.ALL})
* @return if the stacktrace attribute should be included
*/
protected boolean isIncludeStackTrace(HttpServletRequest request, MediaType produces) {
ErrorProperties.IncludeStacktrace include = this.serverProperties.getError().getIncludeStacktrace();
if (include == ErrorProperties.IncludeStacktrace.ALWAYS) {
return true;
}
if (include == ErrorProperties.IncludeStacktrace.ON_TRACE_PARAM) {
return getTraceParameter(request);
}
return false;
}
/**
* 獲取錯誤的信息
*
* @param request
* @param includeStackTrace
* @return
*/
private Map<String, Object> getErrorAttributes(HttpServletRequest request, boolean includeStackTrace) {
RequestAttributes requestAttributes = new ServletRequestAttributes(request);
return this.errorAttributes.getErrorAttributes((WebRequest) requestAttributes, includeStackTrace);
}
/**
* 是否包含trace
*
* @param request
* @return
*/
private boolean getTraceParameter(HttpServletRequest request) {
String parameter = request.getParameter("trace");
if (parameter == null) {
return false;
}
return !"false".equals(parameter.toLowerCase());
}
/**
* 獲取錯誤編碼
*
* @param request
* @return
*/
private HttpStatus getStatus(HttpServletRequest request) {
Integer statusCode = (Integer) request.getAttribute("javax.servlet.error.status_code");
if (statusCode == null) {
return HttpStatus.INTERNAL_SERVER_ERROR;
}
try {
return HttpStatus.valueOf(statusCode);
} catch (Exception ex) {
return HttpStatus.INTERNAL_SERVER_ERROR;
}
}
/**
* 實現錯誤路徑
*
* @return
*/
@Override
public String getErrorPath() {
return "";
}
}
總結
1、@ControllerAdvice 定義多個攔截方法,攔截不同的異常類,並且可以獲取拋出的異常信息
2、@ControllerAdvice 只能捕獲進入 Controller 層的異常,比如404,401等錯誤無法捕獲
3、ErrorController,該方式幾乎可以處理所有的異常,包括未進入控制器的錯誤,比如404,401等錯誤
當然,前提是沒有對異常做 catch 處理才能捕獲到
如您在閱讀中發現不足,歡迎留言!!!