分布式事務Seata框架+springcloud踩坑

1、編排腳本中指定的ServiceName,報找不到bean
腳本片段:

{
...
    "States": {
        "ServiceA": {
            "Type": "ServiceTask",
            "ServiceName": "IServiceASeata",
            "ServiceMethod": "run",
            "CompensateState": "CompensateServiceA",
...

需要在feign接口上指定quilifier,屬性值是服務名

@FeignClient(value = "servicea", qualifier = "IServiceASeata")
public interface IServiceASeata extends IservicewithCancel {
}

2、服務中拋異常后,Seata無法控制事務回滾
debug發(fā)現(xiàn)Seata拿不到異常,異常被feign拿走后直接拋出來了,所以需要重新實現(xiàn)feign的異常處理

public class FeignExceptionConfiguration {
    private static final Logger LOG = LoggerFactory.getLogger(FeignExceptionConfiguration.class);
    @Bean
    public ErrorDecoder errorDecoder() {
        return new UserErrorDecoder();
    }
    /**
     * 重新實現(xiàn)feign的異常處理,捕捉restful接口返回的json格式的異常信息
     *
     */
    public class UserErrorDecoder implements ErrorDecoder {

        public Exception decode(String methodKey, Response response) {
            Exception exception = null;
            ObjectMapper mapper = new ObjectMapper();
            //空屬性處理
            mapper.setSerializationInclusion(JsonSerialize.Inclusion.NON_EMPTY);
            //設置輸入時忽略在JSON字符串中存在但Java對象實際沒有的屬性
            mapper.configure(DeserializationConfig.Feature.FAIL_ON_UNKNOWN_PROPERTIES, false);
            //禁止使用int代表enum的order來反序列化enum
            mapper.configure(DeserializationConfig.Feature.FAIL_ON_NUMBERS_FOR_ENUMS, true);
            try {
                String json;
                //增加判空
                if(response.body() == null){
                    json = "{ \"body\": \"empty body\"}";
                }else {
                    json = Util.toString(response.body().asReader());
                }
                exception = new RuntimeException(json);
                if (StringUtils.isEmpty(json)) {
                    return null;
                }
                FeignFaildResult result = mapper.readValue(json, FeignFaildResult.class);
                // 業(yè)務異常包裝成自定義異常類MyException
                if (result.getStatus() != HttpStatus.OK.value()) {
                    exception = new MyException(result.getMessage(),result.getStatus());
                }
            } catch (IOException ex) {
                LOG.error(ex.getMessage(), ex);
            }
            return exception;
        }
    }
}
public class FeignFaildResult {
    private String message;
    private int status;

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }

    public int getStatus() {
        return status;
    }

    public void setStatus(int status) {
        this.status = status;
    }
}

然后在接口上指定這個處理:

@FeignClient(value = "servicea", qualifier = "IServiceASeata",configuration = FeignExceptionConfiguration.class)
public interface IServiceASeata extends IservicewithCancel {
}

參考:
http://www.itdecent.cn/p/b2a0168afeba
異常處理的代碼基本是原樣照搬,增加了對response.body的判空,不然我的場景會報空指針

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

友情鏈接更多精彩內(nèi)容