基于 Springboot 2.3.12.RELEASE 版本测试
RestTemplate 是 Spring 官方提供的一个同步的 Web Http 客户端请求模板工具。
其他常用客户端工具有:JDK HttpUrlConnection、Apache HttpClient、OkHttp 等。
Spring 的 RestTemplate 默认使用 HttpUrlConnection 提供发送 HTTP 请求的支持,可以指定相关工厂类更换请求工具。
例:使用 Apache HttpClient
RestTemplate template = new RestTemplate(new HttpComponentsClientHttpRequestFactory());
在使用 RestTemplate 工具前进行注入
@Bean public RestTemplate restTemplate() { // RestTemplate 默认使用 HttpUrlConnection。 return new RestTemplate(); }
controller 样例:
@RequestMapping("/demo") @RestController public class DemoController {...}
单元测试类:
@RunWith(SpringJUnit4ClassRunner.class) @SpringBootTest(classes = DemoApp.class, webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT) public class DemoControllerTest { public static final String URL = "http://localhost:18080/rest-demo"; @Autowired private RestTemplate restTemplate; }
发送 GET 请求
使用 getForObject 方法发送 GET 请求
既然是 REST 风格,请求参数一般都组合为一个URI
@GetMapping("/getById1/{id}") public UserInfo getById1(@PathVariable("id") Long id) { ... }
发送请求代码
UserInfo userInfo = restTemplate.getForObject(URL + "/demo/getById1/2", UserInfo.class);
可以通过第二个参数指定返回类型,RestTemplate 是通过 JSON 解析返回结果的,也可以使用 Map 接收。
如果使用 @RequestParam 接收参数,需要使用 ? 拼接URL地址。
@GetMapping("/getById2") public UserInfo getById2(@RequestParam("id") Long id) { ... }
发送请求代码
UserInfo userInfo = restTemplate.getForObject(URL + "/demo/getById2?id=10", UserInfo.class);
使用 getForEntity 方法发送 GET 请求
getForEntity() 方法和 getForObject() 方法使用类似,不同的是请求返回结果封装在 ResponseEntity 对象中,通过该对象可以获取更多网络响应信息。
ResponseEntity<UserInfo> forEntity = restTemplate.getForEntity(URL + "/demo/getById1/2", UserInfo.class); HttpStatus statusCode = forEntity.getStatusCode(); int statusCodeValue = forEntity.getStatusCodeValue(); HttpHeaders headers = forEntity.getHeaders(); UserInfo body = forEntity.getBody();
使用 exchange 方法发送 GET 请求
exchange() 方法即可以发送任意其他网络请求,发送 GET 和 POST 等其他方法底层使用的也是该方法。
exchange() 方法返回的结果也都封装在 ResponseEntity 对象中。
ResponseEntity<UserInfo> exchange = restTemplate.exchange(URL + "/demo/getById1/30", HttpMethod.GET, null, UserInfo.class); HttpStatus statusCode = exchange.getStatusCode(); int statusCodeValue = exchange.getStatusCodeValue(); HttpHeaders headers = exchange.getHeaders(); UserInfo body = exchange.getBody();
发送 POST 请求
使用 getForObject 方法发送 POST 请求
1、发送 POST 请求参数需要使用 MultiValueMap 对象,使用自定义类型 UserInfo 是无法接收到参数的。
@PostMapping("/add1") public UserInfo addUser1(Long id, String name) { ... }
发送请求样例:
MultiValueMap<String, Object> params = new LinkedMultiValueMap<>(); params.add("id", 20L); params.add("name", "Post"); UserInfo userInfo = restTemplate.postForObject(URL + "/demo/add1", params, UserInfo.class);
即使是使用自定义对象 UserInfo 接收参数,在发送请求时依然需要使用 MultiValueMap 对象。
@PostMapping("/add2") public UserInfo addUser2(UserInfo userInfo) { ... }
2、如果接收参数时使用了 @RequestBody 注解:
@PostMapping("/add3") public UserInfo addUser3(@RequestBody UserInfo userInfo) { ... }
则在发送请求时需要使用自定义对象,使用 MultiValueMap 对象封装参数会出现 500 异常。
UserInfo params = new UserInfo(); params.setId(10L); params.setName("Post"); UserInfo userInfo = restTemplate.postForObject(URL + "/demo/add3", params, UserInfo.class);
3、将发送请求的参数封装到 HttpEntity 对象中可以设置请求头
HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_JSON); UserInfo params = new UserInfo(); params.setId(20L); params.setName("Post"); HttpEntity<UserInfo> httpEntity = new HttpEntity<>(params, headers); UserInfo userInfo = restTemplate.postForObject(URL + "/demo/add3", httpEntity, UserInfo.class);
使用 getForEntity 方法发送 POST 请求
postForEntity() 方法和 postForObject() 方法类似,只是放回结果封装到了 ResponseEntity 对象中。
HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_JSON); UserInfo params = new UserInfo(); params.setId(20L); params.setName("Post"); HttpEntity<UserInfo> httpEntity = new HttpEntity<>(params, headers); ResponseEntity<UserInfo> responseEntity = restTemplate.postForEntity(URL + "/demo/add3", httpEntity, UserInfo.class); HttpStatus statusCode = responseEntity.getStatusCode(); int statusCodeValue = responseEntity.getStatusCodeValue(); HttpHeaders responseEntityHeaders = responseEntity.getHeaders(); UserInfo body = responseEntity.getBody();
这里请求参数使用了 HttpEntity 对象进行了封装,也可以不使用。
使用 exchange 方法发送 POST 请求
使用 exchange() 方法发送请求,请求参数必须使用 HttpEntity 对象进行封装,返回结果也封装在 ResponseEntity 对象中:
UserInfo params = new UserInfo(); params.setId(20L); params.setName("Post"); HttpEntity<UserInfo> httpEntity = new HttpEntity<>(params); ResponseEntity<UserInfo> exchange = restTemplate.exchange(URL + "/demo/add3", HttpMethod.POST, httpEntity, UserInfo.class);
Http 协议的状态码分类
1xx 通知
2xx 请求成功
3xx 重定向
4xx 客户端异常
5xx 服务端异常