中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Feign怎么調用接口解決內部異常的問題

發布時間:2021-06-24 09:08:28 來源:億速云 閱讀:679 作者:chen 欄目:開發技術

這篇文章主要介紹“Feign怎么調用接口解決內部異常的問題”,在日常操作中,相信很多人在Feign怎么調用接口解決內部異常的問題問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”Feign怎么調用接口解決內部異常的問題”的疑惑有所幫助!接下來,請跟著小編一起來學習吧!

問題描述:

當使用feign調用接口,出現400~500~的接口問題時。會出錯feign:FeignException。(因為是錯誤,只能用catch Throwable,不可使用catch Exception捕獲異常)導致程序無法繼續運行。

問題原因:

由于feign默認的錯誤處理類是FunFeignFallback會throw new AfsBaseExceptio導致外部無法捕獲異常。

package com.ruicar.afs.cloud.common.core.feign; 
import com.alibaba.fastjson.JSONObject;
import com.ruicar.afs.cloud.common.core.exception.AfsBaseException;
import com.ruicar.afs.cloud.common.core.util.IResponse;
import feign.FeignException;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;
import org.springframework.lang.Nullable; 
import java.lang.reflect.Method;
import java.util.Objects;
 
@Data
@AllArgsConstructor
@Slf4j
public class FunFeignFallback<T> implements MethodInterceptor {
    private final Class<T> targetType;
    private final String targetName;
    private final Throwable cause; 
    private static byte JSON_START = '{';
 
    @Nullable
    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        String errorMessage = cause.getMessage();
        if (!(cause instanceof FeignException)) {
            log.error("FunFeignFallback:[{}.{}] serviceId:[{}] message:[{}]", targetType.getName(), method.getName(), targetName, errorMessage);
            log.error("feign調用失敗", cause);
            return IResponse.fail("請求失敗,請稍后再試");
        }
        int status = ((FeignException.FeignClientException) this.cause).status();
        boolean isAuthFail = (status==426||status==403||status==401)&&"afs-auth".equals(targetName);
        FeignException exception = (FeignException) cause;
        if(isAuthFail){
            log.warn("授權失敗==========原始返回信息:[{}]",exception.contentUTF8());
        }else {
            log.error("FunFeignFallback:[{}.{}] serviceId:[{}] message:[{}]", targetType.getName(), method.getName(), targetName, errorMessage);
            log.error("", cause);
            log.error("原始返回信息{}",exception.contentUTF8());
        }
        if(method.getReturnType().equals(Void.class)){
            throw new AfsBaseException("接口調用失敗");
        }
        if(method.getReturnType().equals(IResponse.class)){
            if(exception instanceof FeignException.Forbidden){
                return IResponse.fail("沒有權限").setCode("403");
            }
            if(exception instanceof FeignException.NotFound){
                return IResponse.fail("請求路徑不存在").setCode("404");
            }
            if(exception instanceof FeignException.BadRequest){
                return IResponse.fail("參數錯誤").setCode("400");
            }
 
            if(exception.content()==null||exception.content().length==0){
                return IResponse.fail("請求失敗,請稍后再試");
            }
            if(JSON_START==exception.content()[0]){
                return JSONObject.parseObject(exception.content(),IResponse.class);
            }else{
                return IResponse.fail(exception.contentUTF8());
            }
        }else{
            try {
                if(method.getReturnType().equals(String.class)){
                    return exception.contentUTF8();
                }else if(method.getReturnType().equals(JSONObject.class)){
                    if(JSON_START==exception.content()[0]){
                        return JSONObject.parseObject(exception.content(), JSONObject.class);
                    }
                }else if(!method.getReturnType().equals(Object.class)){
                    return JSONObject.parseObject(exception.content(), method.getReturnType());
                }
                if(JSON_START==exception.content()[0]){
                    JSONObject jsonObject = JSONObject.parseObject(exception.content(), JSONObject.class);
                    if(jsonObject.containsKey("code")&&jsonObject.containsKey("msg")) {
                        return jsonObject.toJavaObject(IResponse.class);
                    }
                }
            }catch (Throwable e){}
            throw new AfsBaseException("接口調用失敗");
        }
    }
 
    @Override
    public boolean equals(Object o) {
        if (this == o) {
            return true;
        }
        if (o == null || getClass() != o.getClass()) {
            return false;
        }
        FunFeignFallback<?> that = (FunFeignFallback<?>) o;
        return targetType.equals(that.targetType);
    }
 
    @Override
    public int hashCode() {
        return Objects.hash(targetType); 
    } 
}

問題解決:自定義feignFallback異常處理:

1.自定義異常處理 InvoiceApiFeignFallbackFactory

