本文共 7944 字,大约阅读时间需要 26 分钟。
一个简单的异常请求接口。
第一种解决方案:直接在请求的接口中采用try-catch
的方式,手动捕获异常信息,然后返回对应的结果集。
但是推荐使用SpringBoot
提供的全局异常处理解决方案。
public class CustomException extends RuntimeException { private static final long serialVersionUID = 4564124491192825748L; private int code; public CustomException() { super(); } public CustomException(int code, String message) { super(message); this.setCode(code); } public int getCode() { return code; } public void setCode(int code) { this.code = code; }}
2、异常信息模板
定义返回的异常信息的格式,这样异常信息风格更为统一。@Getter@Setter@AllArgsConstructorpublic class ErrorResponseEntity { private int code; private String message;}
3、全局异常处理
创建一个GlobalExceptionHandler
类,并添加上 @RestControllerAdvice
注解就可以定义出异常通知类了,然后在定义的方法中添加上 @ExceptionHandler
即可实现异常的捕捉。 import org.springframework.http.HttpHeaders;import org.springframework.http.HttpStatus;import org.springframework.http.ResponseEntity;import org.springframework.web.bind.MethodArgumentNotValidException;import org.springframework.web.bind.annotation.ExceptionHandler;import org.springframework.web.bind.annotation.RestControllerAdvice;import org.springframework.web.context.request.WebRequest;import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException;import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;@RestControllerAdvicepublic class GlobalExceptionHandler extends ResponseEntityExceptionHandler { /** * 定义要捕获的异常 可以多个 @ExceptionHandler({}) * * @param request request * @param e exception * @param response response * @return 响应结果 */ @ExceptionHandler(CustomException.class) public ErrorResponseEntity customExceptionHandler(HttpServletRequest request, final Exception e, HttpServletResponse response) { response.setStatus(HttpStatus.BAD_REQUEST.value()); CustomException exception = (CustomException) e; return new ErrorResponseEntity(exception.getCode(), exception.getMessage()); } /** * 捕获 RuntimeException 异常 * TODO 如果你觉得在一个 exceptionHandler 通过 if (e instanceof xxxException) 太麻烦 * TODO 那么你还可以自己写多个不同的 exceptionHandler 处理不同异常 * * @param request request * @param e exception * @param response response * @return 响应结果 */ @ExceptionHandler(RuntimeException.class) public ErrorResponseEntity runtimeExceptionHandler(HttpServletRequest request, final Exception e, HttpServletResponse response) { response.setStatus(HttpStatus.BAD_REQUEST.value()); RuntimeException exception = (RuntimeException) e; return new ErrorResponseEntity(400, exception.getMessage()); } /** * 通用的接口映射异常处理方 */ @Override protected ResponseEntity
注解概述:
@ControllerAdvice
捕获 Controller
层抛出的异常,如果添加 @ResponseBody
返回信息则为JSON
格式。@RestControllerAdvice
相当于 @ControllerAdvice
与 @ResponseBody
的结合体。@ExceptionHandler
统一处理一种类的异常,减少代码重复率,降低复杂度。4、控制器
@GetMapping("/demo")public String demo(Integer num){ String result = "success"; if(null == num){ throw new CustomException(-1, "num不能为空"); } return result;}
5、浏览器请求接口返回
自定义静态异常页面,又分为两种,第一种 是使用 HTTP 响应码来命名页面,例如 404.html、405.html、500.html ….,另一种就是直接定义一个 4xx.html,表示400-499 的状态都显示这个异常页面,5xx.html 表示 500-599 的状态显示这个异常页面。
默认是在 classpath:/static/error/
路径下定义相关页面:
动态的异常页面定义方式和静态的基本 一致,可以采用的页面模板有 jsp、freemarker、thymeleaf。动态异常页面,也支持 404.html 或者 4xx.html ,但是一般来说,由于动态异常页面可以直接展示异常详细信息,所以就没有必要挨个枚举错误了 ,直接定义 4xx.html(这里使用thymeleaf模板)或者 5xx.html 即可。
注意,动态页面模板,不需要开发者自己去定义控制器,直接定义异常页面即可 ,Spring Boot 中自带的异常处理器会自动查找到异常页面。
页面定义如下:
Title 5xx
path | |
error | |
message | |
timestamp | |
status |
效果如下:
classpath:/static/error/404.html
和 classpath:/templates/error/404.html
同时存在时,默认使用动态页面。即完整的错误页面查找方式应该是这样:发生了500错误–>查找动态 500.html 页面–>查找静态 500.html –> 查找动态 5xx.html–>查找静态 5xx.html。
默认情况下,在Spring Boot 中,所有的异常数据定义在 org.springframework.boot.web.reactive.error.DefaultErrorAttributes
类中,具体定义在 getErrorAttributes
方法中 :
@Overridepublic MapgetErrorAttributes(ServerRequest request, boolean includeStackTrace) { Map errorAttributes = new LinkedHashMap<>(); errorAttributes.put("timestamp", new Date()); errorAttributes.put("path", request.path()); Throwable error = getError(request); HttpStatus errorStatus = determineHttpStatus(error); errorAttributes.put("status", errorStatus.value()); errorAttributes.put("error", errorStatus.getReasonPhrase()); errorAttributes.put("message", determineMessage(error)); handleException(errorAttributes, determineException(error), includeStackTrace); return errorAttributes;}
下面自定义异常信息,只需要继承DefaultErrorAttributes:
@Componentpublic class MyErrorAttributes extends DefaultErrorAttributes { @Override public MapgetErrorAttributes(WebRequest webRequest, boolean includeStackTrace) { Map map = super.getErrorAttributes(webRequest, includeStackTrace); if ((Integer)map.get("status") == 500) { map.put("message", "服务器内部错误!"); } return map; }}
效果如下:
默认异常视图就是前面所说的静态或者动态页面,这个异常视图是可以自定义的,默认的异常视图加载逻辑在 org.springframework.boot.autoconfigure.web.servlet.error.BasicErrorController
类的 errorHtml 方法中,这个方法用来返回异常页面+数据
,还有另外一个 error 方法,这个方法用来返回异常数据(如果是 ajax 请求,则该方法会被触发)。
正常情况下, resolveErrorView 方法会来到 DefaultErrorViewResolver 类的 resolveErrorView 方法中:
要自定义异常视图解析,也很容易 ,由于 DefaultErrorViewResolver 是在 ErrorMvcAutoConfiguration 类中提供的实例,即开发者没有提供相关实例时,会使用默认的 DefaultErrorViewResolver ,开发者提供了自己的 ErrorViewResolver 实例后,默认的配置就会失效,因此,自定义异常视图,只需要提供 一个 ErrorViewResolver 的实例即可:
@Componentpublic class MyErrorViewResolver extends DefaultErrorViewResolver { public MyErrorViewResolver(ApplicationContext applicationContext, ResourceProperties resourceProperties) { super(applicationContext, resourceProperties); } @Override public ModelAndView resolveErrorView(HttpServletRequest request, HttpStatus status, Mapmodel) { return new ModelAndView("/aaa/123", model); }}
转载地址:http://bgdhb.baihongyu.com/