RestTemplate实践 (5)

注意:HttpEntity有4个构造方法,无参构造,只设置请求body,只设置headers,既设置headers又设置body

/** * Create a new, empty {@code HttpEntity}. */ protected HttpEntity() { this(null, null); } /** * Create a new {@code HttpEntity} with the given body and no headers. * @param body the entity body */ public HttpEntity(T body) { this(body, null); } /** * Create a new {@code HttpEntity} with the given headers and no body. * @param headers the entity headers */ public HttpEntity(MultiValueMap<String, String> headers) { this(null, headers); } /** * Create a new {@code HttpEntity} with the given body and headers. * @param body the entity body * @param headers the entity headers */ public HttpEntity(T body, MultiValueMap<String, String> headers) { this.body = body; HttpHeaders tempHeaders = new HttpHeaders(); if (headers != null) { tempHeaders.putAll(headers); } this.headers = HttpHeaders.readOnlyHttpHeaders(tempHeaders); } 处理响应头信息

使用RestTemplate中xxxForEntity()的方法,会返回ResponseEntity,可以从中获取到响应状态码,响应头和body等信息

HttpHeaders requestHeaders = new HttpHeaders(); requestHeaders.set("MyRequestHeader", "MyValue"); HttpEntity requestEntity = new HttpEntity(requestHeaders); HttpEntity<String> response = template.exchange( "http://example.com/hotels/{hotel}", HttpMethod.GET, requestEntity, String.class, "42"); //response相关信息 String responseHeader = response.getHeaders().getFirst("MyResponseHeader"); String body = response.getBody(); 2、ClientHttpRequestFactory

ClientHttpRequestFactory是Spring定义的一个接口,其用于生产org.springframework.http.client.ClientHttpRequest对象,RestTemplate只是模板类,抽象了很多调用方法,而底层真正使用何种框架发送HTTP请求是通过ClientHttpRequestFactory指定的

接口定义

/** * Factory for {@link ClientHttpRequest} objects. * Requests are created by the {@link #createRequest(URI, HttpMethod)} method. * ClientHttpRequest对象的工厂 * * @author Arjen Poutsma * @since 3.0 */ public interface ClientHttpRequestFactory { /** * Create a new {@link ClientHttpRequest} for the specified URI and HTTP method. * <p>The returned request can be written to, and then executed by calling * {@link ClientHttpRequest#execute()}. * 使用指定的URI和HTTP方法新建一个ClientHttpRequest对象 * 可以修改返回的request,并通过ClientHttpRequest的execute()方法执行调用 * 即调用的逻辑也被Spring封装到ClientHttpRequest中 * * @param uri the URI to create a request for * @param httpMethod the HTTP method to execute * @return the created request * @throws IOException in case of I/O errors */ ClientHttpRequest createRequest(URI uri, HttpMethod httpMethod) throws IOException; }

RestTemplate可以在构造时设置ClientHttpRequestFactory,也可以通过setRequestFactory()方法设置

构造方法设置: /** * Create a new instance of the {@link RestTemplate} based on the given {@link ClientHttpRequestFactory}. * @param requestFactory HTTP request factory to use * @see org.springframework.http.client.SimpleClientHttpRequestFactory * @see org.springframework.http.client.HttpComponentsClientHttpRequestFactory */ public RestTemplate(ClientHttpRequestFactory requestFactory) { this(); setRequestFactory(requestFactory); }

可以看到上面注释中已经给出了Spring的两种ClientHttpRequestFactory的实现类SimpleClientHttpRequestFactory和HttpComponentsClientHttpRequestFactory

SimpleClientHttpRequestFactory

如果什么都不设置,RestTemplate默认使用的是SimpleClientHttpRequestFactory,其内部使用的是jdk的java.net.HttpURLConnection创建底层连接,默认是没有连接池的,connectTimeout和readTimeout都是 -1,即没有超时时间

public class SimpleClientHttpRequestFactory implements ClientHttpRequestFactory, AsyncClientHttpRequestFactory { 。。。。。。 private int connectTimeout = -1; private int readTimeout = -1; //创建Request @Override public ClientHttpRequest createRequest(URI uri, HttpMethod httpMethod) throws IOException { HttpURLConnection connection = openConnection(uri.toURL(), this.proxy); prepareConnection(connection, httpMethod.name()); //bufferRequestBody默认为true if (this.bufferRequestBody) { return new SimpleBufferingClientHttpRequest(connection, this.outputStreaming); } else { return new SimpleStreamingClientHttpRequest(connection, this.chunkSize, this.outputStreaming); } } /** * Opens and returns a connection to the given URL. * 打开并返回一个指定URL的连接 * <p>The default implementation uses the given {@linkplain #setProxy(java.net.Proxy) proxy} - * if any - to open a connection. * @param url the URL to open a connection to * @param proxy the proxy to use, may be {@code null} * @return the opened connection 返回类型为 java.net.HttpURLConnection * @throws IOException in case of I/O errors */ protected HttpURLConnection openConnection(URL url, Proxy proxy) throws IOException { URLConnection urlConnection = (proxy != null ? url.openConnection(proxy) : url.openConnection()); if (!HttpURLConnection.class.isInstance(urlConnection)) { throw new IllegalStateException("HttpURLConnection required for [" + url + "] but got: " + urlConnection); } return (HttpURLConnection) urlConnection; } /** * Template method for preparing the given {@link HttpURLConnection}. * <p>The default implementation prepares the connection for input and output, and sets the HTTP method. * @param connection the connection to prepare * @param httpMethod the HTTP request method ({@code GET}, {@code POST}, etc.) * @throws IOException in case of I/O errors */ protected void prepareConnection(HttpURLConnection connection, String httpMethod) throws IOException { //如果connectTimeout大于等于0,设置连接超时时间 if (this.connectTimeout >= 0) { connection.setConnectTimeout(this.connectTimeout); } //如果readTimeout大于等于0,设置读超时时间 if (this.readTimeout >= 0) { connection.setReadTimeout(this.readTimeout); } connection.setDoInput(true); if ("GET".equals(httpMethod)) { connection.setInstanceFollowRedirects(true); } else { connection.setInstanceFollowRedirects(false); } if ("POST".equals(httpMethod) || "PUT".equals(httpMethod) || "PATCH".equals(httpMethod) || "DELETE".equals(httpMethod)) { connection.setDoOutput(true); } else { connection.setDoOutput(false); } connection.setRequestMethod(httpMethod); } 。。。。。。 } HttpComponentsClientHttpRequestFactory

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zwyjgd.html