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 호출 Invoice ApiFeignFallback Factory

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);
이렇게 하면 돼~
이상 은 개인 적 인 경험 이 므 로 여러분 에 게 참고 가 되 기 를 바 랍 니 다.여러분 들 도 저 희 를 많이 응원 해 주시 기 바 랍 니 다.

좋은 웹페이지 즐겨찾기