当用spring boot开发后端时,我们常采用前后端分离的开发策略,这时候要求前端与后端需要进行数据交互,传统的一般采用json数据交互。
这时候我们要对spring boot的默认异常处理方式进行修改了,要统一返回数据格式,优雅的数据交互,优雅的开发应用。
首先我们要了解一般springboot的错误发生在什么地方。
一般发生在 controller 、 业务层 、 filter中(如spring security) 、 拦截器中 、还有就是 未知错误 了。
下面我分享一下我的处理方式: @RestControllerAdvice + filter + 重写BasicErrorController 的处理方式。
@RestControllerAdvice+@ExceptionHandler(Exception.class)可以处理经过controller的异常错误
@RestControllerAdvicepublic class BaseExceptionHandler { private static final Logger logger = LoggerFactory.getLogger(BaseExceptionHandler.class); /** * 未知异常 * @param e 异常 * @return 统一结果返回 */ @ExceptionHandler(Exception.class) public R exception(Exception e) { logger.error(e.getMessage(), e); return R.error().message(e.getMessage()); } @ExceptionHandler(NoHandlerFoundException.class) public R noHandlerFoundException(){ return R.error().message("当前页面不存在"); }}当错误没有经过controller时,@RestControllerAdvice是不能捕获的,这时候就需要在filter进行处理。
public class ExceptionHandlerFilter implements Filter { @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain){ try { filterChain.doFilter(servletRequest, servletResponse); } catch (Exception e) { ResponseUtils.out((HttpServletResponse) servletResponse, R.error().message(e.getMessage())); } }}@BeanFilterRegistrationBean exceptionFilterRegistrationBean() { FilterRegistrationBean bean = new FilterRegistrationBean<>(); bean.setFilter(new ExceptionHandlerFilter()); bean.setOrder(Ordered.HIGHEST_PRECEDENCE);//放在最前面 return bean;} 当发生的异常不知道在哪时,springboot会进行默认异常处理,跳转到 /error
这时我们要统一数据返回就必须要从这下手了,创建一个新的Controller处理/error,继承 BasicErrorController ,并覆盖其中的方法
@RestControllerpublic class MyErrorController extends BasicErrorController { @Autowired public MyErrorController(ErrorAttributes errorAttributes, ServerProperties serverProperties, List errorViewResolvers) { super(errorAttributes, serverProperties.getError(), errorViewResolvers); } @Override public ModelAndView errorHtml(HttpServletRequest request, HttpServletResponse response) { HttpStatus status = getStatus(request); Map model = Collections .unmodifiableMap(getErrorAttributes(request, getErrorAttributeOptions(request, MediaType.TEXT_HTML)));// return new ModelAndView("error", model, status); ResponseUtils.out(response, R.error().code(status.value()).message((String) model.get("error"))); return null; } @Override public ResponseEntity spring: mvc: throw-exception-if-no-handler-found: true web: resources: add-mappings: falseserver: error: include-exception: true servlet: encoding: charset: utf-8public class ResponseUtils { public static void out(HttpServletResponse response, R r) { ObjectMapper mapper = new ObjectMapper(); response.setStatus(HttpStatus.OK.value()); response.setContentType("application/json;charset=UTF-8"); try { mapper.writeValue(response.getWriter(), r); } catch (IOException e) { e.printStackTrace(); } }@Datapublic class R implements Serializable { private boolean success; private Integer code; private String message; private Map data; private R(){} public static R ok(){ R r = new R(); r.setSuccess(true); r.setCode(200); r.setMessage("成功"); r.setData(new HashMap<>()); return r; } public static R error() { R r = new R(); r.setSuccess(false); r.setCode(500); r.setMessage("失败"); r.setData(new HashMap<>()); return r; } public R success(Boolean success){ this.success = success; return this; } public R code(Integer code){ this.code = code; return this; } public R message(String message){ this.message = message; return this; } public R data(String key, Object value){ this.data.put(key,value); return this; } public R data(Map map){ this.setData(map); return this; }} | 留言与评论(共有 0 条评论) “” |