一 为什么需要统一异常处理
为什么需要异常处理?
程序在运行的过程中难免会出现异常,如果不对异常处理很容易暴露堆栈信息,发生信息泄露事件。
为什么统一异常处理?
1 异常处理逻辑应该与业务逻辑剥离开来,单独处理。
2 相同的异常处理逻辑放在一个地方统一处理,能保证逻辑的统一性。
3 系统中异常处理逻辑可以复用和统一维护。
二 如何实现统一异常处理
在具有 REST API 的 Spring 应用程序中,应使用@ExceptionHandler、@ResponseStatus和@ResponseBody注释来注释异常处理程序方法。让我们看下面的例子:
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;
@ControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(EmployeeNotFoundException.class)
@ResponseStatus(HttpStatus.NOT_FOUND)
@ResponseBody
String employeeNotFoundHandler(HttpServletRequest request,
HttpServletResponse response, Exception ex) {
// do something with request or response
return ex.getMessage();
}
}
@ResponseStatus 注解指定HTTP响应状态码。
也可以在异常处理程序方法中返回自定义对象。如下代码所示:
@ControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(MultipartException.class)
@ResponseStatus(HttpStatus.BAD_REQUEST)
@ResponseBody
public ResponseError handleMultipartException(HttpServletRequest request) {
return new ResponseError(request, "Invalid Upload Request");
}
@ExceptionHandler(HttpRequestMethodNotSupportedException.class)
@ResponseStatus(HttpStatus.METHOD_NOT_ALLOWED)
@ResponseBody
public ResponseError handleMethodNotSupported(HttpServletRequest request) {
return new ResponseError(request, "HTTP request method not supported for this operation.");
}
@ExceptionHandler(IOException.class)
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
@ResponseBody
public ResponseError handleIOException(HttpServletRequest request, Exception ex) {
return new ResponseError(request, "IO Error: " + ex.getMessage());
}
}
ResponseError类:
public class ResponseError {
private final String code;
private final String msg;
private ResponseError() {
}
// 其他方法。。。。。。
}
@RestControllerAdvice 注解如下所示:
使用 @RestControllerAdvice 替换 @ControllerAdvice和@ResponseBody。
@RestControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(MultipartException.class)
@ResponseStatus(HttpStatus.BAD_REQUEST)
public ResponseError handleMultipartException(HttpServletRequest request) {
return new ResponseError(request, "Invalid Upload Request");
}
@ExceptionHandler(HttpRequestMethodNotSupportedException.class)
@ResponseStatus(HttpStatus.METHOD_NOT_ALLOWED)
public ResponseError handleMethodNotSupported(HttpServletRequest request) {
return new ResponseError(request, "HTTP request method not supported for this operation.");
}
@ExceptionHandler(IOException.class)
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
public ResponseError handleIOException(HttpServletRequest request, Exception ex) {
return new ResponseError(request, "IO Error: " + ex.getMessage());
}
}