Article Directory
- Use of HttpClient and RestTemplate (detailed comparison)
Use of HttpClient and RestTemplate (detailed comparison)
Among the interfaces allocated today, there are a few that need to call third-party interface data. I don’t know anything about it, starting from scratch
One, HttpClient
First import dependencies
<!-- https://mvnrepository.com/artifact/org.apache.httpcomponents/httpclient -->
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.13</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.testng/testng -->
<dependency>
<groupId>org.testng</groupId>
<artifactId>testng</artifactId>
<version>7.0.0</version><!--注释掉spring自带的依赖, 最新版本7.3.0会报错, 选了低版本的7.0.0-->
<scope>test</scope>
</dependency>
1. get without parameters
@Test //get 无参
public void doGet() {
String uri = "https://openapi.chanjet.com/auth/refreshToken?grantType=refresh_token&appKey=K2vIOn4m&refreshToken=1";
// 1.创建Http客户端
CloseableHttpClient httpClient = HttpClientBuilder.create().build();
// 2.创建Get请求
HttpGet request = new HttpGet(uri);
// 3.响应模型
CloseableHttpResponse response = null;
try {
// 3.执行Get请求
response = httpClient.execute(request);
// 4.从响应模型中获取响应实体
HttpEntity responseEntity = response.getEntity();
System.out.println("响应状态为:" + response.getStatusLine());
if (responseEntity != null) {
System.out.println("响应内容长度为:" + responseEntity.getContentLength());
System.out.println("响应内容为:" + EntityUtils.toString(responseEntity, StandardCharsets.UTF_8));
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (httpClient != null) {
httpClient.close();
}
if (response != null) {
response.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
Print output:
2. get with parameters
Request address https://dev.chanjet.com/docs/common/app_settled/app_settled_auth
@Test //get 有参
public void doGetParam() {
// 1.创建Http客户端
CloseableHttpClient httpClient = HttpClientBuilder.create().build();
// 2.封装参数
List<NameValuePair> params = new ArrayList<>();
params.add(new BasicNameValuePair("grantType", "authorization_code"));
params.add(new BasicNameValuePair("appKey", "K2vIOn4m"));
params.add(new BasicNameValuePair("redirectUri", "https://baidu.com"));
params.add(new BasicNameValuePair("code", "1"));
// 3.创建uri
URI uri = null;
try {
uri = new URIBuilder().setScheme("https")
.setHost("openapi.chanjet.com")
.setPath("/auth/getToken")
.setParameters(params).build();
} catch (URISyntaxException e) {
e.printStackTrace();
}
// 4.创建请求
HttpGet request = new HttpGet(uri);
CloseableHttpResponse response = null;
try {
// 5.执行Get请求
response = httpClient.execute(request);
// 6.获取响应实体
HttpEntity entity = response.getEntity();
System.out.println("响应状态为:" + response.getStatusLine());
if (entity != null) {
System.out.println("响应内容长度为:" + entity.getContentLength());
String entityStr = EntityUtils.toString(entity, StandardCharsets.UTF_8);
System.out.println("响应内容为:" + entityStr);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (httpClient != null) {
httpClient.close();
}
if (response != null) {
response.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
Print output:
3. Post object
@Test //post 对象
public void postObject() {
// 如果有普通参数,uri 改成 URIBuilder
String uri = "http://localhost:8080/people/addPeople";
// 创建Http客户端
CloseableHttpClient httpClient = HttpClientBuilder.create().build();
// 创建Post请求
HttpPost request = new HttpPost(uri);
request.setHeader("Content-Type", "application/json;charset=utf8");
// 添加json对象
People people = new People();
people.setName("张飞");
people.setCreateTime(LocalDateTime.now());
String jsonString = JSON.toJSONString(people);
StringEntity entity = new StringEntity(jsonString, "UTF-8");
httpPost.setEntity(entity);
// 响应模型
CloseableHttpResponse response = null;
try {
// 执行Post请求
response = httpClient.execute(request);
// 从响应模型中获取响应实体
HttpEntity responseEntity = response.getEntity();
System.out.println("响应状态为:" + response.getStatusLine());
if (responseEntity != null) {
System.out.println("响应内容长度为:" + responseEntity.getContentLength());
System.out.println("响应内容为:" + EntityUtils.toString(responseEntity, StandardCharsets.UTF_8));
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (httpClient != null) {
httpClient.close();
}
if (response != null) {
response.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
Request interface:
@ApiOperation(value = "添加", notes = "添加用户")
@PostMapping("/addPeople")
public String addPeople(@RequestBody People people) {
int row = peopleService.add(people);
return row == 1 ? "添加成功" : "添加失败";
}
Print output:
4. Close the console log
Create logback.xml under resource
<?xml version="1.0" encoding="UTF-8"?>
<configuration debug="false">
<!-- definition of appender STDOUT -->
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%-4relative [%thread] %-5level %logger{35} - %msg %n</pattern>
</encoder>
</appender>
<root level="ERROR">
<!-- appender referenced after it is defined -->
<appender-ref ref="STDOUT"/>
</root>
</configuration>
Two, RestTemplate
1. How to use
-
get request
-
getForObject()
sends an HTTP GET request, and the returned request body will be mapped to an object -
getForEntity()
sends an HTTP GET request, and the returned ResponseEntity contains the object mapped into the response body
-
RestTemplate restTemplate = new RestTemplate();
ResponseEntity<String> entity = restTemplate.getForEntity(uri, String.class);
// TODO 处理响应
- Post request method
-
postForEntity()
POSTs data to a URL and returns a ResponseEntity containing an object, which is mapped from the response body. -
postForObject()
POSTs data to a URL and returns an object formed according to the response body matching. -
postForLocation()
POST data to a URL and return the URL of the newly created resource
-
RestTemplate restTemplate = new RestTemplate();
// headers
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON_UTF8);
HttpEntity<Object> objectHttpEntity = new HttpEntity<>(headers);
ResponseEntity<String> entity = restTemplate.postForEntity(uri, request, String.class);
// TODO 处理响应
//设置超时时间
SimpleClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory();
requestFactory.setConnectTimeout(60 * 1000);
requestFactory.setReadTimeout(60 * 1000);
restTemplate.setRequestFactory(requestFactory);
Only post requests have header parameters, get can be replaced by exchange
// herders
HttpHeaders httpHeaders = new HttpHeaders();
httpHeaders.setContentType(MediaType.APPLICATION_JSON_UTF8);
httpHeaders.add("openToken", openToken);
httpHeaders.add("appKey", chanJetKey);
httpHeaders.add("appSecret", chanJetSecret);
HttpEntity<JSONObject> request = new HttpEntity<>(httpHeaders);
4) Restful style url parameters
uri = "http://localhost:8080/people/selectById/{id}";
// params
Map<String, String> param = new HashMap<>();
param.put("id", XXX);
ResponseEntity<String> entity = restTemplate.getForEntity(uri, String.class, param);
uri = "http://localhost:8080/people/selectById?id={id}&XXX={XXX}";
// params
Map<String, String> params = new HashMap<>();
params.put("id", XXX);
params.put("XXX", XXX);
ResponseEntity<String> entity = restTemplate.getForEntity(uri, String.class, params);
// body post的请求体
JSONObject json = new JSONObject();
json.put("XXX", XXX);
json.put("XXX", XXX);
HttpEntity<JSONObject> request = new HttpEntity<>(json, httpHeaders);
ResponseEntity<String> entity = restTemplate.postForEntity(uri, request, String.class);
7) Call the third-party interface
//调用第三方api 若是服务返回状态码不为200,默认会执行DefaultResponseErrorHandler,返回 401 Unauthorized: [no body]
restTemplate.setRequestFactory(new HttpComponentsClientHttpRequestFactory());
try {// 发起请求
ResponseEntity<String> entity = restTemplate.exchange(uri, HttpMethod.GET, request, String.class, params);
// TODO 状态码200,处理业务逻辑
} catch (HttpClientErrorException e) {
// TODO 状态码非200
byte[] responseBodyAsByteArray = e.getResponseBodyAsByteArray();// 返回的响应
String bodyAsString = null;
try {
bodyAsString = new String(responseBodyAsByteArray, "UTF-8");
} catch (UnsupportedEncodingException unsupportedEncodingException) {
unsupportedEncodingException.printStackTrace();
}
// TODO...
}
The default character encoding of different Spring versions is different
- spring-framework.version 5.2.9
- spring-framework.version 4.3.9
2. Use case
@Test // get 无参
protected void get() {
RestTemplate restTemplate = new RestTemplate();
String uri = "http://localhost:8080/people/selectAll";
//1.getForObject, 将返回的请求体 映射为一个对象
String result = restTemplate.getForObject(uri, String.class);
System.out.println(result);
//2.getForEntity, 返回的ResponseEntity包含了响应体所映射成的对象
ResponseEntity<String> entity = restTemplate.getForEntity(uri, String.class);
System.out.println(entity);
}
Printout
{查询成功:People(id=1, name=赵云, createTime=2020-10-19T20:39:14)}
<200,{查询成功:People(id=1, name=赵云, createTime=2020-10-19T20:39:14)},[Content-Type:"text/plain;charset=UTF-8", Content-Length:"72", Date:"Wed, 21 Oct 2020 14:40:08 GMT", Keep-Alive:"timeout=60", Connection:"keep-alive"]>
@Test // get restful风格 @PathVariable
protected void getRestful1() {
RestTemplate restTemplate = new RestTemplate();
String uri = "http://localhost:8080/people/selectById/{1}";
String result = restTemplate.getForObject(uri, String.class, 1);
System.out.println(result);
}
@Test // get restful风格 @PathVariable
protected void getParam() {
RestTemplate restTemplate = new RestTemplate();
String uri = "http://localhost:8080/people/selectById/{id}";
Map<String, String> params = new HashMap();
params.put("id", "1");
String result = restTemplate.getForObject(uri, String.class, params);
System.out.println(result);
}
Print output:
{查询成功:People(id=1, name=赵云, createTime=2020-10-19T20:39:14)}
Request interface:
@ApiOperation(value = "查询", notes = "通过id查询,restful风格")
@GetMapping("/selectById/{id}")
public String findById2(@PathVariable("id") Integer id) {
People people = peopleService.findById(id);
return people == null ? "{message:查询失败,人员不存在}" : "{查询成功:" + people + "}";
}
3)☆ get headers @PathVariable @RequestParam
The get request has no headers, use exchange instead
/**
* 畅捷通接口说明 应收统计表 https://dev.chanjet.com/docs/accounting/bb/ystjb
*/
@Test // get 带参数 @PathVariable @RequestParam
protected void yftjb() {
ResponseResultNew resultNew = new ResponseResultNew(0,"请求成功");
String uri = "https://sandbox-openapi.chanjet.com/accounting/gl/statistics/pay/{bookid}?period={period}";
RestTemplate restTemplate = new RestTemplate();
//调用第三方api 若是服务返回状态码不为200,默认会执行DefaultResponseErrorHandler
restTemplate.setRequestFactory(new HttpComponentsClientHttpRequestFactory());
// headers
HttpHeaders httpHeaders = new HttpHeaders();
httpHeaders.setContentType(MediaType.APPLICATION_JSON_UTF8);
httpHeaders.add("openToken", access_token);
httpHeaders.add("appKey", chanJetKey);
httpHeaders.add("appSecret", chanJetSecret);
// path
Map<String, String> params = new HashMap<>();
params.put("bookid", bookid);
params.put("period", period);
HttpEntity<Object> request = new HttpEntity<>(httpHeaders);
try {// 发起请求
ResponseEntity<String> entity = restTemplate.exchange(uri, HttpMethod.GET, request, String.class, params);
// TODO 状态码200,处理业务逻辑
YDZResponse ydzResponse = JSON.parseObject(entity.getBody(), YDZResponse.class);
if (ydzResponse.getCode().equals("200")) {
// TODO...
} else {
resultNew.setMessage(ydzResponse.getMsg()); // 返回错误信息
}
} catch (HttpClientErrorException e) {
// TODO: 状态码非200
byte[] responseBody = e.getResponseBodyAsByteArray();
String bodyAsString = getResponseBodyAsString(responseBody, "UTF-8");
YDZResponse ydzResponse = JSON.parseObject(bodyAsString, YDZResponse.class);
resultNew.setCode(Integer.valueOf(ydzResponse.getCode()));
resultNew.setMessage(ydzResponse.getMessage()); // 返回错误信息
}
log.info("执行结果 = {}", resultNew);
return resultNew;
}
Print output:
执行结果: ResponseResultNew(code=50004, message=appSecret不正确, data=, timestamp=1603869867229)
===============================================
Default Suite
Total tests run: 1, Passes: 1, Failures: 0, Skips: 0
===============================================
@Test // post 带参数 @RequestParam
public void post() {
RestTemplate client = new RestTemplate();
// headers
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
// params
MultiValueMap<String, String> params = new LinkedMultiValueMap<>();
params.add("id", "1");
HttpEntity<MultiValueMap<String, String>> request = new HttpEntity<>(params, headers);
ResponseEntity<People> response = client.postForEntity("http://localhost:8080/people/selectById", request, People.class);
System.out.println(response.getBody());
}
Print output:
People(id=1, name=赵云, createTime=2020-08-05T12:53:39)
Request address:
@ApiOperation(value = "查询", notes = "通过id查询(Post)")
@PostMapping("/selectById")
public People findByIdPost(@RequestParam Integer id) {
People people = peopleService.findById(id);
return people;
}
@Test // post 带参数 @RequestBody
public void postJSON() {
RestTemplate client = new RestTemplate();
// headers
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
// body
JSONObject json = new JSONObject();
json.put("id",1);
// request
HttpEntity<JSONObject> request = new HttpEntity<>(json, headers);
ResponseEntity<String> response = client.postForEntity("http://localhost:8080/people/selectByPeople", request, String.class);
System.out.println(response.getBody());
}
Print output:
查询成功
Request interface:
@ApiOperation(value = "查询", notes = "通过People查询")
@PostMapping("/selectByPeople")
public String findByPeople(@RequestBody People people) {
People people2 = peopleService.findById(people.getId());
return people2 == null ? "查询失败" : "查询成功";
}
6)☆ post @RequestParam @RequsetBody
/**
* 易代账API https://dev.chanjet.com/docs/finance/ydzpj/fp
*/
@Test // post @RequestBody, @RequestParam
public void addInvoice() {
ResponseResultNew resultNew = new ResponseResultNew(0, "请求成功");
String uri1 = "https://openapi.chanjet.com/accounting/invoice/Invoice/{bookid}";
String uri2 = "https://sandbox-openapi.chanjet.com/accounting/invoice/Invoice/{bookid}";
RestTemplate client = new RestTemplate();
//调用第三方api 若是服务返回状态码不为200,默认会执行DefaultResponseErrorHandler: 401 Unauthorized: [no body]
client.setRequestFactory(new HttpComponentsClientHttpRequestFactory());
// herders
HttpHeaders httpHeaders = new HttpHeaders();
httpHeaders.setContentType(MediaType.APPLICATION_JSON);
httpHeaders.add("openToken", "openToken");
httpHeaders.add("appKey", "appKey");
httpHeaders.add("appSecret", "appSecret");
// params
Map<String, String> param = new HashMap<>();
param.put("bookid", "1");
// body
JSONObject jsonObject = new JSONObject();
jsonObject.put("custVendor", "");
//...
HttpEntity<String> request = new HttpEntity<>(jsonObject.toJSONString(), httpHeaders);
try {// 发起请求
ResponseEntity<String> entity = client.postForEntity(uri2, request, String.class, param);
// TODO 状态码200, 处理业务逻辑
log.info("响应体 = {}", entity.getBody());
YDZResponse ydzResponse = JSON.parseObject(entity.getBody(), YDZResponse.class);
if (ydzResponse.getCode() == null) {
resultNew.setData(JSON.toJSON(entity.getBody()));
} else {
resultNew.setCode(1);
resultNew.setMessage(ydzResponse.getMsg()); // 返回错误信息
}
} catch (HttpClientErrorException e) {
// TODO 状态码非200
String bodyAsString = e.getResponseBodyAsString();// spring5.2.9默认字符UTF-8
YDZResponse ydzResponse = JSON.parseObject(bodyAsString, YDZResponse.class);
System.out.println("返回结果: "+ydzResponse);
resultNew.setCode(Integer.valueOf(ydzResponse.getCode()));
resultNew.setMessage(ydzResponse.getMessage()); // 返回错误信息
}
System.out.println(resultNew);
}
Print output:
返回结果: YDZResponse(code=50004, requestId=6b1fffed-232232, message=appSecret不正确, status=401, timestamp=2020-10-22T15:14:38.336)
ResponseResultNew(code=1, message=appSecret不正确, data=, timestamp=1603350883894)
===============================================
Default Suite
Total tests run: 1, Passes: 1, Failures: 0, Skips: 0
===============================================