为了账号安全,请及时绑定邮箱和手机立即绑定

微服务异常处理

标签:
Java 微服务

异常处理切入点布局如下:

图片描述

一、网关层

@RestController
public class ErrorHandlerController implements ErrorController {
    private final ErrorAttributes errorAttributes;

    @Autowired
    public ErrorHandlerController(ErrorAttributes errorAttributes) {
        this.errorAttributes = errorAttributes;
    }

    /**
     * 出异常后进入该方法,交由下面的方法处理
     */
    @Override
    public String getErrorPath() {
        return "/error";
    }

    @RequestMapping("/error")
    public Object error(HttpServletRequest request, HttpServletResponse response) {
        WebRequest webRequest = new ServletWebRequest(request);
        Map<String, Object> errorAttributes = this.errorAttributes.getErrorAttributes(webRequest, true);
        String msg = errorAttributes.getOrDefault("message", "not found").toString();
        String code = errorAttributes.getOrDefault("code", 404).toString();
        if (AuthExceptionEnum.TOKEN_EXPIRE.getCode().toString().equals(code)) {
            response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
        }
        return ResponseData.error(Integer.valueOf(code), msg);
    }
 @Bean
 public AbstractTokenValidService jwtTokenValidServiceImpl(){
     return new JwtAbstractTokenValidServiceImpl();
 }

 private class NosErrorAttributes extends DefaultErrorAttributes {

        @Override
        public Map<String, Object> getErrorAttributes(WebRequest webRequest, boolean includeStackTrace) {
            RequestContext currentContext = RequestContext.getCurrentContext();
            Throwable throwable = currentContext.getThrowable();
            if (throwable instanceof ZuulException) {
                ZuulException zuulException = (ZuulException) throwable;
                Throwable cause = zuulException.getCause();
                if (cause instanceof ServiceException) {
                    ServiceException serviceException = (ServiceException) cause;
                    return BeanUtil.beanToMap(ResponseData.error(serviceException.getCode(), serviceException.getMessage()));
                }
            }

            return BeanUtil.beanToMap(ResponseData.error(CoreExceptionEnum.SERVICE_ERROR.getCode(), CoreExceptionEnum.SERVICE_ERROR.getMessage()));
        }
    }

二、Feign

@Component
public class FeignErrorDecoder implements ErrorDecoder {
    @Override
    public Exception decode(String methodKey, Response response) {
        /*
         解析responseBody内容,解析异常抛出ServiceException
         */
        String responseBody;
        try {
            if (response == null || response.body() == null) {
                if (response != null && response.status() == 404) {
                    return new ServiceException(CoreExceptionEnum.REMOTE_SERVICE_NULL);
                } else {
                    return new ServiceException(CoreExceptionEnum.SERVICE_ERROR);
                }
            }
            responseBody = IoUtil.read(response.body().asInputStream(), "UTF-8");

        } catch (IOException e) {
            return new ServiceException(CoreExceptionEnum.IO_ERROR);
        }

        /*
            json反序列化
         */
        JSONObject jsonObject = JSONObject.parseObject(responseBody);


        Integer code = jsonObject.getInteger("code");
        String message = jsonObject.getString("message");
        if (ToolUtil.isEmpty(message)) {
            message = CoreExceptionEnum.SERVICE_ERROR.getMessage();
        }

        if (code == null) {
            Integer status = jsonObject.getInteger("status");
            if (status == null) {
                return new ServiceException(CoreExceptionEnum.SERVICE_ERROR.getCode(), message);
            } else {
                return new ServiceException(status, message);
            }
        } else {
            return new ServiceException(code, message);
        }

    }
}

三、微服务

@ControllerAdvice
@Slf4j
public class DefaultExceptionHandler {
    /**
     * 拦截业务异常
     */
    @ExceptionHandler(ServiceException.class)
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    @ResponseBody
    public ResponseData notFount(ServiceException e) {
        log.info("业务异常:", e);
        return ResponseData.error(e.getCode(), e.getErrorMessage());
    }

    /**
     * 拦截未知的运行时异常
     */
    @ExceptionHandler(Exception.class)
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    @ResponseBody
    public ResponseData serverError(Exception e) {
        log.error("运行时异常:", e);
        return ResponseData.error(CoreExceptionEnum.SERVICE_ERROR.getCode(), CoreExceptionEnum.SERVICE_ERROR.getMessage());
    }
}

附: SpringBoot默认异常处理器

BasicErrorController

    @RequestMapping(
        produces = {"text/html"}
    )
    public ModelAndView errorHtml(HttpServletRequest request, HttpServletResponse response) {
        HttpStatus status = this.getStatus(request);
        Map<String, Object> model = Collections.unmodifiableMap(this.getErrorAttributes(request, this.isIncludeStackTrace(request, MediaType.TEXT_HTML)));
        response.setStatus(status.value());
        ModelAndView modelAndView = this.resolveErrorView(request, response, status, model);
        return modelAndView != null ? modelAndView : new ModelAndView("error", model);
    }
  @RequestMapping
    @ResponseBody
    public ResponseEntity<Map<String, Object>> error(HttpServletRequest request) {
        Map<String, Object> body = this.getErrorAttributes(request, this.isIncludeStackTrace(request, MediaType.ALL));
        HttpStatus status = this.getStatus(request);
        return new ResponseEntity(body, status);
    }
点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消