请稍等 ...
×

采纳答案成功!

向帮助你的同学说点啥吧!感谢那些助人为乐的人

关于SpringCloud的全局异常捕获

师兄您好,我已经看完了 Zuul 的使用,但是还是没明白统一异常该如何处理。

我目前遇到的情况是这样的,同样根据 订单服务商品服务 来举例,在这两个服务中,都有 ResultVO,以及当前服务 ExceptionHandler

  • ResultVO
package com.vito.product.vo

/**
 * Created by VitoYi on 2018/9/11.
 */
class ResultVO<T> private constructor(
        val code: Int?,     //错误码
        val msg: String,    //提示信息
        val data: T?
) {
    companion object {
        fun <T> success(data: T): ResultVO<T> {
            return ResultVO(0, "success", data)
        }

        fun <T> error(code: Int?, msg: String): ResultVO<T> {
            return ResultVO(code, msg, null)
        }
    }
}
  • ExceptionHandler
package com.vito.order.exception

import com.vito.order.vo.ResultVO
import org.slf4j.LoggerFactory
import org.springframework.web.bind.annotation.ControllerAdvice
import org.springframework.web.bind.annotation.ExceptionHandler
import org.springframework.web.bind.annotation.ResponseBody

/**
 * Created by VitoYi on 2018/9/11.
 */
@ControllerAdvice
class ExceptionHandle {
    val log = LoggerFactory.getLogger(this.javaClass)

    @ExceptionHandler(value = [(Exception::class)])
    @ResponseBody
    fun handler(e: Exception): ResultVO<Any> {
        return when(e){
            is CreateOrderException -> ResultVO.error(e.code, e.message!!)
            else -> {
                log.error("【系统异常】{}", e)
                ResultVO.error(-1, e.message!!)
            }
        }
    }
}

比如当有一个下单的请求进来时,请求路径是这样的:Zuul -> 订单服务 -> 商品服务

经过测试发现,如果在 订单服务 中抛出异常,是可以处理并返回封装结果的:

image_1cn3u24mh364blq1sre4c1hp059.png-57.8kB

但是如果在 商品服务 中抛出异常的话:

image_1cn3u8qc61odqi3i12ol1mr2diu5m.png-78.6kB

这是个什么意思呢?
也就是说, Zuul -> A -> B, 如果异常是在 A 这里抛出来的,是没问题的,但如果异常是在 B 这里抛出,那么在 A 这里就要挂了。

对了,我在您的 5-7 扣库存 这一课中,看到您也是在 商品服务 中做了库存的判断,如果库存不足,则抛出异常。

求师兄指教,该如何操作。

正在回答

插入代码

2回答

A是通过http调用B的,http有header和body,是不能传递异常的。B抛出异常,对外就是http的status=500

0 回复 有任何疑惑可以回复我~
  • 提问者 Yoooshiki #1
    那B该如何正确抛出异常呢?
    回复 有任何疑惑可以回复我~ 2018-09-12 09:11:13
  • 提问者 Yoooshiki #2
    目前我是这样解决的:B 不抛出异常,而是将错误信息封装到返回结果里面给到 A,然后在 A 这里抛出异常。这样一来的话,就应该有一个全局的错误码的定义,所有服务都能访问的,因此我将错误码、异常类这些打成一个 jar 包,其他的服务引入。
    这样可以是可以,但是觉得还是太low,分布式事务既然保证的是最终一致性,那么还是应该做异步交互,用消息中间件做事务补偿。可惜课程中没讲到。。。
    回复 有任何疑惑可以回复我~ 2018-09-12 14:11:35
  • 廖师兄 回复 提问者 Yoooshiki #3
    我见过的是这样来做的,一个公共的jar包,handle所有的异常,把异常包装,返回给外部就是一个json, http的status是非200。
    这个和分布式事务没有关系吧,同步是少不了,总会有请求是同步的,另外,对分布式事务感兴趣,可以看看慕课网的相关课程哦。
    回复 有任何疑惑可以回复我~ 2018-09-12 21:03:37
提问者 Yoooshiki 2018-09-11 17:46:18

慕课网的这个 markdown 也太丑了, 发布问题预览的时候挺好,谁知道发出来这么难看,图都挂了。

好吧,再上传一次图。

经过测试发现,如果在 订单服务 中抛出异常,是可以处理并返回封装结果的:

https://img1.sycdn.imooc.com//szimg/5b978f330001424808900570.jpg


但是如果在 商品服务 中抛出异常的话:

https://img1.sycdn.imooc.com//szimg/5b978f460001a6a108880625.jpg

0 回复 有任何疑惑可以回复我~
问题已解决,确定采纳
还有疑问,暂不采纳
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号