package com.ruicar.afs.cloud.invoice.factory; 
import com.ruicar.afs.cloud.invoice.fallback.InvoiceApiFeignFallback;
import com.ruicar.afs.cloud.invoice.feign.InvoiceApiFeign;
import feign.hystrix.FallbackFactory;
import org.springframework.stereotype.Component;
 
@Component
public class InvoiceApiFeignFallbackFactory implements FallbackFactory<InvoiceApiFeign> {
    @Override
    public InvoiceApiFeign create(Throwable throwable) {
        InvoiceApiFeignFallback invoiceApiFeignFallback = new InvoiceApiFeignFallback();
        invoiceApiFeignFallback.setCause(throwable);
        return invoiceApiFeignFallback;
    }
}

2.feign調用 InvoiceApiFeignFallbackFactory

package com.ruicar.afs.cloud.invoice.feign; 
import com.alibaba.fastjson.JSONObject;
import com.ruicar.afs.cloud.common.core.feign.annotations.AfsFeignClear;
import com.ruicar.afs.cloud.invoice.dto.InvoiceCheckDto;
import com.ruicar.afs.cloud.invoice.factory.InvoiceApiFeignFallbackFactory;
import io.swagger.annotations.ApiOperation;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestHeader; 
import java.util.Map;
 
/**
 * @description: 發票驗證接口
 * @author: rongji.zhang
 * @date: 2020/8/14 10:32
 */
@FeignClient(name = "invoice", url = "${com.greatwall.systems.invoice-system.url}" ,fallbackFactory = InvoiceApiFeignFallbackFactory.class)
public interface InvoiceApiFeign {
    /**
     *
     * @param dto
     * @return
     */
    @ApiOperation("獲取業務數據API接口")
    @PostMapping(value = "/vi/check")
    @AfsFeignClear(true)//通過此注解防止添加內部token
    JSONObject InvoiceCheck(@RequestBody InvoiceCheckDto dto, @RequestHeader Map<String, String> headers);
}

3.實現自定義報錯處理

package com.ruicar.afs.cloud.invoice.fallback; 
import com.alibaba.fastjson.JSONObject;
import com.ruicar.afs.cloud.invoice.dto.InvoiceCheckDto;
import com.ruicar.afs.cloud.invoice.feign.InvoiceApiFeign;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component; 
import java.util.Map;
 
/**
 * @author Fzero
 * @date 2019-01-24
 */
@Slf4j
@Component
public class InvoiceApiFeignFallback implements InvoiceApiFeign { 
    @Setter
    private Throwable cause; 
    /**
     * @param dto
     * @param headers
     * @return
     */
    @Override
    public JSONObject InvoiceCheck(InvoiceCheckDto dto, Map<String, String> headers) {
        log.error("feign 接口調用失敗", cause);
        return null;
    }
}

Feign遠程調用失敗-----丟請求頭

@FeignClient("guli-cart")
public interface CartFenignService { 
    @GetMapping("/currentUserCartItems")
    List<OrderItemVo> getCurrentUserCartItems();
}// 這樣去掉接口時其實Feign在底層是一個全新的requst所有請求頭就沒有了

解決辦法使用Feign遠程掉用攔截器,在遠程請求是先創建攔截器

@Bean("requestInterceptor")
public RequestInterceptor requestInterceptor() {
    return new RequestInterceptor() {
        @Override
        public void apply(RequestTemplate template) { 
            /**
             * 把以前的Cookie放到新請求中去   原理就是運用了同一線程數據共享   ThreadLocal
             */
            ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
            HttpServletRequest request = attributes.getRequest(); 
            String cookie = request.getHeader("Cookie"); 
            template.header("Cookie", cookie);
        }
    };
}

但是上面的辦法只能解決同意線程問題,在多線程下還是會丟失請求頭

多線程下解決辦法:

RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();

把請求單獨拿出來給每個線程單獨

RequestContextHolder.setRequestAttributes(requestAttributes);

這樣就可以了~

到此,關于“Feign怎么調用接口解決內部異常的問題”的學習就結束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學習,快去試試吧!若想繼續學習更多相關知識,請繼續關注億速云網站,小編會繼續努力為大家帶來更多實用的文章!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

襄垣县| 伊川县| 诸暨市| 昌宁县| 渭源县| 开平市| 界首市| 洞头县| 曲靖市| 德州市| 桦甸市| 岑溪市| 叶城县| 荣成市| 察隅县| 通河县| 武穴市| 措勤县| 肃南| 镇远县| 镇沅| 辽中县| 绍兴市| 灌南县| 常山县| 宁安市| 潞城市| 大埔区| 拉孜县| 马山县| 招远市| 农安县| 青神县| 龙泉市| 宁强县| 肥城市| 巴马| 沾化县| 积石山| 视频| 成武县|