目錄
- 一 介紹
- 二 正文
- 三 例子
- 五 bug
- 參考
一 介紹
預備知識:
- HttpEntity含有headers和body資訊;子類ResponseEntity添加了狀态碼;子類RequestEntit添加了method和url資訊。
- 都有對象的Builder類,友善建構對象。
- 在一些HTTP用戶端庫的基礎上提供更高層的API,使得更容易的通路rest風格的http請求。
- http請求用戶端、線程安全、同步請求
- 底層基于JDK HttpURLConnection(預設)或Apache HttpComponents等等
二 正文
- 方法:
- 通用方法:
和exchange
,用于支援更少見的請求,可定制的功能更多(可定制化程度:execute
>execute
),一個比較底層的方法。exchange
- Rest方法:該類的方法被組織成rest方式的風格,命名方式有規律,部分方法如下所示:
HTTP RestTemplate DELETE delete(String, String...)
GET getForObject(String, Class, String...)
HEAD headForHeaders(String, String...)
OPTIONS optionsForAllow(String, String...)
POST postForLocation(String, Object, String...)
PUT put(String, Object, String...)
- 基本上,方法名第一部分表示http請求方法,第二部分表示傳回值。
- 基本上,第一個參數為url,接着(請求對象)request(if any),接着傳回對象類型(if any),接着第三個為url參數(if any)。
- request參數一般為
,或者HttpEntity
(可寫入MultiValueMap
中),但不可為其他類型對象 也可為其他對象, 隻要存在對應轉化器(Converter)HttpEntity
- 當不想要傳回值時,傳回類型可設為
Void.class
- request參數一般為
- 這些方法底層都是調用了
方法實作的doExecute
- 通用方法:
- 初始化:底層預設使用JDK的
實作,也可在構造函數上切換其他HTTP庫。内置支援:HttpURLConnection
- Apache HttpComponents
- Netty
- OkHttp
- URI:方法中第一個參數指定URI,它是一個模闆,支援路徑變量,方法的最後一個參數設定變量值,并且會自動進行url編碼。一個例子如下所示:
- Headers:
方法可以設定請求頭部,也會擷取響應頭部。為啥rest方法不用設定呢?因為能自動推斷,是以通常情況下不用設定,見Body部分。exchange
- Body(消息體):請求消息體中填充對象或響應消息體中擷取對象,都是通過
完成的。通常情況下,你是不必顯示設定HttpMessageConverter
和Content-Type
,因為僅通過傳入的Java類型就可以确定轉換器,然後由轉換器自己設定這些頭字段。Accept
- 方法參數的請求對象
的類型,可以确定序列化請求對象的轉換器,繼而轉換器确定Object
Content-Type
- 方法參數的結果對象類型
可以确定解析響應消息體的轉換器,繼而轉換器确定responseType
Accept
- 當然可以通過
手動指定,這會影響使用的轉換器的選擇。exchange
- 方法參數的請求對象
- HttpMessageConverter:Spring為常用的MIME類型和Java類型注冊了一些預設的轉換器,至于該轉化器是否生效,取決于classpath下是否有對應的jar包。預設轉化器如下所示: 從描述中,可以看到轉換器會自動設定頭字段。其中注意的是,請求體中直接轉入pojo對象,會被jackson轉化為JSON資料,如果想使用
MessageConverter Description StringHttpMessageConverter
An
implementation that can read and writeHttpMessageConverter
instances from the HTTP request and response. By default, this converter supports all text media types (String
) and writes with atext*
ofContent-Type
. You can override this by setting theapplication/octet-stream
property and overridingsupportedMediaTypes
.getContentType(byte[])
MarshallingHttpMessageConverter
An
implementation that can read and write XML by using Spring’sHttpMessageConverter
andMarshaller
abstractions from theUnmarshaller
package. This converter requires aorg.springframework.oxm
andMarshaller
before it can be used. You can inject these through constructor or bean properties. By default, this converter supportsUnmarshaller
andtext/xml
.application/xml
MappingJackson2HttpMessageConverter
An
implementation that can read and write JSON by using Jackson’sHttpMessageConverter
. You can customize JSON mapping as needed through the use of Jackson’s provided annotations. When you need further control (for cases where custom JSON serializers/deserializers need to be provided for specific types), you can inject a customObjectMapper
through theObjectMapper
property. By default, this converter supportsObjectMapper
.application/json
MappingJackson2XmlHttpMessageConverter
An
implementation that can read and write XML by usingJackson XML extension’sHttpMessageConverter
. You can customize XML mapping as needed through the use of JAXB or Jackson’s provided annotations. When you need further control (for cases where custom XML serializers/deserializers need to be provided for specific types), you can inject a customXmlMapper
through theXmlMapper
property. By default, this converter supportsObjectMapper
.application/xml
SourceHttpMessageConverter
An
implementation that can read and writeHttpMessageConverter
from the HTTP request and response. Onlyjavax.xml.transform.Source
,DOMSource
, andSAXSource
are supported. By default, this converter supportsStreamSource
andtext/xml
.application/xml
BufferedImageHttpMessageConverter
An
implementation that can read and writeHttpMessageConverter
from the HTTP request and response. This converter reads and writes the media type supported by the Java I/O API.java.awt.image.BufferedImage
生成前端表單post請求格式的資料,需要使用FormHttpMessageConverter
類存儲資料。MultiValueMap
spring mvc(服務端)和RestTemplate(用戶端)中都用到了
、HttpMessageConverter
/RequestEntity
- form表單:表單的消息體由
轉換器進行轉換,當請求資料為MultiValueMap<String,?>類時會使用該轉換器,該類可以使用MultipartBodyBuilder更友善的建立出來。表單有兩種編碼方式:FormHttpMessageConverter
-
:當application/x-www-form-urlencoded
的值(value,非key、非請求參數值)全為字元串時,轉換器會使用這種編碼方式。MultiValueMap
-
:其他情況都使用這種編碼方式。每個part都是一個HttpEntity,可能會有頭字段,如檔案須有multipart/form-data
,但一般不必手動設定,每個part的轉換器會自動設定,如下面的例子所示:Content-Type
上面的序列化檔案時,使用的,,是哪個轉換器??不知道,,反正使用的對象必須有對應的轉換器存在才行!MultipartBodyBuilder builder = new MultipartBodyBuilder(); builder.part("fieldPart", "fieldValue"); builder.part("filePart", new FileSystemResource("...logo.png")); builder.part("jsonPart", new Person("Jason")); template.postForObject("https://example.com/upload", builder.build(), Void.class);
-
三 例子
測試時所用的,全貼下來了,,
@RunWith(SpringRunner.class)
@SpringBootTest
public class BlogApplicationTests {
static class A{
int a;
int b;
public int getA() {
return a;
}
public void setA(int a) {
this.a = a;
}
public int getB() {
return b;
}
public void setB(int b) {
this.b = b;
}
}
@Test
public void test3(){
A a=new A();
a.setA(1);
a.setB(2);
new RestTemplate().postForObject("http://localhost:8080/image/test",a,Void.class);
}
@Test
public void test4(){
/*MultiValueMap<String,Object> map=new LinkedMultiValueMap<>();
map.add("a","a");
map.add("b","23");*/
MultipartBodyBuilder builder=new MultipartBodyBuilder();
builder.part("a","a");
builder.part("b","b");
builder.part("file",new FileSystemResource("C:\\Users\\Administrator\\Pictures\\王通.jpg"));
new RestTemplate().postForObject("http://localhost:8080/image/test3",builder.build(),Void.class);
}
@Test
public void test5(){
Map<String,Object> map=new HashMap<>();
map.put("a","aa");
map.put("b",23);
new RestTemplate().postForObject("http://localhost:8080/image/test2",new HttpEntity<Map>(map),Void.class);
}
@Test
public void contextLoads() throws IOException {
RestTemplate restTemplate = new RestTemplate();
String url
= "http://localhost:8080/user/login";
MultiValueMap<String,String> param= new LinkedMultiValueMap<>();
param.add("username","千霜");
param.add("password","123456");
HttpHeaders headers=new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
HttpEntity<Map> entity=new HttpEntity<>(param,headers);
ResponseEntity<Status> responseEntity=restTemplate.postForEntity(url,entity,Status.class);
Status status=responseEntity.getBody();
System.out.println(status);
}
@Test
public void test2() throws FileNotFoundException, URISyntaxException {
MultipartBodyBuilder builder=new MultipartBodyBuilder();
builder.part("file",new FileSystemResource("C:\\Users\\Administrator\\Pictures\\王通.jpg"));
Status status=new RestTemplate().postForObject("http://localhost:8080/image/upload",builder.build(),Status.class);
System.out.println(status);
}
//new FileInputStream("C:\\Users\\Administrator\\Pictures\\王通.jpg")
}
五 bug
使用過程中發現了點spring boot的bug,就是必須添加了如下依賴後,一些功能才能使用:
<dependency>
<groupId>org.reactivestreams</groupId>
<artifactId>reactive-streams</artifactId>
<version>1.0.2</version>
</dependency>
見issue12579
參考
- REST Endpoints office doc
- RestTemplate office post
- RestTemplate Baeldung
- MIME
- on Basic Auth with RestTemplate:進階閱讀,儲存憑證credentials