一、三者的對(duì)比
HttpClient:代碼復(fù)雜,還得操心資源回收等。代碼很復(fù)雜,冗余代碼多,不建議直接使用。 RestTemplate: 是 Spring 提供的用于訪問(wèn)Rest服務(wù)的客戶端, RestTemplate 提供了多種便捷訪問(wèn)遠(yuǎn)程Http服務(wù)的方法,能夠大大提高客戶端的編寫(xiě)效率。 okhttp:OkHttp是一個(gè)高效的HTTP客戶端,允許所有同一個(gè)主機(jī)地址的請(qǐng)求共享同一個(gè)socket連接;連接池減少請(qǐng)求延時(shí);透明的GZIP壓縮減少響應(yīng)數(shù)據(jù)的大小;緩存響應(yīng)內(nèi)容,避免一些完全重復(fù)的請(qǐng)求
二、HttpClient的使用
HttpClient是Apache Jakarta Common下的子項(xiàng)目,用來(lái)提供高效的、最新的、功能豐富的支持HTTP協(xié)議的客戶端編程工具包,并且它支持HTTP協(xié)議最新的版本和建議。HttpClient已經(jīng)應(yīng)用在很多的項(xiàng)目中,比如Apache Jakarta上很著名的另外兩個(gè)開(kāi)源項(xiàng)目Cactus和HTMLUnit都使用了HttpClient。
使用HttpClient發(fā)送請(qǐng)求、接收響應(yīng)很簡(jiǎn)單,一般需要如下幾步即可。
創(chuàng)建HttpClient對(duì)象。 創(chuàng)建請(qǐng)求方法的實(shí)例,并指定請(qǐng)求URL。如果需要發(fā)送GET請(qǐng)求,創(chuàng)建HttpGet對(duì)象;如果需要發(fā)送POST請(qǐng)求,創(chuàng)建HttpPost對(duì)象。 如果需要發(fā)送請(qǐng)求參數(shù),可調(diào)用HttpGet、HttpPost共同的setParams(HetpParams params)方法來(lái)添加請(qǐng)求參數(shù);對(duì)于HttpPost對(duì)象而言,也可調(diào)用setEntity(HttpEntity entity)方法來(lái)設(shè)置請(qǐng)求參數(shù)。 調(diào)用HttpClient對(duì)象的execute(HttpUriRequest request)發(fā)送請(qǐng)求,該方法返回一個(gè)HttpResponse。 調(diào)用HttpResponse的getAllHeaders()、getHeaders(String name)等方法可獲取服務(wù)器的響應(yīng)頭;調(diào)用HttpResponse的getEntity()方法可獲取HttpEntity對(duì)象,該對(duì)象包裝了服務(wù)器的響應(yīng)內(nèi)容。程序可通過(guò)該對(duì)象獲取服務(wù)器的響應(yīng)內(nèi)容。 釋放連接。無(wú)論執(zhí)行方法是否成功,都必須釋放連接
< dependency> < groupId> org.apache.httpcomponents
</ groupId> < artifactId> httpclient
</ artifactId> < version> 4.5.13
</ version> </ dependency> < dependency> < groupId> com.fasterxml.jackson.core
</ groupId> < artifactId> jackson-databind
</ artifactId> < version> 2.13.0
</ version> </ dependency>
public class HttpClientExample_get { public static void main ( String [ ] args
) throws IOException { HttpGet request
= new HttpGet ( "https://httpbin.org/get" ) ; request
. addHeader ( "custom-key" , "test" ) ; request
. addHeader ( HttpHeaders . USER_AGENT
, "Googlebot" ) ; try ( CloseableHttpClient httpClient
= HttpClients . createDefault ( ) ; CloseableHttpResponse response
= httpClient
. execute ( request
) ) { System . out
. println ( response
. getProtocolVersion ( ) ) ; System . out
. println ( response
. getStatusLine ( ) . getStatusCode ( ) ) ; System . out
. println ( response
. getStatusLine ( ) . getReasonPhrase ( ) ) ; System . out
. println ( response
. getStatusLine ( ) . toString ( ) ) ; HttpEntity entity
= response
. getEntity ( ) ; if ( entity
!= null ) { String result
= EntityUtils . toString ( entity
) ; System . out
. println ( result
) ; } } }
}
public class HttpClientExample_post { public static void main ( String [ ] args
) { try { String result
= sendPOST ( "https://httpbin.org/post" ) ; System . out
. println ( result
) ; } catch ( IOException e
) { e
. printStackTrace ( ) ; } } private static String sendPOST ( String url
) throws IOException { String result
= "" ; HttpPost post
= new HttpPost ( url
) ; List < NameValuePair > urlParameters
= new ArrayList < > ( ) ; urlParameters
. add ( new BasicNameValuePair ( "username" , "abc" ) ) ; urlParameters
. add ( new BasicNameValuePair ( "password" , "123" ) ) ; urlParameters
. add ( new BasicNameValuePair ( "custom" , "secret" ) ) ; post
. setEntity ( new UrlEncodedFormEntity ( urlParameters
) ) ; try ( CloseableHttpClient httpClient
= HttpClients . createDefault ( ) ; CloseableHttpResponse response
= httpClient
. execute ( post
) ) { result
= EntityUtils . toString ( response
. getEntity ( ) ) ; } return result
; }
}
public class HttpClientExample_JsonPost { public static void main ( String [ ] args
) { try { String result
= sendPOST ( "https://httpbin.org/post" ) ; System . out
. println ( result
) ; } catch ( IOException e
) { e
. printStackTrace ( ) ; } } private static String sendPOST ( String url
) throws IOException { String result
= "" ; HttpPost post
= new HttpPost ( url
) ; String json
= "{" + "\"name\":\"mkyong\"," + "\"notes\":\"hello\"" + "}" ; post
. setEntity ( new StringEntity ( json
) ) ; try ( CloseableHttpClient httpClient
= HttpClients . createDefault ( ) ; CloseableHttpResponse response
= httpClient
. execute ( post
) ) { result
= EntityUtils . toString ( response
. getEntity ( ) ) ; } return result
; }
}
public class HttpClientAuthentication { public static void main ( String [ ] args
) throws IOException { HttpGet request
= new HttpGet ( "http://localhost:8080/books" ) ; CredentialsProvider provider
= new BasicCredentialsProvider ( ) ; provider
. setCredentials ( AuthScope . ANY
, new UsernamePasswordCredentials ( "user" , "password" ) ) ; try ( CloseableHttpClient httpClient
= HttpClientBuilder . create ( ) . setDefaultCredentialsProvider ( provider
) . build ( ) ; CloseableHttpResponse response
= httpClient
. execute ( request
) ) { System . out
. println ( response
. getStatusLine ( ) . getStatusCode ( ) ) ; HttpEntity entity
= response
. getEntity ( ) ; if ( entity
!= null ) { String result
= EntityUtils . toString ( entity
) ; System . out
. println ( result
) ; } } }
}
參考文章 參考文章
三、OKHttp的使用
提供了對(duì) HTTP/2 和 SPDY 的支持,這使得對(duì)同一個(gè)主機(jī)發(fā)出的所有請(qǐng)求都可以共享相同的套接字連接 如果 HTTP/2 和 SPDY 不可用,OkHttp會(huì)使用連接池來(lái)復(fù)用連接以提高效率 提供了對(duì) GZIP 的默認(rèn)支持來(lái)降低傳輸內(nèi)容的大小 提供了對(duì) HTTP 響應(yīng)的緩存機(jī)制,可以避免不必要的網(wǎng)絡(luò)請(qǐng)求 當(dāng)網(wǎng)絡(luò)出現(xiàn)問(wèn)題時(shí),OkHttp 會(huì)自動(dòng)重試一個(gè)主機(jī)的多個(gè) IP 地址
Requests(請(qǐng)求): 每一個(gè)HTTP請(qǐng)求中都應(yīng)該包含一個(gè)URL,一個(gè)GET或POST方法以及Header或其他參數(shù),當(dāng)然還可以含特定內(nèi)容類(lèi)型的數(shù)據(jù)流。 Responses(響應(yīng)): 響應(yīng)則包含一個(gè)回復(fù)代碼(200代表成功,404代表未找到),Header和定制可選的body。
pom.xml
< dependency> < groupId> com.squareup.okhttp3
</ groupId> < artifactId> okhttp
</ artifactId> < version> 4.9.1
</ version>
</ dependency>
創(chuàng)建OkHttpClient實(shí)例
簡(jiǎn)單來(lái)說(shuō),通過(guò)OkHttpClient可以發(fā)送一個(gè)Http請(qǐng)求,并讀取該Http請(qǐng)求的響應(yīng),它是一個(gè)生產(chǎn)Call的工廠。此外,受益于一個(gè)共享的響應(yīng)緩存/線程池/復(fù)用的連接等因素,絕大多數(shù)應(yīng)用使用一個(gè)OkHttpClient實(shí)例,便可以滿足整個(gè)應(yīng)用的Http請(qǐng)求。
三種創(chuàng)建實(shí)例的方法:
創(chuàng)建一個(gè)默認(rèn)配置OkHttpClient,可以使用默認(rèn)的構(gòu)造函數(shù)。 通過(guò)new OkHttpClient.Builder()方法來(lái)一步一步配置一個(gè)OkHttpClient實(shí)例。 如果要求使用現(xiàn)有的實(shí)例,可以通過(guò)newBuilder()方法來(lái)進(jìn)行構(gòu)造。
OkHttpClient client
= new OkHttpClient ( ) ;
OkHttpClient clientWith30sTimeout
= client. Builder( ) . readTimeout ( 30 , TimeUnit . SECONDS
) . build ( ) ;
OkHttpClient client
= client
. newBuilder ( ) . build ( ) ;
看一下OkHttpClient的源碼,會(huì)發(fā)現(xiàn)緩存/代理等等需求,一應(yīng)俱全的按照類(lèi)封裝到了Builder中。
Dispatcher dispatcher
;
Proxy proxy
;
List < Protocol > protocols
;
List < ConnectionSpec > connectionSpecs
;
final List < Interceptor > interceptors
= new ArrayList < > ( ) ;
final List < Interceptor > networkInterceptors
= new ArrayList < > ( ) ;
ProxySelector proxySelector
;
CookieJar cookieJar
;
Cache cache
;
InternalCache internalCache
;
SocketFactory socketFactory
;
SSLSocketFactory sslSocketFactory
;
HostnameVerifier hostnameVerifier
;
CertificatePinner certificatePinner
;
Authenticator proxyAuthenticator
;
Authenticator authenticator
;
ConnectionPool connectionPool
;
Dns dns
;
boolean followSslRedirects
;
boolean followRedirects
;
boolean retryOnConnectionFailure
;
int connectTimeout
;
int readTimeout
;
int writeTimeout
;
okhttp–get
OkHttpClient client
= new OkHttpClient ( ) ;
String run ( String url
) throws IOException { Request request
= new Request. Builder ( ) . url ( url
) . build ( ) ; Response response
= client
. newCall ( request
) . execute ( ) ; return response
. body ( ) . string ( ) ;
}
簡(jiǎn)單看一下Request類(lèi),可以發(fā)現(xiàn)它代表一個(gè)Http請(qǐng)求,需要注意的是Request一旦build()之后,便不可修改。主要通過(guò)new Request.Builder()來(lái)一步一步構(gòu)造的。看一下Builder的代碼。
public Builder ( ) { this . method
= "GET" ; this . headers
= new Headers. Builder ( ) ;
}
此外還創(chuàng)建了頭信息。Headers類(lèi)中是通過(guò)List<String> namesAndValues = new ArrayList<>(20),來(lái)存放頭信息的,一開(kāi)始我也很納悶,頭信息都是一對(duì)一對(duì)的為什么要用List,看一下源碼發(fā)現(xiàn),在存取的時(shí)候都是將索引+2或者-2。并且頭信息可以存在多個(gè)相同的Key信息。
跟到newCall()方法中發(fā)現(xiàn),又使用OkHttpClient實(shí)例和Request的實(shí)例,一起構(gòu)造了一個(gè)RealCall的實(shí)例。RealCall類(lèi)簡(jiǎn)單做了一個(gè)托管并通過(guò)Dispather類(lèi)對(duì)請(qǐng)求進(jìn)行分發(fā)和執(zhí)行,實(shí)際開(kāi)啟線程發(fā)起請(qǐng)求的方法就在這個(gè)類(lèi)中。隨后又調(diào)用execute()方法,拿到了一個(gè)響應(yīng)。這個(gè)execute()方法,實(shí)際上執(zhí)行的就是RealCall中的execute()方法,最后調(diào)用了Dispatcher的execute()方法。
Response代表一個(gè)Http的響應(yīng),這個(gè)類(lèi)的實(shí)例不可修改。
一個(gè)簡(jiǎn)單的Get請(qǐng)求和說(shuō)明就結(jié)束了
okhttp–post
public static final MediaType JSON
= MediaType . parse ( "application/json; charset=utf-8" ) ;
OkHttpClient client
= new OkHttpClient ( ) ;
String post ( String url
, String json
) throws IOException { RequestBody body
= RequestBody . create ( JSON
, json
) ; Request request
= new Request. Builder ( ) . url ( url
) . post ( body
) . build ( ) ; Response response
= client
. newCall ( request
) . execute ( ) ; return response
. body ( ) . string ( ) ;
}
MediaType用于描述Http請(qǐng)求和響應(yīng)體的內(nèi)容類(lèi)型,也就是Content-Type。一次請(qǐng)求就是向目標(biāo)服務(wù)器發(fā)送一串文本。什么樣的文本?有下面結(jié)構(gòu)的文本。
POST
/ meme
. php
/ home
/ user
/ login HTTP
/ 1.1
Host : 114.215 .86 .90
Cache - Control : no
- cache
Postman - Token : bd243d6b
- da03
- 902f - 0 a2c
- 8e9377f 6f 6 ed
Content - Type : application
/ x
- www
- form
- urlencodedtel
= 13637829200 & password
= 123456
例如,MediaType.parse(“application/json; charset=utf-8”);這個(gè)就帶表請(qǐng)求體的類(lèi)型為JSON格式的。定義好數(shù)據(jù)類(lèi)型,還要將其變?yōu)檎?qǐng)求體,最后通過(guò)post()方法,隨請(qǐng)求一并發(fā)出。
OkHttp也可以通過(guò)POST方式把鍵值對(duì)數(shù)據(jù)傳送到服務(wù)器
OkHttpClient client
= new OkHttpClient ( ) ;
String post ( String url
, String json
) throws IOException { RequestBody formBody
= new FormBody. Builder ( ) . add ( "platform" , "android" ) . add ( "name" , "bug" ) . add ( "subject" , "XXXXXXXXXXXXXXX" ) . build ( ) ; Request request
= new Request. Builder ( ) . url ( url
) . post ( formBody
) . build ( ) ; Response response
= client
. newCall ( request
) . execute ( ) ; if ( response
. isSuccessful ( ) ) { return response
. body ( ) . string ( ) ; } else { throw new IOException ( "Unexpected code " + response
) ; }
}
HTTP頭部的設(shè)置和讀取
HTTP 頭的數(shù)據(jù)結(jié)構(gòu)是 Map<String, List<String>>類(lèi)型。也就是說(shuō),對(duì)于每個(gè) HTTP 頭,可能有多個(gè)值。但是大部分 HTTP 頭都只有一個(gè)值,只有少部分 HTTP 頭允許多個(gè)值。至于name的取值說(shuō)明,可以查看這個(gè)請(qǐng)求頭大全。
OkHttp的處理方式是:
使用header(name,value)來(lái)設(shè)置HTTP頭的唯一值,如果請(qǐng)求中已經(jīng)存在響應(yīng)的信息那么直接替換掉。 使用addHeader(name,value)來(lái)補(bǔ)充新值,如果請(qǐng)求頭中已經(jīng)存在name的name-value,那么還會(huì)繼續(xù)添加,請(qǐng)求頭中便會(huì)存在多個(gè)name相同而value不同的“鍵值對(duì)”。 使用header(name)讀取唯一值或多個(gè)值的最后一個(gè)值 使用headers(name)獲取所有值
OkHttpClient client
= new OkHttpClient ( ) ;
Request request
= new Request. Builder ( ) . url ( "https://github.com" ) . header ( "User-Agent" , "My super agent" ) . addHeader ( "Accept" , "text/html" ) . build ( ) ;
Response response
= client
. newCall ( request
) . execute ( ) ;
if ( ! response
. isSuccessful ( ) ) { throw new IOException ( "服務(wù)器端錯(cuò)誤: " + response
) ;
}
System . out
. println ( response
. header ( "Server" ) ) ;
System . out
. println ( response
. headers ( "Set-Cookie" ) ) ;
參考文章
四、RestTemplate的使用
RestTemplate 是從 Spring3.0 開(kāi)始支持的一個(gè) HTTP 請(qǐng)求工具,它提供了常見(jiàn)的REST請(qǐng)求方案的模版,例如 GET 請(qǐng)求、POST 請(qǐng)求、PUT 請(qǐng)求、DELETE 請(qǐng)求以及一些通用的請(qǐng)求執(zhí)行方法 exchange 以及 execute。RestTemplate 繼承自 InterceptingHttpAccessor 并且實(shí)現(xiàn)了 RestOperations 接口,其中 RestOperations 接口定義了基本的 RESTful 操作,這些操作在 RestTemplate 中都得到了實(shí)現(xiàn)。
< dependency> < groupId> org.springframework.boot
</ groupId> < artifactId> spring-boot-starter-web
</ artifactId>
</ dependency>
RestTemplate restTemplate
= new RestTemplate ( ) ;
RestTemplate restTemplate
= new RestTemplate ( new HttpComponentsClientHttpRequestFactory ( ) ) ;
RestTemplate restTemplate
= new RestTemplate ( new OkHttp3ClientHttpRequestFactory ( ) ) ;
當(dāng)然如果想使用OkHttp的話也得引入相應(yīng)的jar包
默認(rèn)情況下RestTemplate自動(dòng)幫我們注冊(cè)了一組HttpMessageConverter用來(lái)處理一些不同的contentType的請(qǐng)求。如果現(xiàn)有的轉(zhuǎn)換器不能滿足你的需求,你還可以實(shí)現(xiàn)org.springframework.http.converter.HttpMessageConverter接口自己寫(xiě)一個(gè)。詳情參考官方api。其他相關(guān)的配置,也可以在官方文檔中查看。當(dāng)然,對(duì)于一個(gè)請(qǐng)求來(lái)說(shuō),超期時(shí)間,請(qǐng)求連接時(shí)間等都是必不可少的參數(shù),為了更好的適應(yīng)業(yè)務(wù)需求,所以可以自己修改restTemplate的配置。
RestTemplate提供了六種常用的HTTP方法實(shí)現(xiàn)遠(yuǎn)程服務(wù)調(diào)用,RestTemplate的方法名遵循一定的命名規(guī)范,第一部分表示用哪種HTTP方法調(diào)用(get,post),第二部分表示返回類(lèi)型。
getForObject – 發(fā)送GET請(qǐng)求,將HTTP response轉(zhuǎn)換成一個(gè)指定的object對(duì)象
postForEntity –發(fā)送POST請(qǐng)求,將給定的對(duì)象封裝到HTTP請(qǐng)求體,返回類(lèi)型是一個(gè)HttpEntity對(duì)象(包含響應(yīng)數(shù)據(jù)和響應(yīng)頭)
每個(gè)HTTP方法對(duì)應(yīng)的RestTemplate方法都有3種。其中2種的url參數(shù)為字符串,URI參數(shù)變量分別是Object數(shù)組和Map,第3種使用URI類(lèi)型作為參數(shù)
exchange 和execute方法比上面列出的其它方法(如getForObject、postForEntity等)使用范圍更廣,允許調(diào)用者指定HTTP請(qǐng)求的方法(GET、POST、PUT等),并且可以支持像HTTP PATCH(部分更新)。
做好了準(zhǔn)備工作,先來(lái)看使用 RestTemplate 發(fā)送 GET 請(qǐng)求。在 RestTemplate 中,和 GET 請(qǐng)求相關(guān)的方法有如下幾個(gè):
public class TemplateGet { public static void main ( String [ ] args
) throws UnsupportedEncodingException { RequestConfig config
= RequestConfig . custom ( ) . setConnectionRequestTimeout ( 10000 ) . setConnectTimeout ( 10000 ) . setSocketTimeout ( 30000 ) . build ( ) ; HttpClientBuilder builder
= HttpClientBuilder . create ( ) . setDefaultRequestConfig ( config
) . setRetryHandler ( new DefaultHttpRequestRetryHandler ( 3 , false ) ) ; HttpClient httpClient
= builder
. build ( ) ; ClientHttpRequestFactory requestFactory
= new HttpComponentsClientHttpRequestFactory ( httpClient
) ; RestTemplate restTemplate
= new RestTemplate ( requestFactory
) ; String forObject
= restTemplate
. getForObject ( "https://httpbin.org/get" , String . class ) ; ResponseEntity < String > forEntity
= restTemplate
. getForEntity ( "https://httpbin.org/get" , String . class ) ; ResponseEntity < String > responseEntity
= restTemplate
. exchange ( "https://httpbin.org/get" , HttpMethod . GET
, null , String . class ) ; System . out
. println ( "響應(yīng)頭--start" ) ; forEntity
. getHeaders ( ) . entrySet ( ) . forEach ( System . out
:: println ) ; System . out
. println ( "響應(yīng)頭--end" ) ; assert forObject
!= null ; byte [ ] bytes
= forObject
. getBytes ( StandardCharsets . UTF_8
) ; String res
= new String ( bytes
, StandardCharsets . UTF_8
) ; System . out
. println ( res
) ; System . out
. println ( forEntity
. getBody ( ) ) ; System . out
. println ( responseEntity
. getBody ( ) ) ; }
}
json形式
public class TemplatePostJson { public static void main ( String [ ] args
) { RequestConfig config
= RequestConfig . custom ( ) . setConnectionRequestTimeout ( 10000 ) . setConnectTimeout ( 10000 ) . setSocketTimeout ( 30000 ) . build ( ) ; HttpClientBuilder builder
= HttpClientBuilder . create ( ) . setDefaultRequestConfig ( config
) . setRetryHandler ( new DefaultHttpRequestRetryHandler ( 3 , false ) ) ; HttpClient httpClient
= builder
. build ( ) ; ClientHttpRequestFactory requestFactory
= new HttpComponentsClientHttpRequestFactory ( httpClient
) ; RestTemplate restTemplate
= new RestTemplate ( requestFactory
) ; String url
= "https://httpbin.org/post" ; String json
= "{" + "\"name\":\"mkyong\"," + "\"notes\":\"hello\"" + "}" ; HttpHeaders headers
= new HttpHeaders ( ) ; headers
. setContentType ( MediaType . APPLICATION_JSON
) ; headers
. set ( "CustomHeader" , "myCustom" ) ; HttpEntity < String > httpEntity
= new HttpEntity < > ( json
, headers
) ; ResponseEntity < String > responseEntity
= restTemplate
. exchange ( url
, HttpMethod . POST
, httpEntity
, String . class ) ; String s
= restTemplate
. postForObject ( url
, httpEntity
, String . class ) ; ResponseEntity < String > stringResponseEntity
= restTemplate
. postForEntity ( url
, httpEntity
, String . class ) ; assert s
!= null ; byte [ ] bytes
= s
. getBytes ( StandardCharsets . UTF_8
) ; String body
= new String ( bytes
, StandardCharsets . UTF_8
) ; System . out
. println ( body
) ; System . out
. println ( responseEntity
. getBody ( ) ) ; System . out
. println ( "響應(yīng)頭--start" ) ; stringResponseEntity
. getHeaders ( ) . entrySet ( ) . forEach ( System . out
:: println ) ; System . out
. println ( "響應(yīng)頭--end" ) ; }
}
map(表單)形式
public class TemplatePostMap { public static void main ( String [ ] args
) { RequestConfig config
= RequestConfig . custom ( ) . setConnectionRequestTimeout ( 10000 ) . setConnectTimeout ( 10000 ) . setSocketTimeout ( 30000 ) . build ( ) ; HttpClientBuilder builder
= HttpClientBuilder . create ( ) . setDefaultRequestConfig ( config
) . setRetryHandler ( new DefaultHttpRequestRetryHandler ( 3 , false ) ) ; HttpClient httpClient
= builder
. build ( ) ; ClientHttpRequestFactory requestFactory
= new HttpComponentsClientHttpRequestFactory ( httpClient
) ; RestTemplate restTemplate
= new RestTemplate ( requestFactory
) ; String url
= "https://httpbin.org/post" ; MultiValueMap < Object , Object > map
= new LinkedMultiValueMap < > ( ) ; map
. add ( "aa" , "aa" ) ; map
. add ( "bb" , "bb" ) ; map
. add ( "cc" , "cc" ) ; HttpHeaders headers
= new HttpHeaders ( ) ; headers
. setContentType ( MediaType . APPLICATION_JSON
) ; headers
. set ( "CustomHeader" , "myCustom" ) ; HttpEntity < MultiValueMap < Object , Object > > httpEntity
= new HttpEntity < > ( map
, headers
) ; ResponseEntity < String > responseEntity
= restTemplate
. exchange ( url
, HttpMethod . POST
, httpEntity
, String . class ) ; String s
= restTemplate
. postForObject ( url
, httpEntity
, String . class ) ; ResponseEntity < String > stringResponseEntity
= restTemplate
. postForEntity ( url
, httpEntity
, String . class ) ; assert s
!= null ; byte [ ] bytes
= s
. getBytes ( StandardCharsets . UTF_8
) ; String body
= new String ( bytes
, StandardCharsets . UTF_8
) ; System . out
. println ( body
) ; System . out
. println ( responseEntity
. getBody ( ) ) ; System . out
. println ( "響應(yīng)頭--start" ) ; stringResponseEntity
. getHeaders ( ) . entrySet ( ) . forEach ( System . out
:: println ) ; System . out
. println ( "響應(yīng)頭--end" ) ; }
}
其實(shí),如果參數(shù)是一個(gè) MultiValueMap 的實(shí)例,則以 key/value 的形式發(fā)送,如果是一個(gè)普通對(duì)象,則會(huì)被轉(zhuǎn)成 json 發(fā)送。
postForLocation 方法的返回值是一個(gè) URL 對(duì)象,因?yàn)?POST 請(qǐng)求一般用來(lái)添加數(shù)據(jù),有的時(shí)候需要將剛剛添加成功的數(shù)據(jù)的 URL 返回來(lái),此時(shí)就可以使用這個(gè)方法,一個(gè)常見(jiàn)的使用場(chǎng)景如用戶注冊(cè)功能,用戶注冊(cè)成功之后,可能就自動(dòng)跳轉(zhuǎn)到登錄頁(yè)面了,此時(shí)就可以使用該方法。
只要將 GET 請(qǐng)求和 POST 請(qǐng)求搞定了,接下來(lái) PUT 請(qǐng)求就會(huì)容易很多了,PUT 請(qǐng)求本身方法也比較少,只有三個(gè),如下: 這三個(gè)重載的方法其參數(shù)其實(shí)和 POST 是一樣的,可以用 key/value 的形式傳參,也可以用 JSON 的形式傳參,無(wú)論哪種方式,都是沒(méi)有返回值的
和 PUT 請(qǐng)求一樣,DELETE 請(qǐng)求也是比較簡(jiǎn)單的,只有三個(gè)方法,如下:
不同于 POST 和 PUT ,DELETE 請(qǐng)求的參數(shù)只能在地址欄傳送,可以是直接放在路徑中,也可以用 key/value 的形式傳遞,當(dāng)然,這里也是沒(méi)有返回值的。
public class TemplateDeleteJson { public static void main ( String [ ] args
) { RequestConfig config
= RequestConfig . custom ( ) . setConnectionRequestTimeout ( 10000 ) . setConnectTimeout ( 10000 ) . setSocketTimeout ( 30000 ) . build ( ) ; HttpClientBuilder builder
= HttpClientBuilder . create ( ) . setDefaultRequestConfig ( config
) . setRetryHandler ( new DefaultHttpRequestRetryHandler ( 3 , false ) ) ; HttpClient httpClient
= builder
. build ( ) ; ClientHttpRequestFactory requestFactory
= new HttpComponentsClientHttpRequestFactory ( httpClient
) ; RestTemplate restTemplate
= new RestTemplate ( requestFactory
) ; String url
= "https://httpbin.org/delete" ; String json
= "{" + "\"name\":\"mkyong\"," + "\"notes\":\"hello\"" + "}" ; HttpHeaders headers
= new HttpHeaders ( ) ; headers
. setContentType ( MediaType . APPLICATION_JSON
) ; headers
. set ( "CustomHeader" , "myCustom" ) ; HttpEntity < String > httpEntity
= new HttpEntity < > ( json
, headers
) ; restTemplate
. delete ( url
, httpEntity
) ; }
}
參考文章 參考文章 參考文章
總結(jié)
以上是生活随笔 為你收集整理的HttpClient、OKhttp、RestTemplate对比 的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
如果覺(jué)得生活随笔 網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔 推薦給好友。