RestTemplate 是 Spring 框架中用于同步客户端 HTTP 请求的一个类,它提供了多种方法来发送 HTTP 请求。以下是一些常用的 RestTemplate 方法及其代码案例:
1.postForObject()
该方法用于发送 POST 请求,并期望返回一个对象。以下是一个使用 postForObject
的示例:
RestTemplate restTemplate = new RestTemplate();
HttpEntity<Foo> request = new HttpEntity<>(new Foo("bar"));
Foo foo = restTemplate.postForObject(fooResourceUrl, request, Foo.class);
Assertions.assertNotNull(foo);
Assertions.assertEquals(foo.getName(), "bar");
-
RestTemplate restTemplate = new RestTemplate();
:创建了RestTemplate
的一个实例,用于执行 HTTP 请求。 -
HttpEntity<Foo> request = new HttpEntity<>(new Foo("bar"));
:创建了一个HttpEntity
对象,它包含了要发送的数据(在这个例子中是一个Foo
对象,其构造函数接收一个字符串参数 "bar")和 HTTP 头部信息(在这个例子中头部信息是空的,因为HttpEntity
的构造函数没有接收任何头部信息参数)。 -
Foo foo = restTemplate.postForObject(fooResourceUrl, request, Foo.class);
:使用postForObject
方法发送 POST 请求到fooResourceUrl
指定的 URL。这个方法的第一个参数是请求的 URL,第二个参数是包含请求体和头部信息的HttpEntity
对象,第三个参数是期望返回的对象类型,这里期望返回一个Foo
类型的对象。 -
Assertions.assertNotNull(foo);
:使用断言来检查返回的foo
对象是否不为null
,确保请求成功并且得到了响应。 -
Assertions.assertEquals(foo.getName(), "bar");
:再次使用断言来检查返回的foo
对象的name
属性是否等于 "bar",确保返回的对象包含了正确的数据。
2. postForLocation()
该方法用于发送 POST 请求,不返回完整的资源,只返回新创建资源的位置:
HttpEntity<Foo> request = new HttpEntity<>(new Foo("bar"));
URI location = restTemplate.postForLocation(fooResourceUrl, request);
Assertions.assertNotNull(location);
这段代码展示了如何使用 RestTemplate
发送一个 POST 请求,并期望服务器响应中包含新创建资源的 URI。以下是代码的详细解释:
-
HttpEntity<Foo> request = new HttpEntity<>(new Foo("bar"));
:创建了一个HttpEntity
对象,它包含了要发送的数据(在这个例子中是一个Foo
对象,其构造函数接收一个字符串参数 "bar")。HttpEntity
对象不仅包含请求体,还可以包含请求头信息,但在这个例子中没有显式设置任何请求头。 -
URI location = restTemplate.postForLocation(fooResourceUrl, request);
:使用postForLocation
方法发送 POST 请求到fooResourceUrl
指定的 URL。这个方法的第一个参数是请求的 URL,第二个参数是包含请求体的HttpEntity
对象。与postForObject
方法不同,postForLocation
方法不期望返回一个响应体,而是期望返回新创建资源的 URI。这个方法返回一个URI
对象,表示新创建资源的位置。 -
Assertions.assertNotNull(location);
:使用断言来检查返回的location
对象是否不为null
,确保请求成功并且服务器返回了新资源的位置。
这个示例假设服务端接收 POST 请求后,会处理请求体中的数据,并创建一个新的资源。然后,服务器会在响应中包含一个 Location
头,指示新创建资源的 URI。RestTemplate
会自动从响应头中提取这个 Location
值,并将其作为 URI
对象返回。
3. exchange()
exchange
方法是一个更通用的 POST 请求方法,允许更灵活的请求配置:
RestTemplate restTemplate = new RestTemplate();
HttpEntity<Foo> request = new HttpEntity<>(new Foo("bar"));
ResponseEntity<Foo> response = restTemplate.exchange(fooResourceUrl, HttpMethod.POST, request, Foo.class);
Assertions.assertEquals(response.getStatusCode(), HttpStatus.CREATED);
Foo foo = response.getBody();
Assertions.assertNotNull(foo);
Assertions.assertEquals(foo.getName(), "bar");
这段代码展示了如何使用 RestTemplate
发送一个 POST 请求,并检查响应状态码以及响应体。以下是代码的详细解释:
-
RestTemplate restTemplate = new RestTemplate();
:创建了RestTemplate
的一个实例,用于执行 HTTP 请求。 -
HttpEntity<Foo> request = new HttpEntity<>(new Foo("bar"));
:创建了一个HttpEntity
对象,它包含了要发送的数据(在这个例子中是一个Foo
对象,其构造函数接收一个字符串参数 "bar")。HttpEntity
对象不仅包含请求体,还可以包含请求头信息,但在这个例子中没有显式设置任何请求头。 -
ResponseEntity<Foo> response = restTemplate.exchange(fooResourceUrl, HttpMethod.POST, request, Foo.class);
:使用exchange
方法发送 POST 请求到fooResourceUrl
指定的 URL。这个方法的第一个参数是请求的 URL,第二个参数是请求的方法(这里是HttpMethod.POST
),第三个参数是包含请求体和头部信息的HttpEntity
对象,第四个参数是期望返回的对象类型,这里期望返回一个Foo
类型的对象。exchange
方法返回一个ResponseEntity
对象,它包含了响应的状态码、响应头、响应体等信息。 -
Assertions.assertEquals(response.getStatusCode(), HttpStatus.CREATED);
:使用断言来检查响应的状态码是否等于HttpStatus.CREATED
(201),这通常表示资源创建成功。 -
Foo foo = response.getBody();
:从ResponseEntity
对象中获取响应体,这里期望是一个Foo
类型的对象。 -
Assertions.assertNotNull(foo);
:使用断言来检查返回的foo
对象是否不为null
,确保请求成功并且得到了响应。 -
Assertions.assertEquals(foo.getName(), "bar");
:再次使用断言来检查返回的foo
对象的name
属性是否等于 "bar",确保返回的对象包含了正确的数据。
4. 提交表单数据
使用 POST 方法提交表单数据,需要将 Content-Type 头设置为 application/x-www-form-urlencoded:
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);MultiValueMap<String, String> map = new LinkedMultiValueMap<>();
map.add("id", "1");HttpEntity<MultiValueMap<String, String>> request = new HttpEntity<>(map, headers);
ResponseEntity<String> response = restTemplate.postForEntity(fooResourceUrl+"/form", request, String.class);
Assertions.assertEquals(response.getStatusCode(), HttpStatus.CREATED);
这段代码展示了如何使用 RestTemplate
发送一个包含表单数据的 POST 请求,并验证响应状态码。以下是代码的详细解释:
-
HttpHeaders headers = new HttpHeaders();
:创建了一个HttpHeaders
对象,用于设置 HTTP 请求的头部信息。 -
headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
:设置请求的Content-Type
头部为application/x-www-form-urlencoded
,这表明请求体中的数据是 URL 编码的表单数据。 -
MultiValueMap<String, String> map = new LinkedMultiValueMap<>();
:创建了一个LinkedMultiValueMap
实例,用于存储表单数据。LinkedMultiValueMap
允许每个键对应多个值,但在这个例子中,我们只添加了一个值。 -
map.add("id", "1");
:向map
中添加了一个键值对,键是 "id",值是 "1"。 -
HttpEntity<MultiValueMap<String, String>> request = new HttpEntity<>(map, headers);
:创建了一个HttpEntity
对象,它包含了表单数据(map
)和头部信息(headers
)。 -
ResponseEntity<String> response = restTemplate.postForEntity(fooResourceUrl+"/form", request, String.class);
:使用postForEntity
方法发送 POST 请求到fooResourceUrl+"/form"
指定的 URL。这个方法的第一个参数是请求的 URL,第二个参数是包含请求体和头部信息的HttpEntity
对象,第三个参数是期望返回的对象类型,这里期望返回一个String
类型的对象。postForEntity
方法返回一个ResponseEntity
对象,它包含了响应的状态码、响应头、响应体等信息。 -
Assertions.assertEquals(response.getStatusCode(), HttpStatus.CREATED);
:使用断言来检查响应的状态码是否等于HttpStatus.CREATED
(201),这通常表示资源创建成功。`
5. optionsForAllow()
使用 optionsForAllow
方法来获取指定 URL 上允许的操作(请求方法):
Set<HttpMethod> optionsForAllow = restTemplate.optionsForAllow(fooResourceUrl);
HttpMethod[] supportedMethods = {HttpMethod.GET, HttpMethod.POST, HttpMethod.PUT, HttpMethod.DELETE};
Assertions.assertTrue(optionsForAllow.containsAll(Arrays.asList(supportedMethods)));
这段代码使用了 RestTemplate
的 optionsForAllow
方法来查询指定资源 URL 支持的 HTTP 方法,并验证这些方法是否包含在特定的一组方法中。以下是代码的详细解释:
-
Set<HttpMethod> optionsForAllow = restTemplate.optionsForAllow(fooResourceUrl);
:调用optionsForAllow
方法发送一个 HTTP OPTIONS 请求到fooResourceUrl
指定的 URL。这个方法返回一个Set<HttpMethod>
,包含了服务器声明该资源支持的所有 HTTP 方法。 -
HttpMethod[] supportedMethods = {HttpMethod.GET, HttpMethod.POST, HttpMethod.PUT, HttpMethod.DELETE};
:定义了一个HttpMethod
数组,包含了你期望服务器支持的方法。 -
Assertions.assertTrue(optionsForAllow.containsAll(Arrays.asList(supportedMethods)));
:使用断言来检查第一步中获取的Set<HttpMethod>
是否包含了第二步中定义的所有 HTTP 方法。containsAll
方法会检查集合是否包含指定集合中的所有元素。
这个示例假设你想要验证服务器是否支持 GET、POST、PUT 和 DELETE 这四种常见的 HTTP 方法。如果服务器对 fooResourceUrl
资源的响应中包含了 Allow
头部,其中列出了支持的方法,那么 optionsForAllow
方法将解析这个头部并返回相应的 HttpMethod
集合。
6. 使用 PUT 请求更新资源
使用 exchange()
发起简单的 PUT 请求,该请求没有响应体:
Foo updatedInstance = new Foo("newName");
updatedInstance.setId(createResponse.getBody().getId());
String resourceUrl = fooResourceUrl + '/' + createResponse.getBody().getId();
HttpEntity<Foo> requestUpdate = new HttpEntity<>(updatedInstance, headers);
template.exchange(resourceUrl, HttpMethod.PUT, requestUpdate, Void.class);
这段代码展示了如何使用 RestTemplate
发送一个 HTTP PUT 请求来更新服务器上的资源。以下是代码的详细解释:
-
Foo updatedInstance = new Foo("newName");
:创建了一个新的Foo
实例,并将其属性设置为 "newName"。 -
updatedInstance.setId(createResponse.getBody().getId());
:从之前创建资源时获得的响应(createResponse
)中获取资源的 ID,并将其设置为更新实例的 ID。这确保了更新操作是针对特定的资源。 -
String resourceUrl = fooResourceUrl + '/' + createResponse.getBody().getId();
:构建了包含资源 ID 的完整 URL,用于指定要更新的资源。 -
HttpEntity<Foo> requestUpdate = new HttpEntity<>(updatedInstance, headers);
:创建了一个HttpEntity
对象,它包含了要更新的Foo
实例和之前定义的 HTTP 头部信息(headers
)。 -
template.exchange(resourceUrl, HttpMethod.PUT, requestUpdate, Void.class);
:使用exchange
方法发送 PUT 请求到构建的资源 URL。这个方法的第一个参数是请求的 URL,第二个参数是请求的方法(这里是HttpMethod.PUT
),第三个参数是包含请求体和头部信息的HttpEntity
对象,第四个参数是期望返回的对象类型,这里使用Void.class
表示不期望返回任何内容(即服务器应该返回状态码,但不返回响应体)。
这个示例假设服务端接收 PUT 请求后,会处理请求体中的数据,并更新指定 ID 的资源。通常,PUT 请求用于发送资源的完整更新,而 PATCH 请求用于发送资源的部分更新。
请注意,这段代码中的 createResponse
是之前某个创建资源操作的响应,它包含了新创建资源的 ID。此外,headers
是之前定义的 HttpHeaders
实例,它可能包含了如 Content-Type
等必要的头部信息。
7. 上传文件
上传文件时,Content-Type 为 multipart/form-data 类型。以下是上传单个文件的示例:
RestTemplate restTemplate = new RestTemplate();
String url = "http://localhost:8080/chat16/test/form2";
MultiValueMap<String, Object> body = new LinkedMultiValueMap<>();
body.add("file1", new FileSystemResource(".\\src\\main\\java\\com\\javacode2018\\springmvc\\chat16\\dto\\UserDto.java"));
HttpHeaders headers = new HttpHeaders();
headers.add("header1", "v1");
headers.add("header2", "v2");
RequestEntity<MultiValueMap<String, Object>> requestEntity = new RequestEntity<>(body, headers, HttpMethod.POST, URI.create(url));
ResponseEntity<Map<String, String>> responseEntity = restTemplate.exchange(requestEntity,new ParameterizedTypeReference<Map<String, String>>() {}
);
Map<String, String> result = responseEntity.getBody();
System.out.println(result);
这段代码展示了如何使用 RestTemplate
发送一个包含文件和其他表单数据的 HTTP POST 请求,并处理响应。以下是代码的详细解释:
-
RestTemplate restTemplate = new RestTemplate();
:创建了RestTemplate
的一个实例,用于执行 HTTP 请求。 -
String url = "http://localhost:8080/chat16/test/form2";
:定义了请求的目标 URL。 -
MultiValueMap<String, Object> body = new LinkedMultiValueMap<>();
:创建了一个MultiValueMap
实例,用于存储请求体中的表单数据和文件。 -
body.add("file1", new FileSystemResource(".\\src\\main\\java\\com\\javacode2018\\springmvc\\chat16\\dto\\UserDto.java"));
:向body
中添加了一个文件。这里使用的是FileSystemResource
,它表示一个文件系统中的资源。 -
HttpHeaders headers = new HttpHeaders();
:创建了一个HttpHeaders
对象,用于设置 HTTP 请求的头部信息。 -
headers.add("header1", "v1");
和headers.add("header2", "v2");
:向请求头部添加了两个自定义的头部字段。 -
RequestEntity<MultiValueMap<String, Object>> requestEntity = new RequestEntity<>(body, headers, HttpMethod.POST, URI.create(url));
:创建了一个RequestEntity
对象,它包含了请求体、头部信息、请求方法(这里是 POST)和请求的 URI。 -
ResponseEntity<Map<String, String>> responseEntity = restTemplate.exchange(requestEntity, new ParameterizedTypeReference<Map<String, String>>() {});
:使用exchange
方法发送请求并接收响应。这里使用了RequestEntity
作为请求参数,并且指定了响应体期望的类型是一个Map<String, String>
。 -
Map<String, String> result = responseEntity.getBody();
:从响应实体中获取响应体,这里期望是一个Map
类型的对象。 -
System.out.println(result);
:打印出响应体的内容。
这个示例中,exchange
方法被用来发送一个包含文件和其他表单数据的 POST 请求。由于文件数据是多部分的,所以不需要手动设置 Content-Type
为 multipart/form-data
,RestTemplate
会自动处理。但是,如果需要自定义多部分请求的边界,可以通过设置 HttpHeaders
的 Content-Type
属性来实现。
请注意,这段代码中的 new ParameterizedTypeReference<Map<String, String>>() {}
是一个泛型类型参考,它用于指定响应体的泛型类型。这是必要的,因为 Java 的类型擦除机制会在运行时移除泛型信息。
最后,确保服务器端的 URL 能够处理多部分表单数据,并且能够正确响应。如果服务器返回的不是 Map<String, String>
类型的数据,你需要修改 ParameterizedTypeReference
以匹配实际的响应类型。