从零搭建后端框架——异常统一处理的三种方式
前言
项目在运行时出现异常时,从零如若没有对异常进行捕获并处理,搭建就会出现如下页面:

这样显然对用户是后端极其不友好的。
后端不应该直接返回错误页面,框架而应返回统一的异常错误信息,比如:
{ "code": 500,统处 "data": null, "message": "服务异常,请稍后重试" } 复制代码然后,种方前端根据返回的从零信息,显示友好的搭建提示页面。
Spring提供了三种方式对异常统一处理:
@ExceptionHandler 实现HandlerExceptionResolver接口 @ControllerAdvice + @ExceptionHandler下面我们来实际操作下。后端
具体实现
@ExceptionHandler
在【统一基类、框架接口、异常返回对象设计】这一篇文章中,统处 定义了Controller的种方基类BaseController,香港云服务器所以只要在BaseController中使用@ExceptionHandler处理异常,从零 其它Controller继承BaseController即可。实现如下:
@Slf4j public abstract class BaseController { /** * BusinessException 异常处理 */ @ResponseBody @ExceptionHandler(BusinessException.class) public ApiResult businessExceptionHandler(BusinessException e) { log.error(e.getMessage(), e); // do something return ApiResult.fail(e.getMessage()); } /** * Exception 异常处理 */ @ResponseBody @ExceptionHandler(Exception.class) public ApiResult exceptionHandler(Exception e) { log.error(e.getMessage(), e); return ApiResult.fail("服务异常,请稍后重试"); } } 复制代码这里对异常BusinessException和Exception进行了处理, BusinessException是约定的业务异常的基类,若是主动抛出一般都要求是BusinessException的子类,都会被businessExceptionHandler处理。 若是其它异常,可能是意想不到的异常,则会被exceptionHandler处理。b2b供应网
统一处理后,返回结果如下:

实现HandlerExceptionResolver接口
@Slf4j @Component public class GlobalHandlerExceptionResolver implements HandlerExceptionResolver { @Override public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object o, Exception e) { log.error(e.getMessage(), e); ApiResult apiResult; if (e instanceof BusinessException) { BusinessException be = (BusinessException) e; // do something apiResult = ApiResult.fail(be.getMessage()); } else { apiResult = ApiResult.fail("服务异常,请稍后重试"); } WebUtils.writeJson(response, apiResult); return null; } } 复制代码
该方式需要实现HandlerExceptionResolver接口,然后将实现类注入到Spring容器中。
但第一种方式中,通过@ResponseBody注解,Spring就帮我们返回了json格式数据,而这需要自己实现。
这里实现了工具类WebUtils,用于返回json数据,如下:
public class WebUtils { private static final Logger log = LoggerFactory.getLogger(WebUtils.class); private static Gson gson = new GsonBuilder().serializeNulls().create(); /** * 返回json数据 * * @param response * @param object */ public static void writeJson(HttpServletResponse response, int status, Object object) { response.setHeader("Content-Type", "application/json;charset=UTF-8"); response.setContentType("application/json;charset=UTF-8"); response.setStatus(status); PrintWriter out = null; try { String data = object instanceof String ? (String) object : gson.toJson(object); out = response.getWriter(); out.print(data); out.flush(); } catch (Exception e) { log.error(e.getMessage(), e); } finally { if (out != null) { out.close(); } } } /** * 返回json数据 * * @param response * @param object */ public static void writeJson(HttpServletResponse response, Object object) { writeJson(response, HttpServletResponse.SC_OK, object); } /** * 返回json数据 * * @param response * @param object */ public static void writeJson(ServletResponse response, Object object) { if (response instanceof HttpServletResponse) { writeJson((HttpServletResponse) response, object); } } } 复制代码工具类中使用了Gson,需要引用:
<dependency> <groupId>com.google.code.gson</groupId> <artifactId>gson</artifactId> </dependency> 复制代码@ControllerAdvice + @ExceptionHandler
该方式与第一种方式类似,如下:
@Slf4j @ControllerAdvice public class GlobalExceptionHandler { /** * BusinessException 异常处理 */ @ResponseBody @ExceptionHandler(BusinessException.class) public ApiResult businessExceptionHandler(BusinessException e) { log.error(e.getMessage(), e); // do something return ApiResult.fail(e.getMessage()); } /** * Exception 异常处理 */ @ResponseBody @ExceptionHandler(Exception.class) public ApiResult exceptionHandler(Exception e) { log.error(e.getMessage(), e); return ApiResult.fail("服务异常,请稍后重试"); } } 复制代码总结
三种方式都能很好对异常进行统一处理,但是一般推荐使用@ControllerAdvice + @ExceptionHandler方式, 这样能够使异常处理与业务逻辑分离,并且不用自己处理Json数据返回。
源码
github.com/zhuqianchan…
站群服务器本文地址:http://www.bzve.cn/html/439e67298888.html
版权声明
本文仅代表作者观点,不代表本站立场。
本文系作者授权发表,未经许可,不得转载。
