spring resttemplate文档阅读
This commit is contained in:
111
spring/Spring Http Client/Spring RestTemplate.md
Normal file
111
spring/Spring Http Client/Spring RestTemplate.md
Normal file
@@ -0,0 +1,111 @@
|
|||||||
|
# RestTemplate
|
||||||
|
RestTemplate提供了比http client library更高层级的api,其允许以更加容易的方式来调用rest接口。
|
||||||
|
## 初始化
|
||||||
|
RestTemplate的默认构造函数使用`java.net.HttpURLConnection`来执行http请求。
|
||||||
|
## URIs
|
||||||
|
RestTemplate的许多方法都接收一个URI template和URI tempalte变量要么作为`String`变量参数,要么作为`Map<String,String>`.
|
||||||
|
如下示例使用了String类型参数:
|
||||||
|
```java
|
||||||
|
String result = restTemplate.getForObject(
|
||||||
|
"https://example.com/hotels/{hotel}/bookings/{booking}", String.class, "42", "21");
|
||||||
|
```
|
||||||
|
如下示例则是使用了Map类型的参数:
|
||||||
|
```java
|
||||||
|
Map<String, String> vars = Collections.singletonMap("hotel", "42");
|
||||||
|
|
||||||
|
String result = restTemplate.getForObject(
|
||||||
|
"https://example.com/hotels/{hotel}/rooms/{hotel}", String.class, vars);
|
||||||
|
```
|
||||||
|
URI tempalte是自动编码的,按如下示例所示:
|
||||||
|
```java
|
||||||
|
restTemplate.getForObject("https://example.com/hotel list", String.class);
|
||||||
|
|
||||||
|
// Results in request to "https://example.com/hotel%20list"
|
||||||
|
```
|
||||||
|
## headers
|
||||||
|
可以通过`exchange()`方法来指定请求的headers,如下所示:
|
||||||
|
```java
|
||||||
|
String uriTemplate = "https://example.com/hotels/{hotel}";
|
||||||
|
URI uri = UriComponentsBuilder.fromUriString(uriTemplate).build(42);
|
||||||
|
|
||||||
|
RequestEntity<Void> requestEntity = RequestEntity.get(uri)
|
||||||
|
.header("MyRequestHeader", "MyValue")
|
||||||
|
.build();
|
||||||
|
|
||||||
|
ResponseEntity<String> response = template.exchange(requestEntity, String.class);
|
||||||
|
|
||||||
|
String responseHeader = response.getHeaders().getFirst("MyResponseHeader");
|
||||||
|
String body = response.getBody();
|
||||||
|
```
|
||||||
|
## body
|
||||||
|
向RestTemplate中方法传入的参数或RestTemplate方法返回的对象,其与raw content之间的转换都是通过`HttpMessageConverter`来执行的。
|
||||||
|
在一个POST请求中,传入到RestTemplate方法中的参数会被序列化到请求的body中:
|
||||||
|
```java
|
||||||
|
URI location = template.postForLocation("https://example.com/people", person);
|
||||||
|
```
|
||||||
|
**使用者并不需要显式设置请求体的`Content-Type`header**。在大多数情况下,都可以基于source Object类型找到一个合适的message converter,而被选中的message converter则会设置content type header。如果在必要情况下,可以通过`exchange`方法来显式提供`Content-Type` header,并且在设置content type请求头之后,会影响选中的message converter。
|
||||||
|
如下示例显示了一个get请求,将响应的body反序列化为方法的返回类型:
|
||||||
|
```java
|
||||||
|
Person person = restTemplate.getForObject("https://example.com/people/{id}", Person.class, 42);
|
||||||
|
```
|
||||||
|
类似于`Content-Type`请求头,`Accept`请求头也不需要显式设置。在多数情况下,根据方法返回类型选中的message converter会帮助注入Accept请求头。在必要情况下,可以通过`exchange()`方法来指定要传递的`Accept`请求头。
|
||||||
|
默认情况下,RestTemplate注册了所有内置的message converter。
|
||||||
|
|
||||||
|
## Multipart
|
||||||
|
如果需要发送multipart数据,需要提供一个`MultiValueMap<String,Object>`,该map的value可以是一个part content object,file part resource,含有part content和header的HttpEntity。
|
||||||
|
```java
|
||||||
|
MultiValueMap<String, Object> parts = new LinkedMultiValueMap<>();
|
||||||
|
|
||||||
|
parts.add("fieldPart", "fieldValue");
|
||||||
|
parts.add("filePart", new FileSystemResource("...logo.png"));
|
||||||
|
parts.add("jsonPart", new Person("Jason"));
|
||||||
|
|
||||||
|
HttpHeaders headers = new HttpHeaders();
|
||||||
|
headers.setContentType(MediaType.APPLICATION_XML);
|
||||||
|
parts.add("xmlPart", new HttpEntity<>(myBean, headers));
|
||||||
|
|
||||||
|
```
|
||||||
|
当MultiValueMap构建好之后,可以将其传递给RestTemplate,如下所示:
|
||||||
|
```java
|
||||||
|
MultiValueMap<String, Object> parts = ...;
|
||||||
|
template.postForObject("https://example.com/upload", parts, Void.class);
|
||||||
|
```
|
||||||
|
如果MultiValueMap至少含有一个不为String的值,那么Content-Type将会被`FormHttpMessageConverter`设置为`multipart/form-data`。
|
||||||
|
如果MultiValueMap中只有String类型的值,那么content-type会被设置为`application/x-www-form-urlencoded`。
|
||||||
|
|
||||||
|
## Http接口
|
||||||
|
Spring允许将Http service定义为java接口,该方法上有注解用于http交换。可以通过该接口产生一个代理对象实现该接口,代理对象可以执行http请求交换。
|
||||||
|
首先,定义一个接口,并且通过`@HttpExchange`注解来标注接口中的方法:
|
||||||
|
```java
|
||||||
|
interface RepositoryService {
|
||||||
|
|
||||||
|
@GetExchange("/repos/{owner}/{repo}")
|
||||||
|
Repository getRepository(@PathVariable String owner, @PathVariable String repo);
|
||||||
|
|
||||||
|
// more HTTP exchange methods...
|
||||||
|
|
||||||
|
}
|
||||||
|
```
|
||||||
|
其次,可以创建一个代理对象来执行http请求,创建方式如下所示:
|
||||||
|
```java
|
||||||
|
WebClient client = WebClient.builder().baseUrl("https://api.github.com/").build();
|
||||||
|
HttpServiceProxyFactory factory = HttpServiceProxyFactory.builder(WebClientAdapter.forClient(client)).build();
|
||||||
|
|
||||||
|
RepositoryService service = factory.createClient(RepositoryService.class);
|
||||||
|
```
|
||||||
|
`@HttpExchange`注解也支持类级别,类级别注解将会应用到接口中所有的方法:
|
||||||
|
```java
|
||||||
|
@HttpExchange(url = "/repos/{owner}/{repo}", accept = "application/vnd.github.v3+json")
|
||||||
|
interface RepositoryService {
|
||||||
|
|
||||||
|
@GetExchange
|
||||||
|
Repository getRepository(@PathVariable String owner, @PathVariable String repo);
|
||||||
|
|
||||||
|
@PatchExchange(contentType = MediaType.APPLICATION_FORM_URLENCODED_VALUE)
|
||||||
|
void updateRepository(@PathVariable String owner, @PathVariable String repo,
|
||||||
|
@RequestParam String name, @RequestParam String description, @RequestParam String homepage);
|
||||||
|
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
Reference in New Issue
Block a user