SpringBoot - 如何发送Http请求
SpringBoot发送Http请求 — RestTemplate的使用
一、引入
①本文中代码用于测试Get请求(手机号归属地)
和Post请求(生成带logo二维码),
且实操皆已成功(源码)。
②本文采用IOC方式使用RestTemplate类,当然使用时new一个RestTemplate类也可正常工作。
import org.springframework.web.client.RestTemplate;
@Bean
public RestTemplate restTemplate(){ //在SpringBoot启动类中注册RestTemplate
return new RestTemplate();
}
@Resource
private RestTemplate restTemplate; //使用时注入RestTemplate类
二、介绍
①RestTemplate类是Spring3.0版本后自带的发送Http请求的客户端,使用简单、便捷。
②RestTemplate有常用的Get、Post方法,也有Put、Delete方法,还有通用的方法execute和exchange(可以发送所有类型Http请求)。
③getForObject()与getForEntity()的区别:
- getForObject()将Get请求的response序列化为一个Object(类型可以指定)并返回;
- getForEntity()将response序列化为ResponseEntity<T>类并返回(T是getForObject()返回的Object);
- getForEntity()实际上是将getForObject()的返回值进行二次加工,包装为ResponseEntity类;
④postForObject()与postForEntity()的区别:
- postForObject()将Post请求的response序列化为一个Object(类型可以指定)并返回;
- postForEntity()将response序列化为ResponseEntity<T>类并返回(T是getForObject()返回的Object);
- postForEntity()实际上是将postForObject()的返回值进行二次加工,包装为ResponseEntity类;
⑤execute()与exchange()的区别:
- execute()将Http请求的response序列化为一个Object(类型可以指定)并返回;
- exchange()将response序列化为ResponseEntity<T>类并返回(execute()返回的Object);
- exchange()实际上是将execute()的返回值进行二次加工,包装为ResponseEntity类;
⑥RestTemplate中各类发送请求的方法最终都是执行execute()。它们只不过是对execute()的各类包装。
三、Get请求
注意,Get请求的请求参数必须先在URL中用占位符”{}”声明,调用方法时才能识别并传入。
1.getForObject
<T> T getForObject(String url, Class<T> responseType, Map<String, ?> uriVariables) throws RestClientException;
1)将Get请求的Response序列化为String
public String getForString(String mobile) {
String url = MXN_HOST + "/mobile_location/aim_mobile?mobile={mobile}&app_id={app_id}&app_secret={app_secret}"; //声明三个请求参数
Map<String, String> params = new HashMap<>();
params.put("mobile", mobile);
params.put("app_id", MXN_APP_ID);
params.put("app_secret", MXN_APP_SECRET);
return restTemplate.getForObject(url, String.class, params); //将请求的response序列化为String类
}
2)将Get请求的Response序列化为指定类
@Data
public class MXNResponse {
private int code;
private String msg;
}
@Data
public class MobileResponse extends MXNResponse{
private Data data;
@lombok.Data
static class Data {
private String mobile;
private String province;
private String carrier;
}
}
public MobileResponse getForResponse(String mobile) {
String url = MXN_HOST + "/mobile_location/aim_mobile?mobile={mobile}&app_id={app_id}&app_secret={app_secret}";
Map<String, String> params = new HashMap<>();
params.put("mobile", mobile);
params.put("app_id", MXN_APP_ID);
params.put("app_secret", MXN_APP_SECRET);
return restTemplate.getForObject(url, MobileResponse.class, params); //将请求的response序列化为MobileResponse类
}
2.getForEntity
public ResponseEntity<MobileResponse> getForEntity(String mobile) {
String url = MXN_HOST + "/mobile_location/aim_mobile?mobile={mobile}&app_id={app_id}&app_secret={app_secret}";
Map<String, String> params = new HashMap<>();
params.put("mobile", mobile);
params.put("app_id", MXN_APP_ID);
params.put("app_secret", MXN_APP_SECRET);
return restTemplate.getForEntity(url, MobileResponse.class, params);
}
3.带Header的Get
HttpEntity类有两个属性:headers和body,body是Post发送的body,因此只能将Get的请求参数写入URL中。
public ResponseEntity<MobileResponse> getForEntityWithHeader(String mobile) {
String url = MXN_HOST + "/mobile_location/aim_mobile?mobile=" + mobile; //请求参数写入URL
HttpHeaders headers = new HttpHeaders();
headers.add("app_id", MXN_APP_ID);
headers.add("app_secret", MXN_APP_SECRET);
HttpEntity httpEntity = new HttpEntity(headers);
return restTemplate.exchange(url, HttpMethod.GET, httpEntity, MobileResponse.class);
}
四、Post请求
RestTemplate中Post用法与Get一致,简单的用法不再赘述,只写一个终极Post。
终极Post
此Post请求需携带Header,且需要Post一张图片至服务器,最终将Response序列化为QRCodeResponse。
@Data
public class QRCodeResponse extends MXNResponse{
private Data data;
@lombok.Data
static class Data {
private String qrCodeUrl;
private String content;
private int type;
private String qrCodeBase64;
}
}
public ResponseEntity<QRCodeResponse> postForEntityWithHeader(String content) {
String url = MXN_HOST + "qrcode/create/logo";
FileSystemResource resource = new FileSystemResource(new File("D:/文件/壁纸/cat.png"));
MultiValueMap<String, Object> params = new LinkedMultiValueMap<>(); //只能是MultiValueMap,不能是Map
params.add("content", content);
params.add("size", 400);
params.add("logo_size", 120);
params.add("type", 0);
params.add("logo_img", resource);
HttpHeaders headers = new HttpHeaders();
headers.add("app_id", MXN_APP_ID);
headers.add("app_secret", MXN_APP_SECRET);
HttpEntity httpEntity = new HttpEntity(params, headers); //将Post的body和header塞进HttpEntity
return restTemplate.postForEntity(url, httpEntity, QRCodeResponse.class);
}
五、问题
1.将请求的Response序列化为指定类时,若因指定类中属性不符合驼峰命名而导致序列化失败,可在getter方法上使用@JsonProperty注解来映射。
2.实操时ResponseEntity<MobileResponse>的值。