Java通过HttpClient的请求封装

背景

昨天在公司做项目的时候要在Java代码里面调用网管系统的Restful接口返回Json数据,然后简单的看了一下关于Java中发起Http或者Https请求的几种方式,总结一下。

方法

目前JAVA实现HTTP请求的方法用的最多的有两种:一种是通过HTTPClient这种第三方的开源框架去实现。HTTPClient对HTTP的封装性比较不错,通过它基本上能够满足我们大部分的需求,HttpClient3.1 是 org.apache.commons.httpclient下操作远程 url的工具包,虽然已不再更新,但实现工作中使用httpClient3.1的代码还是很多,HttpClient4.5是org.apache.http.client下操作远程 url的工具包,最新的;另一种则是通过HttpURLConnection去实现,HttpURLConnection是JAVA的标准类,是JAVA比较原生的一种实现方式。

我采用的是org.apache.http.client这个包来做Http请求。然后最开始分别实现了Get,Post,Put,Delete增删改查四种请求方式,后来觉得不妥改成了一个通用的方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
public synchronized String getCall(String url, String contentType,
Map<String, String> addRequestHeader)
throws NbiException {

log.debug("Get Rest URL = " + url);

HttpGet getRequest = new HttpGet(url);
if (!StringUtils.isEmpty(contentType)) {
getRequest.addHeader("Accept", contentType);
}

return call(addRequestHeader, getRequest);
}

public synchronized String postCall(String url, String inputParam,
String contentType, Map<String, String> addRequestHeader)
throws NbiException {
log.debug("Post Rest URL = " + url);

HttpPost postRequest = new HttpPost(url);
StringEntity input = null;
try {
if(!StringUtils.isEmpty(inputParam)){
input = new StringEntity(inputParam);
input.setContentType(contentType);
}
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
postRequest.setEntity(input);

return call(addRequestHeader, postRequest);
}

public synchronized String deleteCall(String url) throws NbiException {
log.debug("Delete Rest URL = " + url);

HttpDelete deleteRequest = new HttpDelete(url);

return call(null, deleteRequest);
}

public synchronized String putCall(String url, String inputParam,
String contentType, Map<String, String> addRequestHeader)
throws NbiException {

log.debug("Put Rest URL = " + url);

HttpPut httpPut = new HttpPut(url);
StringEntity input = null;
try {
if(StringUtils.isNotEmpty(inputParam)){
input = new StringEntity(inputParam);
input.setContentType(contentType);
}
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
httpPut.setEntity(input);

return call(addRequestHeader, httpPut);
}

/**
* @Author: xingrui
* @Description: support: get, post, put, delete
* @Date: 15:42 2018/6/22
*/
public String call(Map<String, String> addRequestHeader,
HttpRequestBase request) throws NbiException {
StringBuilder sb = new StringBuilder();

try {
if (addRequestHeader != null){
for (String paramKey : addRequestHeader.keySet()) {
String paramValue = addRequestHeader.get(paramKey);
request.setHeader(paramKey, paramValue);
}
}

HttpResponse response = this.execute(request);
checkHttpStatus(response);

BufferedReader br = new BufferedReader(new InputStreamReader(
(response.getEntity().getContent())));

String output;
while ((output = br.readLine()) != null) {
sb.append(output + "\n");
}
return sb.toString();

} catch (Exception e) {
log.error(e);
throw ExceptionConverter.convertToInternalException(e);
}
}

具体的调用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
public synchronized boolean login()
throws NbiException {
String url = "https://localhost/xxx/xxx";
String username = "xxxx";
String password = "xxxx";
log.debug("Get Token Url: " + url);

String originalCredentials = username + ":" + password;
String base64Credentials = new String(Base64
.encodeBase64(originalCredentials.getBytes()));
RestfulConstant.BASIC_TOKEN = "Basic " + base64Credentials;

String inputParams = "{\"grant_type\":\"client_credentials\"}";
Map<String, String> headers = new HashMap<>();
headers.put("Authorization", RestfulConstant.BASIC_TOKEN);
headers.put("Content-Type", "application/json");

String out = postCall(url, inputParams,
"application/json", headers);
JsonNode jsonNode = JsonUtil.toNode(out);

RestfulConstant.ACCESS_TOKEN = jsonNode.get("access_token").asText();
RestfulConstant.REFRESH_TOKEN = jsonNode.get("refresh_token").asText();

return true;
}

根据实际需要自由更改代码即可。

发起Https请求

Https就是在Http的基础上使用了SSLSocket安全套接字的请求,使用SSL或TLS协议的安全套接字。

如果服务器中没有相关链接的SSL证书,就不能信任此链接,访问不到。所以我们要在请求之前加一个信任管理器,去实现X509TrustManager 这个类。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
public static void main(String[] args) throws Exception {    
X509TrustManager x509m = new X509TrustManager() {

@Override
public X509Certificate[] getAcceptedIssuers() {
return null;
}

@Override
public void checkServerTrusted(X509Certificate[] chain,
String authType) throws CertificateException {
}

@Override
public void checkClientTrusted(X509Certificate[] chain,
String authType) throws CertificateException {
}
};
// 获取一个SSLContext实例
SSLContext s = SSLContext.getInstance("SSL");
// 初始化SSLContext实例
s.init(null, new TrustManager[] { x509m },
new java.security.SecureRandom());
// 打印这个SSLContext实例使用的协议
System.out.println("缺省安全套接字使用的协议: " + s.getProtocol());
// 获取SSLContext实例相关的SSLEngine
SSLEngine e = s.createSSLEngine();
System.out
.println("支持的协议: " + Arrays.asList(e.getSupportedProtocols()));
System.out.println("启用的协议: " + Arrays.asList(e.getEnabledProtocols()));
System.out.println("支持的加密套件: "
+ Arrays.asList(e.getSupportedCipherSuites()));
System.out.println("启用的加密套件: "
+ Arrays.asList(e.getEnabledCipherSuites()));
}

然后就可以愉快的发起Https请求了。

参考文章

https://www.cnblogs.com/hhhshct/p/8523697.html Java实现Http请求的三种方式

https://blog.csdn.net/guozili1/article/details/53995121 如何在java中发起http和https请求

https://blog.csdn.net/qq_31694651/article/details/52372341 java SSLSocket的详解

zhangxingrui wechat
欢迎您扫一扫上面的微信公众号,订阅我的博客!