背景
昨天在公司做项目的时候要在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增删改查四种请求方式,后来觉得不妥改成了一个通用的方法。
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);
}
}
具体的调用
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 这个类。
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的详解) java SSLSocket的详解