全网独一份,原创,更多好文,请关注微信公众号,干货你触手可及
seata几个核心角色如下:
异常捕获了,就相当你把事务try/catch了,seata的原理是入全局事务入口
(加了 @GlobalTransactional )方法,TM 向 TC 申请开启一个全局事务,全局事务创建成功并生成一个全局唯一的 XID,XID 在微服务调用链路的上下文中传播,在各自的微服务中RM会判断请求中是否有XID,有就开启一个分支事务
根据分支事务的情况,TM 向 TC 发起针对 XID 的全局提交或回滚决议,
TC 调度 XID 下管辖的全部分支事务完成提交或回滚请求。
下面分析事务捕获,也就是说,分支事务没异常,则事务提交,不会回滚。
微服务中全局异常,会使得分支事务httpResponse中的status状态 = 200,TM就是认为事务是正常的,执行提交哦,

这里解决方案就是在全局异常处理中,判断下是否开启了seata的全局事务,如果开启,则设置httpResponse中的status状态 = 500,这样TM就是认为事务是异常了,抛出TmTransactionException异常,事务就可以回滚了
解决方案代码

/*** 描述: 全局异处理器 <br>* 时间: 2020-06-07 16:32 <br>* 作者:IT学习道场*/@ResponseBody@RestControllerAdvice@Slf4jpublic 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());}}}
AjaxVo 是我们系统的全局响应统一数据结构
你get了吗?这么好,这么优质的公众号,关注下,你将收获满满
文章转载自IT学习道场,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。




