springcloud之seata在微服务模块全局异常捕捉后导致事务不会滚优雅方案解决

全网独一份,原创第一,更多好文,请关注下方微信公众号

方案一

这个是全局异常在一个方法中进行处理的

下面是大家习惯了的异常处理习惯,代码如下,原理都一样

/**
 * 描述: 全局异处理器 <br>
 * 时间: 2020-06-07 16:32  <br>
 * 作者:IT学习道场
 */
@ResponseBody
@RestControllerAdvice
@Slf4j
public class GlobalExceptionHandler {


    @ExceptionHandler({Exception.class})
    public AjaxVo<?> handleException(Exception e, HttpServletResponse response) {
        //捕捉到的异常如果是自定义异常类,那么就返回自定义异常类中的错误码和错误信息
        String stackExceptionMsg = ExceptionUtil.stacktraceToString(e);
        //异常输出到日志
        log.error(stackExceptionMsg);
        setRespErrStatus(response);
        return AjaxVo.fail(message);
    }

    @ExceptionHandler({TokenException.class})
    public AjaxVo<?> handleTokenException(TokenException e, HttpServletResponse response) {
        setRespErrStatus(response);
        return AjaxVo.fail(e.getCode(), e.getMessage());
    }

    @ExceptionHandler({BaseException.class})
    public AjaxVo<?> handleBaseException(BaseException e, HttpServletResponse response) {
        setRespErrStatus(response);
        return AjaxVo.fail(e.getCode(), e.getMessage());
    }

    @ExceptionHandler({BindException.class})
    public AjaxVo<?> handleBindException(BindException e, HttpServletResponse response) {
        StringBuilder message = new StringBuilder();
        List<FieldError> fieldErrors = e.getBindingResult().getFieldErrors();
        Iterator var4 = fieldErrors.iterator();

        while (var4.hasNext()) {
            FieldError error = (FieldError) var4.next();
            message.append(error.getField()).append(error.getDefaultMessage()).append(",");
        }

        message = new StringBuilder(message.substring(0, message.length() - 1));
        log.error(message.toString());
        setRespErrStatus(response);
        return AjaxVo.fail(message.toString());
    }

    @ExceptionHandler({MethodArgumentNotValidException.class})
    public AjaxVo<?> handlerMethodArgumentNotValidException(MethodArgumentNotValidException e, HttpServletResponse response) {
        StringBuilder message = new StringBuilder();
        Iterator var3 = e.getBindingResult().getFieldErrors().iterator();

        while (var3.hasNext()) {
            FieldError error = (FieldError) var3.next();
            message.append(error.getField()).append(error.getDefaultMessage()).append(",");
        }

        message = new StringBuilder(message.substring(0, message.length() - 1));
        log.error(message.toString());
        setRespErrStatus(response);
        return AjaxVo.fail(message.toString());
    }

    @ExceptionHandler({HttpMediaTypeNotSupportedException.class})
    public AjaxVo<?> handleHttpMediaTypeNotSupportedException(HttpMediaTypeNotSupportedException e, HttpServletResponse response) {
        String message = "该方法不支持" + e.getMessage() + "媒体类型";
        log.error(message);
        setRespErrStatus(response);
        return AjaxVo.fail(message);
    }

    @ExceptionHandler({HttpRequestMethodNotSupportedException.class})
    public AjaxVo<?> handleHttpRequestMethodNotSupportedException(HttpRequestMethodNotSupportedException e, HttpServletResponse response) {
        String message = "该方法不支持" + e.getMessage() + "请求方法";
        log.error(message);
        setRespErrStatus(response);
        return AjaxVo.fail(message);
    }

    @ExceptionHandler({IOException.class})
    public AjaxVo<?> handleIOException(IOException e, HttpServletResponse response) {
        log.error(ExceptionUtil.stacktraceToString(e));
        setRespErrStatus(response);
        return AjaxVo.fail(e.getMessage());
    }

    @ExceptionHandler({IllegalArgumentException.class})
    public AjaxVo<?> handleIllegalArgumentException(IllegalArgumentException e, HttpServletResponse response) {
        log.error(ExceptionUtil.stacktraceToString(e));
        setRespErrStatus(response);
        return AjaxVo.fail(HttpStatus.BAD_REQUEST.value(), e.getMessage());
    }

    @ExceptionHandler({NullPointerException.class})
    public AjaxVo<?> handleNullPointerException(NullPointerException e, HttpServletResponse response) {
        log.error(ExceptionUtil.stacktraceToString(e));
        setRespErrStatus(response);
        return AjaxVo.fail(HttpStatus.BAD_REQUEST.value(), MscmExceptionEnum.NULL_POINT_EXCEPTION.getMessage());
    }

    @ExceptionHandler({BusinessException.class})
    public AjaxVo<?> handleBusinessException(BusinessException e, HttpServletResponse response) {
        log.error(ExceptionUtil.stacktraceToString(e));
        setRespErrStatus(response);
        return AjaxVo.fail(HttpStatus.NOT_ACCEPTABLE.value(), e.getMessage());
    }

    @ExceptionHandler({ServiceException.class})
    public AjaxVo<?> handleServiceException(ServiceException e, HttpServletResponse response) {
        log.error(ExceptionUtil.stacktraceToString(e));
        setRespErrStatus(response);
        Result<Object> result = e.getResult();
        if (Objects.nonNull(result)) {
            return AjaxVo.fail(result.getCode(), e.getMessage());
        }
        return AjaxVo.fail(e.getMessage());
    }

	/**
	 * 如果开启分布式事务,就设置response.status = 500,seata的tm(事务管理器)
	 * 就是感知到 TmTransactionException异常,发起事务回滚
	 */
    private void setRespErrStatus(HttpServletResponse response){
        //如果开启分布式事务,设置错误状态码,让事务回滚
        if (StringUtils.isNotBlank(RootContext.getXID())) {
            response.setStatus(HttpCode.SERVER_ERROR.value());
        }else {
            response.setStatus(HttpCode.OK.value());
        }
    }
}

方案2

可以在全局事务开启端拦截httpresponse 判断 ajaxVo的状态即可,采用手动回滚异常

更多精彩分享请移步:IT学习道场

更多分享关注公众号【IT学习道场】

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

IT学习道场

为你的进步加点油!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值