此抽象类在AbstractClientHttpRequest基础之上添加了缓冲功能,可以保存要发送给服务器的数据,然后一块发送。看这一句:
ClientHttpResponse result = executeInternal(headers, bytes);也是一个executeInternal方法,不过参数不同,它也是一个抽象方法。进入方法,到达org.springframework.http.client.InterceptingClientHttpRequest类
protected final ClientHttpResponse executeInternal(HttpHeaders headers, byte[] bufferedOutput) throws IOException { InterceptingRequestExecution requestExecution = new InterceptingRequestExecution(); return requestExecution.execute(this, bufferedOutput); }实例化了一个带拦截器的请求执行对象InterceptingRequestExecution,进入看一看。
public ClientHttpResponse execute(HttpRequest request, final byte[] body) throws IOException { // 如果有拦截器,则执行拦截器并返回结果 if (this.iterator.hasNext()) { ClientHttpRequestInterceptor nextInterceptor = this.iterator.next(); return nextInterceptor.intercept(request, body, this); } else { // 如果没有拦截器,则通过requestFactory创建request对象并执行 ClientHttpRequest delegate = requestFactory.createRequest(request.getURI(), request.getMethod()); for (Map.Entry<String, List<String>> entry : request.getHeaders().entrySet()) { List<String> values = entry.getValue(); for (String value : values) { delegate.getHeaders().add(entry.getKey(), value); } } if (body.length > 0) { if (delegate instanceof StreamingHttpOutputMessage) { StreamingHttpOutputMessage streamingOutputMessage = (StreamingHttpOutputMessage) delegate; streamingOutputMessage.setBody(new StreamingHttpOutputMessage.Body() { @Override public void writeTo(final OutputStream outputStream) throws IOException { StreamUtils.copy(body, outputStream); } }); } else { StreamUtils.copy(body, delegate.getBody()); } } return delegate.execute(); } }看一下RestTemplate的配置:
RestTemplateBuilder builder = new RestTemplateBuilder(); return builder .setConnectTimeout(customConfig.getRest().getConnectTimeOut()) .setReadTimeout(customConfig.getRest().getReadTimeout()) .interceptors(restTemplateLogInterceptor) .errorHandler(new ThrowErrorHandler()) .build(); }可以看到配置了连接超时,读超时,拦截器,和错误处理器。
看一下拦截器的实现:
可以看到当返回码不是200时,抛出异常。还记得RestTemplate中的doExecute方法吧,此处如果抛出异常,虽然会执行doExecute方法中的finally代码,但由于返回的response为null(其实是有response的),没有关闭response,所以这里不能抛出异常,如果确实想抛出异常,可以在错误处理器errorHandler中抛出,这样确保response能正常返回和关闭。
RestTemplate源码部分解析 如何决定使用哪一个底层http框架知道了原因,我们再来看一下RestTemplate在什么时候决定使用什么http框架。其实在通过RestTemplateBuilder实例化RestTemplate对象时就决定了。
看一下RestTemplateBuilder的build方法
可以看到在实例化RestTemplate对象之后,进行配置。
public <T extends RestTemplate> T configure(T restTemplate) { // 配置requestFactory configureRequestFactory(restTemplate); // 配置消息转换器 if (!CollectionUtils.isEmpty(this.messageConverters)) { restTemplate.setMessageConverters( new ArrayList<HttpMessageConverter<?>>(this.messageConverters)); } //配置uri模板处理器 if (this.uriTemplateHandler != null) { restTemplate.setUriTemplateHandler(this.uriTemplateHandler); } //配置错误处理器 if (this.errorHandler != null) { restTemplate.setErrorHandler(this.errorHandler); } // 设置根路径(一般为'http://www.likecs.com/') if (this.rootUri != null) { RootUriTemplateHandler.addTo(restTemplate, this.rootUri); } // 配置登录验证 if (this.basicAuthorization != null) { restTemplate.getInterceptors().add(this.basicAuthorization); } //配置自定义restTemplate器 if (!CollectionUtils.isEmpty(this.restTemplateCustomizers)) { for (RestTemplateCustomizer customizer : this.restTemplateCustomizers) { customizer.customize(restTemplate); } } //配置拦截器 restTemplate.getInterceptors().addAll(this.interceptors); return restTemplate; }