亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

Feign調(diào)用接口解決處理內(nèi)部異常的問(wèn)題

 更新時(shí)間:2021年06月23日 15:49:57   作者:萌中芢  
這篇文章主要介紹了Feign調(diào)用接口解決處理內(nèi)部異常的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教

問(wèn)題描述:

當(dāng)使用feign調(diào)用接口,出現(xiàn)400~500~的接口問(wèn)題時(shí)。會(huì)出錯(cuò)feign:FeignException。(因?yàn)槭清e(cuò)誤,只能用catch Throwable,不可使用catch Exception捕獲異常)導(dǎo)致程序無(wú)法繼續(xù)運(yùn)行。

問(wèn)題原因:

由于feign默認(rèn)的錯(cuò)誤處理類是FunFeignFallback會(huì)throw new AfsBaseExceptio導(dǎo)致外部無(wú)法捕獲異常。

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調(diào)用失敗", cause);
            return IResponse.fail("請(qǐng)求失敗,請(qǐng)稍后再試");
        }
        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("授權(quán)失敗==========原始返回信息:[{}]",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("接口調(diào)用失敗");
        }
        if(method.getReturnType().equals(IResponse.class)){
            if(exception instanceof FeignException.Forbidden){
                return IResponse.fail("沒有權(quán)限").setCode("403");
            }
            if(exception instanceof FeignException.NotFound){
                return IResponse.fail("請(qǐng)求路徑不存在").setCode("404");
            }
            if(exception instanceof FeignException.BadRequest){
                return IResponse.fail("參數(shù)錯(cuò)誤").setCode("400");
            }
 
            if(exception.content()==null||exception.content().length==0){
                return IResponse.fail("請(qǐng)求失敗,請(qǐng)稍后再試");
            }
            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("接口調(diào)用失敗");
        }
    }
 
    @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); 
    } 
}

問(wèn)題解決:自定義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調(diào)用 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: 發(fā)票驗(yàn)證接口
 * @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("獲取業(yè)務(wù)數(shù)據(jù)API接口")
    @PostMapping(value = "/vi/check")
    @AfsFeignClear(true)//通過(guò)此注解防止添加內(nèi)部token
    JSONObject InvoiceCheck(@RequestBody InvoiceCheckDto dto, @RequestHeader Map<String, String> headers);
}

3.實(shí)現(xiàn)自定義報(bào)錯(cuò)處理

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 接口調(diào)用失敗", cause);
        return null;
    }
}

Feign遠(yuǎn)程調(diào)用失敗-----丟請(qǐng)求頭

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

解決辦法使用Feign遠(yuǎn)程掉用攔截器,在遠(yuǎn)程請(qǐng)求是先創(chuàng)建攔截器

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

但是上面的辦法只能解決同意線程問(wèn)題,在多線程下還是會(huì)丟失請(qǐng)求頭

多線程下解決辦法:

RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();

把請(qǐng)求單獨(dú)拿出來(lái)給每個(gè)線程單獨(dú)

RequestContextHolder.setRequestAttributes(requestAttributes);

這樣就可以了~

以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • Java StringUtils字符串分割轉(zhuǎn)數(shù)組的實(shí)現(xiàn)

    Java StringUtils字符串分割轉(zhuǎn)數(shù)組的實(shí)現(xiàn)

    這篇文章主要介紹了Java StringUtils字符串分割轉(zhuǎn)數(shù)組的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-09-09
  • Java設(shè)計(jì)模式編程中的工廠方法模式和抽象工廠模式

    Java設(shè)計(jì)模式編程中的工廠方法模式和抽象工廠模式

    這篇文章主要介紹了Java設(shè)計(jì)模式編程中的工廠方法模式和抽象工廠模式,設(shè)計(jì)模式的建立有利于團(tuán)隊(duì)協(xié)作時(shí)代碼的共同維護(hù),需要的朋友可以參考下
    2016-01-01
  • SpringBoot調(diào)用Poi-tl實(shí)現(xiàn)渲染數(shù)據(jù)并生成Word文檔

    SpringBoot調(diào)用Poi-tl實(shí)現(xiàn)渲染數(shù)據(jù)并生成Word文檔

    這篇文章主要為大家詳細(xì)介紹了SpringBoot如何調(diào)用Poi-tl實(shí)現(xiàn)渲染數(shù)據(jù)并生成Word文檔,文中的示例代碼講解詳細(xì),有需要的小伙伴可以了解下
    2023-09-09
  • Java多線程中的Exchanger應(yīng)用簡(jiǎn)析

    Java多線程中的Exchanger應(yīng)用簡(jiǎn)析

    這篇文章主要介紹了Java多線程中的Exchanger應(yīng)用簡(jiǎn)析,Exchanger提供了一個(gè)同步點(diǎn)exchange方法,兩個(gè)線程調(diào)用exchange方法時(shí),無(wú)論調(diào)用時(shí)間先后,兩個(gè)線程會(huì)互相等到線程到達(dá)exchange方法調(diào)用點(diǎn),此時(shí)兩個(gè)線程可以交換數(shù)據(jù),將本線程產(chǎn)出數(shù)據(jù)傳遞給對(duì)方,需要的朋友可以參考下
    2023-12-12
  • Java線程的start方法回調(diào)run方法的操作技巧

    Java線程的start方法回調(diào)run方法的操作技巧

    面試過(guò)程中經(jīng)常會(huì)被面試官問(wèn)到為什么我們調(diào)用start()方法時(shí)會(huì)執(zhí)行run()方法,為什么不能直接調(diào)用run()方法,問(wèn)的一頭霧水,今天小編給大家介紹下Java線程的start方法回調(diào)run方法的操作技巧,需要的朋友參考下吧
    2017-11-11
  • Springboot下RedisTemplate的兩種序列化方式實(shí)例詳解

    Springboot下RedisTemplate的兩種序列化方式實(shí)例詳解

    這篇文章主要介紹了Springboot下RedisTemplate的兩種序列化方式,通過(guò)定義一個(gè)配置類,自定義RedisTemplate的序列化方式,結(jié)合實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-09-09
  • Java調(diào)用WebService接口作測(cè)試

    Java調(diào)用WebService接口作測(cè)試

    這篇文章主要介紹了Java調(diào)用WebService接口作測(cè)試,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-11-11
  • LinkedList學(xué)習(xí)示例模擬堆棧與隊(duì)列數(shù)據(jù)結(jié)構(gòu)

    LinkedList學(xué)習(xí)示例模擬堆棧與隊(duì)列數(shù)據(jù)結(jié)構(gòu)

    這篇文章主要介紹了LinkedList學(xué)習(xí)示例,模擬一個(gè)堆棧與隊(duì)列數(shù)據(jù)結(jié)構(gòu),大家參考使用吧
    2014-01-01
  • 淺談Java自定義類加載器及JVM自帶的類加載器之間的交互關(guān)系

    淺談Java自定義類加載器及JVM自帶的類加載器之間的交互關(guān)系

    這篇文章主要介紹了淺談Java自定義類加載器及JVM自帶的類加載器之間的交互關(guān)系,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2021-02-02
  • Java?GUI實(shí)現(xiàn)學(xué)生成績(jī)管理系統(tǒng)

    Java?GUI實(shí)現(xiàn)學(xué)生成績(jī)管理系統(tǒng)

    這篇文章主要為大家詳細(xì)介紹了Java?GUI實(shí)現(xiàn)學(xué)生成績(jī)管理系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-01-01

最新評(píng)論