注入容器过程
一、EnableFeignClients 入口
开启Feign使用注解EnableFeignClients ,进入EnableFeignClients ,
与大多数集成Spring的框架一样,使用@Import方式实现ImportBeanDefinitionRegistrar进行对接(Mybatis等也是如此)。
另外可以通过spring.factories查看入口
org.springframework.cloud.openfeign.hateoas.FeignHalAutoConfiguration,\
org.springframework.cloud.openfeign.FeignAutoConfiguration,\
org.springframework.cloud.openfeign.encoding.FeignAcceptGzipEncodingAutoConfiguration,\
org.springframework.cloud.openfeign.encoding.FeignContentGzipEncodingAutoConfiguration,\
org.springframework.cloud.openfeign.loadbalancer.FeignLoadBalancerAutoConfiguration
此处FeignClientsRegistrar实现了ImportBeanDefinitionRegistrar接口。
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
@Documented
//Spring bean注入方式之一
@Import({FeignClientsRegistrar.class})
public @interface EnableFeignClients {
String[] value() default {};
String[] basePackages() default {};
Class<?>[] basePackageClasses() default {};
Class<?>[] defaultConfiguration() default {};
Class<?>[] clients() default {};
}
二、FeignClientsRegistrar 注入Bean
注入bean主要有一下几步:
1、获取注解信息,扫包下的@FeignClient 接口
2、根据扫描的信息,生成bean定义
3、创建FeignClientFactoryBean(FactoryBean实现)类信息
4、把bean定义注入到Spring容器(回调中通过FactortBean.getObject创建真实bean即代理对象)
class FeignClientsRegistrar implements ImportBeanDefinitionRegistrar, ResourceLoaderAware, EnvironmentAware {
...
//Spring注册@EnableFeignClients 后会回调此处(详细了解@Import)
public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {
//注入配置类FeignClientSpecification
this.registerDefaultConfiguration(metadata, registry);
//注入扫描包下的@FeignClient的接口
this.registerFeignClients(metadata, registry);
}
//注入配置类FeignClientSpecification
private void registerDefaultConfiguration(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {
Map<String, Object> defaultAttrs = metadata.getAnnotationAttributes(EnableFeignClients.class.getName(), true);
if (defaultAttrs != null && defaultAttrs.containsKey("defaultConfiguration")) {
String name;
if (metadata.hasEnclosingClass()) {
name = "default." + metadata.getEnclosingClassName();
} else {
name = "default." + metadata.getClassName();
}
this.registerClientConfiguration(registry, name, defaultAttrs.get("defaultConfiguration"));
}
}
//循环注入@FeignClient 接口bean
public void registerFeignClients(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {
LinkedHashSet<BeanDefinition> candidateComponents = new LinkedHashSet();
Map<String, Object> attrs = metadata.getAnnotationAttributes(EnableFeignClients.class.getName());
Class<?>[] clients = attrs == null ? null : (Class[])((Class[])attrs.get("clients"));
if (clients != null && clients.length != 0) {
Class[] var12 = clients;
int var14 = clients.length;
for(int var16 = 0; var16 < var14; ++var16) {
Class<?> clazz = var12[var16];
candidateComponents.add(new AnnotatedGenericBeanDefinition(clazz));
}
} else {
ClassPathScanningCandidateComponentProvider scanner = this.getScanner();
scanner.setResourceLoader(this.resourceLoader);
scanner.addIncludeFilter(new AnnotationTypeFilter(FeignClient.class));
Set<String> basePackages = this.getBasePackages(metadata);
Iterator var8 = basePackages.iterator();
while(var8.hasNext()) {
String basePackage = (String)var8.next();
candidateComponents.addAll(scanner.findCandidateComponents(basePackage));
}
}
Iterator var13 = candidateComponents.iterator();
while(var13.hasNext()) {
BeanDefinition candidateComponent = (BeanDefinition)var13.next();
if (candidateComponent instanceof AnnotatedBeanDefinition) {
AnnotatedBeanDefinition beanDefinition = (AnnotatedBeanDefinition)candidateComponent;
AnnotationMetadata annotationMetadata = beanDefinition.getMetadata();
Assert.isTrue(annotationMetadata.isInterface(), "@FeignClient can only be specified on an interface");
Map<String, Object> attributes = annotationMetadata.getAnnotationAttributes(FeignClient.class.getCanonicalName());
String name = this.getClientName(attributes);
//注入配置类FeignClientSpecification(一个@FeignClient对应一个)
this.registerClientConfiguration(registry, name, attributes.get("configuration"));
//注入@FeignClient接口代理bean
this.registerFeignClient(registry, annotationMetadata, attributes);
}
}
}
//注入@FeignClient (与mybatis类似,有细微不同,mybatis直接注入FactoryBean),然后在FactoryBean.getObject() 获取动态代理类注入到Spring容器中
private void registerFeignClient(BeanDefinitionRegistry registry, AnnotationMetadata annotationMetadata, Map<String, Object> attributes) {
//@FeignClient 接口
String className = annotationMetadata.getClassName();
Class clazz = ClassUtils.resolveClassName(className, (ClassLoader)null);
ConfigurableBeanFactory beanFactory = registry instanceof ConfigurableBeanFactory ? (ConfigurableBeanFactory)registry : null;
String contextId = this.getContextId(beanFactory, attributes);
String name = this.getName(attributes);
//FeignClientFactoryBean 实现FactoryBean,FactoryBean是一种特殊的bean,在注入到Spring时Spring会通过getObjct获取真实的Bean,此类后续会分析。
FeignClientFactoryBean factoryBean = new FeignClientFactoryBean();
factoryBean.setBeanFactory(beanFactory);
factoryBean.setName(name);
factoryBean.setContextId(contextId);
//类文件
factoryBean.setType(clazz);
factoryBean.setRefreshableClient(this.isClientRefreshEnabled());
//生成bean定义,在回调中生成bean
BeanDefinitionBuilder definition = BeanDefinitionBuilder.genericBeanDefinition(clazz, () -> {
factoryBean.setUrl(this.getUrl(beanFactory, attributes));
factoryBean.setPath(this.getPath(beanFactory, attributes));
factoryBean.setDecode404(Boolean.parseBoolean(String.valueOf(attributes.get("decode404"))));
Object fallback = attributes.get("fallback");
if (fallback != null) {
factoryBean.setFallback(fallback instanceof Class ? (Class)fallback : ClassUtils.resolveClassName(fallback.toString(), (ClassLoader)null));
}
Object fallbackFactory = attributes.get("fallbackFactory");
if (fallbackFactory != null) {
factoryBean.setFallbackFactory(fallbackFactory instanceof Class ? (Class)fallbackFactory : ClassUtils.resolveClassName(fallbackFactory.toString(), (ClassLoader)null));
}
//此处获取真实的bean(该bean其实是一个Proxy java动态代理)
return factoryBean.getObject();
});
definition.setAutowireMode(2);
//设置懒加载
definition.setLazyInit(true);
this.validate(attributes);
//构建起模式获取 bean定义
AbstractBeanDefinition beanDefinition = definition.getBeanDefinition();
beanDefinition.setAttribute("factoryBeanObjectType", className);
beanDefinition.setAttribute("feignClientsRegistrarFactoryBean", factoryBean);
boolean primary = (Boolean)attributes.get("primary");
beanDefinition.setPrimary(primary);
String[] qualifiers = this.getQualifiers(attributes);
if (ObjectUtils.isEmpty(qualifiers)) {
qualifiers = new String[]{contextId + "FeignClient"};
}
//bean定义包装器
BeanDefinitionHolder holder = new BeanDefinitionHolder(beanDefinition, className, qualifiers);
//注入Spring容器
BeanDefinitionReaderUtils.registerBeanDefinition(holder, registry);
this.registerOptionsBeanDefinition(registry, contextId);
}
//获取扫描的包名
protected Set<String> getBasePackages(AnnotationMetadata importingClassMetadata) {
Map<String, Object> attributes = importingClassMetadata.getAnnotationAttributes(EnableFeignClients.class.getCanonicalName());
Set<String> basePackages = new HashSet();
String[] var4 = (String[])((String[])attributes.get("value"));
int var5 = var4.length;
int var6;
String pkg;
for(var6 = 0; var6 < var5; ++var6) {
pkg = var4[var6];
if (StringUtils.hasText(pkg)) {
basePackages.add(pkg);
}
}
var4 = (String[])((String[])attributes.get("basePackages"));
var5 = var4.length;
for(var6 = 0; var6 < var5; ++var6) {
pkg = var4[var6];
if (StringUtils.hasText(pkg)) {
basePackages.add(pkg);
}
}
Class[] var8 = (Class[])((Class[])attributes.get("basePackageClasses"));
var5 = var8.length;
for(var6 = 0; var6 < var5; ++var6) {
Class<?> clazz = var8[var6];
basePackages.add(ClassUtils.getPackageName(clazz));
}
if (basePackages.isEmpty()) {
basePackages.add(ClassUtils.getPackageName(importingClassMetadata.getClassName()));
}
return basePackages;
}
//获取feign的中实例id
private String getClientName(Map<String, Object> client) {
if (client == null) {
return null;
} else {
String value = (String)client.get("contextId");
if (!StringUtils.hasText(value)) {
value = (String)client.get("value");
}
if (!StringUtils.hasText(value)) {
value = (String)client.get("name");
}
if (!StringUtils.hasText(value)) {
value = (String)client.get("serviceId");
}
if (StringUtils.hasText(value)) {
return value;
} else {
throw new IllegalStateException("Either 'name' or 'value' must be provided in @" + FeignClient.class.getSimpleName());
}
}
}
//注入FeignClientSpecification,后续在构建FeignContext 时需要用到
private void registerClientConfiguration(BeanDefinitionRegistry registry, Object name, Object configuration) {
//Bean定义构建创建FeignClientSpecification
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(FeignClientSpecification.class);
builder.addConstructorArgValue(name);
builder.addConstructorArgValue(configuration);
//注入FeignClientSpecification
registry.registerBeanDefinition(name + "." + FeignClientSpecification.class.getSimpleName(), builder.getBeanDefinition());
}
}
三、FeignClientFactoryBean实现bean创建
1、通过FeignContext 构造Builder
2、如果@FeignClient中url不为空,那么走直接Client.Default直接http调用
3、如果@FeignClient中url为空,那么走负载均衡逻辑
public class FeignClientFactoryBean implements FactoryBean<Object>, InitializingBean, ApplicationContextAware, BeanFactoryAware {
...
//获取目标代理对象
<T> T getTarget() {
//FeignAutoConfiguration中自动注入了FeignContext
FeignContext context = this.beanFactory != null ? (FeignContext)this.beanFactory.getBean(FeignContext.class) : (FeignContext)this.applicationContext.getBean(FeignContext.class);
//此处是通过FeignContext构建Builder,一系列配置信息
Builder builder = this.feign(context);
//如果@FeignClient中配置了url,那么就要直接访问http请求,不会走注册中心负载均衡逻辑。
if (StringUtils.hasText(this.url)) {
if (StringUtils.hasText(this.url) && !this.url.startsWith("http")) {
this.url = "http://" + this.url;
}
String url = this.url + this.cleanPath();
//获取调用Client
Client client = (Client)this.getOptional(context, Client.class);
if (client != null) {
//如果是FeignBlockingLoadBalancerClient获取Delegate(这个就是Client.Default 这个就是通过HttpUrlConnection做http请求)
if (client instanceof FeignBlockingLoadBalancerClient) {
//获取Client.Default
client = ((FeignBlockingLoadBalancerClient)client).getDelegate();
}
//同理FeignBlockingLoadBalancerClient
if (client instanceof RetryableFeignBlockingLoadBalancerClient) {
//获取Client.Default
client = ((RetryableFeignBlockingLoadBalancerClient)client).getDelegate();
}
builder.client(client);
}
Targeter targeter = (Targeter)this.get(context, Targeter.class);
//实际是通过client调用
return targeter.target(this, builder, context, new HardCodedTarget(this.type, this.name, url));
} else {
//如果@FeignClient中没有配置url,那么会走注册中心负载均衡逻辑。
if (this.url != null && LOG.isWarnEnabled()) {
LOG.warn("The provided URL is empty. Will try picking an instance via load-balancing.");
} else if (LOG.isDebugEnabled()) {
LOG.debug("URL not provided. Will use LoadBalancer.");
}
if (!this.name.startsWith("http")) {
this.url = "http://" + this.name;
} else {
this.url = this.name;
}
this.url = this.url + this.cleanPath();
//负载均衡逻辑。
return this.loadBalance(builder, context, new HardCodedTarget(this.type, this.name, this.url));
}
}
//负载均衡逻辑。会获取注册中心对应的服务,通过负载均衡策略获取对应实例,从而获得本次http访问的真实url
protected <T> T loadBalance(Builder builder, FeignContext context, HardCodedTarget<T> target) {
//获取http请求访问的类,实际请求http通过此类
Client client = (Client)this.getOptional(context, Client.class);
if (client != null) {
//构建期中加入http访问类
builder.client(client);
//此处会根据FeignContext进入DefaultTarget(暂时看其中细节,细节较多)
Targeter targeter = (Targeter)this.get(context, Targeter.class);
//创建动态代理对象
return targeter.target(this, builder, context, target);
} else {
throw new IllegalStateException("No Feign Client for loadBalancing defined. Did you forget to include spring-cloud-starter-loadbalancer?");
}
}
}
四、Feign类构建器构造Feign实现类
1、构造ReflectiveFeign,该对象包含了很多基本信息,如Encoder(编码器),Decoder(解码器),RequestInterceptor(拦截器)
2、newInstance() ,构造动态代理对现象
public abstract class Feign {
public static class Builder {
...
//newInstance()构建动态代理对象
public <T> T target(Target<T> target) {
return this.build().newInstance(target);
}
//创建一个Feign对象即(ReflectiveFeign),通过此对象构建动态代理对象,此处会带入所有访问调用的拦截器,编码解码,协议等配置信息
public Feign build() {
Client client = (Client)Capability.enrich(this.client, this.capabilities);
Retryer retryer = (Retryer)Capability.enrich(this.retryer, this.capabilities);
List<RequestInterceptor> requestInterceptors = (List)this.requestInterceptors.stream().map((ri) -> {
return (RequestInterceptor)Capability.enrich(ri, this.capabilities);
}).collect(Collectors.toList());
Logger logger = (Logger)Capability.enrich(this.logger, this.capabilities);
Contract contract = (Contract)Capability.enrich(this.contract, this.capabilities);
Options options = (Options)Capability.enrich(this.options, this.capabilities);
Encoder encoder = (Encoder)Capability.enrich(this.encoder, this.capabilities);
Decoder decoder = (Decoder)Capability.enrich(this.decoder, this.capabilities);
InvocationHandlerFactory invocationHandlerFactory = (InvocationHandlerFactory)Capability.enrich(this.invocationHandlerFactory, this.capabilities);
QueryMapEncoder queryMapEncoder = (QueryMapEncoder)Capability.enrich(this.queryMapEncoder, this.capabilities);
Factory synchronousMethodHandlerFactory = new Factory(client, retryer, requestInterceptors, logger, this.logLevel, this.decode404, this.closeAfterDecode, this.propagationPolicy, this.forceDecoding);
ParseHandlersByName handlersByName = new ParseHandlersByName(contract, options, encoder, decoder, queryMapEncoder, this.errorDecoder, synchronousMethodHandlerFactory);
return new ReflectiveFeign(handlersByName, invocationHandlerFactory, queryMapEncoder);
}
}
}
}
五、ReflectiveFeign创建动态代理对象
1、构造MethodHandler,方法处理器
2、获取InvocationHandler (FeignInvocationHandler)
3、创建Java动态代理对象(Proxy.newProxyInstance(target.type().getClassLoader(), new Class[]{target.type()}, handler);)
public class ReflectiveFeign extends Feign {
public <T> T newInstance(Target<T> target) {
//获取方法处理器,每一个feign方法对应一个MethodHandler,bean调用时进入InvocationHandler 后通过方法名找到对应MethodHandler进行处理
Map<String, MethodHandler> nameToHandler = this.targetToHandlersByName.apply(target);
Map<Method, MethodHandler> methodToHandler = new LinkedHashMap();
List<DefaultMethodHandler> defaultMethodHandlers = new LinkedList();
Method[] var5 = target.type().getMethods();
int var6 = var5.length;
for(int var7 = 0; var7 < var6; ++var7) {
Method method = var5[var7];
if (method.getDeclaringClass() != Object.class) {
if (Util.isDefault(method)) {
DefaultMethodHandler handler = new DefaultMethodHandler(method);
defaultMethodHandlers.add(handler);
methodToHandler.put(method, handler);
} else {
methodToHandler.put(method, nameToHandler.get(Feign.configKey(target.type(), method)));
}
}
}
//动态代理处理器(调用feign都会进入此handler即FeignInvocationHandler)
InvocationHandler handler = this.factory.create(target, methodToHandler);
//动态代理对象
T proxy = Proxy.newProxyInstance(target.type().getClassLoader(), new Class[]{target.type()}, handler);
Iterator var12 = defaultMethodHandlers.iterator();
while(var12.hasNext()) {
DefaultMethodHandler defaultMethodHandler = (DefaultMethodHandler)var12.next();
defaultMethodHandler.bindTo(proxy);
}
return proxy;
}
}
调用过程
FeignInvocationHandler代理所有调用
接口调用一般都是通过动态代理实现,和mybatis一样,都是使用的java的动态代理。feign使用的是静态内部类FeignInvocationHandler。
MethodHandler 有三种:
1、SynchronousMethodHandler 处理正常远程调用逻辑,
2、DefaultMethodHandler处理接口default方法逻辑
3、匿名内部类处理异常逻辑
static class FeignInvocationHandler implements InvocationHandler {
private final Target target;
//每个方法的处理器
private final Map<Method, MethodHandler> dispatch;
FeignInvocationHandler(Target target, Map<Method, MethodHandler> dispatch) {
this.target = (Target)Util.checkNotNull(target, "target", new Object[0]);
this.dispatch = (Map)Util.checkNotNull(dispatch, "dispatch for %s", new Object[]{target});
}
//调用代理,所有调用在此处代理
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//个人认为此处代码不是特别好,就我自己而言认为应该把 equals,hashCode,toString分别用if处理,主干逻辑this.dispatch.get(method)).invoke(args) 放在else中,这样代码可读性更好
if (!"equals".equals(method.getName())) {
if ("hashCode".equals(method.getName())) {
return this.hashCode();
} else {
return "toString".equals(method.getName()) ? this.toString() : ((MethodHandler)this.dispatch.get(method)).invoke(args);
}
} else {
try {
Object otherHandler = args.length > 0 && args[0] != null ? Proxy.getInvocationHandler(args[0]) : null;
return this.equals(otherHandler);
} catch (IllegalArgumentException var5) {
return false;
}
}
}
...
}
SynchronousMethodHandler 处理每个方法
通过ReflectiveFeign.ParseHandlersByName 代码可以看出创建MethodHandler 使用的 SynchronousMethodHandler .Factory
1、Client调用
2、失败后根据配置重试
final class SynchronousMethodHandler implements MethodHandler {
...
//调用逻辑处理
public Object invoke(Object[] argv) throws Throwable {
RequestTemplate template = this.buildTemplateFromArgs.create(argv);
Options options = this.findOptions(argv);
Retryer retryer = this.retryer.clone();
//开始调用,失败后根据配置重试
while(true) {
try {
//执行远程调用,并解码
return this.executeAndDecode(template, options);
} catch (RetryableException var9) {
RetryableException e = var9;
try {
//判断是否继续重试
retryer.continueOrPropagate(e);
} catch (RetryableException var8) {
Throwable cause = var8.getCause();
if (this.propagationPolicy == ExceptionPropagationPolicy.UNWRAP && cause != null) {
throw cause;
}
throw var8;
}
if (this.logLevel != Level.NONE) {
this.logger.logRetry(this.metadata.configKey(), this.logLevel);
}
}
}
}
//真实执行调用并解码代码
Object executeAndDecode(RequestTemplate template, Options options) throws Throwable {
//生成请求对象(此处的请求只是选择实例使用)
Request request = this.targetRequest(template);
if (this.logLevel != Level.NONE) {
this.logger.logRequest(this.metadata.configKey(), this.logLevel, request);
}
long start = System.nanoTime();
Response response;
try {
//执行远程调用返回调用结果Response
response = this.client.execute(request, options);
response = response.toBuilder().request(request).requestTemplate(template).build();
} catch (IOException var12) {
if (this.logLevel != Level.NONE) {
this.logger.logIOException(this.metadata.configKey(), this.logLevel, var12, this.elapsedTime(start));
}
throw FeignException.errorExecuting(request, var12);
}
long elapsedTime = TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - start);
if (this.decoder != null) {
//通过Decoder解码Response为@FeignClient方法中的返回的对象
return this.decoder.decode(response, this.metadata.returnType());
} else {
CompletableFuture<Object> resultFuture = new CompletableFuture();
this.asyncResponseHandler.handleResponse(resultFuture, this.metadata.configKey(), response, this.metadata.returnType(), elapsedTime);
try {
if (!resultFuture.isDone()) {
throw new IllegalStateException("Response handling not done");
} else {
return resultFuture.join();
}
} catch (CompletionException var13) {
Throwable cause = var13.getCause();
if (cause != null) {
throw cause;
} else {
throw var13;
}
}
}
}
...
}
FeignBlockingLoadBalancerClient 处理调用
1、通过负载均衡获取实例对象(如果没有配置OkHttpClient或ApacheClient,并且自己也没有配置Client,那么就会用DefaultFeignLoadBalancerConfiguration中配置的Client(FeignBlockingLoadBalancerClient ))
2、如果获取不到ServiceInstance,那么返回503Response
3、如果获取到ServiceInstance,那么获取真实url后,开始请求(实际是通过Client.Default调用处理)。
public class FeignBlockingLoadBalancerClient implements Client {
...
//具体执行
public Response execute(Request request, Options options) throws IOException {
//此处originalUri为分布式实例组成的。不是真实url
URI originalUri = URI.create(request.url());
//服务id
String serviceId = originalUri.getHost();
Assert.state(serviceId != null, "Request URI does not contain a valid hostname: " + originalUri);
String hint = this.getHint(serviceId);
DefaultRequest<RequestDataContext> lbRequest = new DefaultRequest(new RequestDataContext(LoadBalancerUtils.buildRequestData(request), hint));
Set<LoadBalancerLifecycle> supportedLifecycleProcessors = LoadBalancerLifecycleValidator.getSupportedLifecycleProcessors(this.loadBalancerClientFactory.getInstances(serviceId, LoadBalancerLifecycle.class), RequestDataContext.class, ResponseData.class, ServiceInstance.class);
supportedLifecycleProcessors.forEach((lifecycle) -> {
lifecycle.onStart(lbRequest);
});
//通过负载均衡选择实例(Spring默认有轮询和随机两种负载均衡器)
ServiceInstance instance = this.loadBalancerClient.choose(serviceId, lbRequest);
org.springframework.cloud.client.loadbalancer.Response<ServiceInstance> lbResponse = new DefaultResponse(instance);
String message;
//实例为空那么报错
if (instance == null) {
message = "Load balancer does not contain an instance for the service " + serviceId;
if (LOG.isWarnEnabled()) {
LOG.warn(message);
}
supportedLifecycleProcessors.forEach((lifecycle) -> {
lifecycle.onComplete(new CompletionContext(Status.DISCARD, lbRequest, lbResponse));
});
//错误码HttpStatus.SERVICE_UNAVAILABLE 503
return Response.builder().request(request).status(HttpStatus.SERVICE_UNAVAILABLE.value()).body(message, StandardCharsets.UTF_8).build();
} else {
//实例存在,找到真实url(域名或ip 与端口组成的url)
message = this.loadBalancerClient.reconstructURI(instance, originalUri).toString();
//组建请求参数
Request newRequest = this.buildRequest(request, message);
//远程调用返回响应对象(delegate为真实处理Client)
return LoadBalancerUtils.executeWithLoadBalancerLifecycleProcessing(this.delegate, options, newRequest, lbRequest, lbResponse, supportedLifecycleProcessors);
}
}
...
}
Client.Default 处理http远程调用
1、通过请求对象获取HttpURLConnection
2、请求后组装为Response
public static class Default implements Client {
...
public Response execute(Request request, Options options) throws IOException {
//使用HttpURLConnection 进行http请求
HttpURLConnection connection = this.convertAndSend(request, options);
//请求后组装为Response对象
return this.convertResponse(connection, request);
}
Response convertResponse(HttpURLConnection connection, Request request) throws IOException {
int status = connection.getResponseCode();
String reason = connection.getResponseMessage();
if (status < 0) {
throw new IOException(String.format("Invalid status(%s) executing %s %s", status, connection.getRequestMethod(), connection.getURL()));
} else {
Map<String, Collection<String>> headers = new LinkedHashMap();
Iterator var6 = connection.getHeaderFields().entrySet().iterator();
while(var6.hasNext()) {
Entry<String, List<String>> field = (Entry)var6.next();
if (field.getKey() != null) {
headers.put(field.getKey(), field.getValue());
}
}
Integer length = connection.getContentLength();
if (length == -1) {
length = null;
}
InputStream stream;
if (status >= 400) {
stream = connection.getErrorStream();
} else {
stream = connection.getInputStream();
}
return Response.builder().status(status).reason(reason).headers(headers).request(request).body(stream, length).build();
}
}