处理fegin的自定义的异常
spring boot 2.X.X
import feign.FeignException; import feign.RetryableException; import feign.codec.ErrorDecoder; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.springframework.context.annotation.Bean; @Slf4j public class MicroServiceFeignConfiguration { @Bean ErrorDecoder defaultErrorDecoder() { return (methodKey, response) -> { Exception rawFeignException = new ErrorDecoder.Default().decode(methodKey, response); if (rawFeignException instanceof RetryableException) { return rawFeignException; } FeignException feignException = (FeignException) rawFeignException; if (StringUtils.isBlank(feignException.contentUTF8())) { return feignException; } try { String errorBody = feignException.contentUTF8(); ExceptionHttpBody exceptionHttpBody = JsonUtil.parse(errorBody, ExceptionHttpBody.class); if (exceptionHttpBody.getException() != null) { try { Class<?> clazz = Class.forName(exceptionHttpBody.getException()); return (Exception) JsonUtil.convertValue(exceptionHttpBody, clazz); } catch (ClassNotFoundException e) { log.warn("class {} not in classpath", exceptionHttpBody.getException()); } } } catch (Exception e) { log.warn("Can not decode microservice exception", e); } return feignException; }; } }
springboot 1.x.x
import feign.FeignException import feign.Response import feign.RetryableException import feign.codec.ErrorDecoder import groovy.util.logging.Slf4j import org.apache.commons.lang.StringUtils import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Configuration @Configuration @Slf4j class FeignErrorConfig { @Bean ErrorDecoder feignErrorDecoder() { return new ErrorDecoder() { @Override Exception decode(String methodKey, Response response) { Exception rawFeignException = new ErrorDecoder.Default().decode(methodKey, response); if (rawFeignException instanceof RetryableException) { return rawFeignException; } FeignException feignException = (FeignException) rawFeignException; if (StringUtils.isBlank(feignException.getMessage())) { return feignException } try { ExceptionHttpBody exceptionHttpBody = JsonUtil.parse(feignException.getMessage().split('\n')[1], ExceptionHttpBody.class) if (exceptionHttpBody.getException() != null) { try { Class<?> clazz = Class.forName(exceptionHttpBody.getException()) return (Exception) JsonUtil.convertValue(exceptionHttpBody, clazz) } catch (ClassNotFoundException e) { log.warn("class {} not in classpath", exceptionHttpBody.getException()) } } } catch (Exception e) { log.warn("Can not decode microservice exception", e) } return feignException } } } }
配置请求的处理
mport feign.RequestInterceptor import feign.RequestTemplate import groovy.transform.CompileStatic import org.springframework.beans.factory.annotation.Value import org.springframework.cloud.netflix.feign.FeignClient import org.springframework.context.annotation.Bean import org.springframework.web.bind.annotation.GetMapping import org.springframework.web.bind.annotation.PathVariable @FeignClient(name = "xxx", url = '${funding.base-url}', configuration = [FundingClientFeignConfig]) @CompileStatic interface xxx { @GetMapping('/{xxxId}?idType=1') P2pLoanDetailResult getLoanDetail(@PathVariable('loanId') String loanId) class FundingClientFeignConfig { @Bean AuthRequestInterceptor authRequestInterceptor(@Value('${funding.token}') String token) { return new AuthRequestInterceptor(token) } class AuthRequestInterceptor implements RequestInterceptor { String token AuthRequestInterceptor(String token) { this.token = token } @Override void apply(RequestTemplate template) { template.header('Authorization', "Bearer ${token}") } } } }
配置
@Configuration @Slf4j @CompileStatic class FeignConfig { @Bean @ConditionalOnMissingBean Retryer feignRetryer() { return Retryer.NEVER_RETRY } @Bean @Scope("prototype") @ConditionalOnMissingBean Feign.Builder feignBuilder(Retryer retryer, @Value("spring.profile") String profile) { return Feign.builder().invocationHandlerFactory(new InvocationHandlerFactoryImpl((profile))).retryer(retryer) } @Bean Client feignClient(CachingSpringLoadBalancerFactory cachingFactory, SpringClientFactory clientFactory) { return new LoadBalancerFeignClient(new LoggingClient(null, null, { false }), cachingFactory, clientFactory) } @Bean Decoder feignDecoder() { MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter(JsonUtil.COMMON_OBJECT_MAPPER) converter.supportedMediaTypes = [MediaType.ALL, MediaType.APPLICATION_JSON, new MediaType("application", "*+json")] ObjectFactory<HttpMessageConverters> objectFactory = { new HttpMessageConverters(converter) } return new ResponseEntityDecoder(new SpringDecoder(objectFactory)) } }
log