Feign Client 捕获自定义异常

    xiaoxiao2022-07-03  155

    在feign.hystrix.enable=false情况下,微服务提供方跑出自定义异常,微服务调用方怎么捕获这个自定义异常?

     

    分两种情况:

    1.如果微服务提供了接口声明,微服务调用工程引用了这个接口声明jar,有异常可以正常捕获。

    2.如果微服务提供方以RestController的方式对外提供服务(例如/api/login),则在微服务调用工程中要自定义错误解码处理。

    3.还有一种说法是利用@HystrixCommand,人家的原话是:

    Thanks. However, I think disabling Feign hystrix support (feign.hystrix.enabled=false) and using a @HystrixCommand on the caller method is simpler. That's what I'm doing now. – Abhijit Sarkar Nov 30 '16 at 8:56

    And you use ignroeExceptions of @HystrixCommand? – Roi Ezra Dec 1 '16 at 11:50

    Yes, using ignoreExceptions. – Abhijit Sarkar Dec 5 '16 at 3:37

     

     

     

    方法2使用举例:

     

    微服务提供方:

     

    @RestController

    @RequestMapping("api")

    public class UserController{

     

        @Autowired

        private UserFacadeService userFacadeService;

     

        @RequestMapping(vlaue="/login", method=RequestMethod.POST)

        public Token login(@RequestBody UserDto user) throws MyException{

            return userFacadeService.getLoginToken(user);

        }

     

    }

     

     

    微服务调用方:

     

    1.FeignClient中定义configuration采用自定义配置

    @FeignClient(name="serviceProvide", fallback=UserServiceImpl.class, configuration={KeepErrMsgConfiguration.class})

    public interface UserService{

     

        @RequestMapping(value="/api/login",  method=RequestMethod.POST)

        public Token login(@RequestBody UserDto user) throws MyException;

     

    }

     

     

    @Service

    public UserServiceImpl implements UserService{

        private final Logger log = LoggerFactory.getLogger(UserServiceImpl.class);

     

        @Override

        public Token login(@RequestBody UserDto user) throws MyException{

            log.error("调用{}异常:{}","serviceProvide:/api/login",user);

            return null;

        }

    }

     

    2.自定义错误解码

    import com.alibaba.fastjson.JSON;

    import com.test.common.exception.MyException;

    import feign.Response;

    import feign.Util;

    import feign.codec.ErrorDecoder;

    import org.apach.commons.langs3.StringUtils;

    import org.slf4j.Logger;

    import org.slf4j.LoggerFactory;

    import java.io.IOException;

    import java.util.Map;

     

    class MyErrDecoder implements ErrorDecoder{

        private final Logger log = LoggerFactory.getLogger(MyErrDecoder.class);

        private static final String ERR_CODE="500";

        private static final String SPLIT=":";

     

        @Override

        public Exception decode(String methodKey, Response response){

            Exception excepiton = null;

            try{

                //获取原始的返回内容

                String json = Utils.toString(response.body().asReader());

                //将返回的内容反序列化位Result,这里应根据自身项目做修改

                Map<String, Object> result = JSON.parseObject(json, Map.class);

                log.error("", result);

                String msg = result.get("msg");

                String code = String.valueOf(result.get("code"));

                exception = new RuntimeException(json);

                if(ERR_CODE.equals(code)){

                    if(StringUtils.isNotEmpty(msg)){

                        if(msg.contains(SPLIT)){

                            String []msgArr = msg.split(SPLIT);

                            exception = new MyException(msgArr[0], msgArr[1]);

                        }

                    }

                }

            }catch(IOException ex){

                log.error(ex.getMessage(), ex);

            }

        }

    }

     

    3.自定义错误捕捉配置

     

    import feign.codec.ErrorDecoder;

    import org.springframework.context.annotation.Bean;

     

    public class KeepErrMsgConfiguration{

        @Bean

        public ErrorDecoder errorDecoder(){

            return new MyErrDecoder();

        }

    }

     

     

     

     

     

    如果feign.hystrix.enable=true,则@FeignClient(name="serviceProvide", fallback=UserServiceImpl.class)中的fallback会被开启,但是也不会捕获到远端跑出的异常信息,要捕获异常需要使用到fallbackFactory 

    @FeignClient(name="serviceProvide", fallbackFactory = TestServiceFallback.class)

     

    import feign.hystrix.FallbackFactory;

    import org.apache.commons.lang3.StringUtils;

     

    @Component

    public class TestServiceFallback implements FallbackFactory<TestService> {

        private static final Logger LOG = LoggerFactory.getLogger(TestServiceFallback.class);

     

        public static final String ERR_MSG = "Test接口暂时不可用: ";

     

        @Override

        public TestService create(Throwable throwable) {

            String msg = throwable == null ? "" : throwable.getMessage();

            if (!StringUtils.isEmpty(msg)) {

                LOG.error(msg);

            }

            return new TestService() {

                @Override

                public String get(Integer id) {

                    return ResultBuilder.unsuccess(ERR_MSG + msg);

                }

            };

        }

    }

    最新回复(0)