工程结构
工程的主要目录结构如下:

Main.java
为函数的主入口,在main函数中需要配置三个参数:1.访问的函数名称 2.登录用户账户 3.登录用户密码
如图 args = new String[] {"WEB_CallSiteAPI","api","Change_Me"},
这里的 api, Change_Me 应该改成用户登录的用户名密码,如本次访问的环境为https://192.168.32.77,则应该改成该环境的登录用户名密码
/**
* 主函数入口
*
* @param args 用户输入的参数
*/
public static void main(String[] args) {
args = new String[]{"WEB_CallSiteAPI","api","Change_Me"};
if(args.length<=2){
return;
}
initSeesionId();
token = login(HttpClientUtil.sessionId, args);
if (TextUtils.isEmpty(token)) {
systemPrint("login failed");
return;
}
changeSeesionId();
callMethodByName(args);
}
HttpClientUtil.java
为http请求连接池工具类。HttpClientUtil.java内容如下:
package com.device.terminal;
import org.apache.http.*;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpRequestRetryHandler;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.*;
import org.apache.http.client.protocol.HttpClientContext;
import org.apache.http.config.Registry;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.conn.ConnectTimeoutException;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.conn.socket.LayeredConnectionSocketFactory;
import org.apache.http.conn.socket.PlainConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLContextBuilder;
import org.apache.http.conn.ssl.TrustStrategy;
import org.apache.http.conn.ssl.X509HostnameVerifier;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.entity.mime.HttpMultipartMode;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.protocol.HttpContext;
import org.apache.http.util.EntityUtils;
import org.json.JSONObject;
import javax.net.ssl.*;
import java.io.File;
import java.io.IOException;
import java.io.InterruptedIOException;
import java.io.UnsupportedEncodingException;
import java.net.UnknownHostException;
import java.nio.charset.Charset;
import java.security.KeyManagementException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.text.Normalizer;
import java.text.Normalizer.Form;
import java.util.Map;
/**
* 功能描述:连接池
* @since 2020/7/1
*/
public class HttpClientUtil {
/**
* 每一个请求都会用到的sessionid
*/
public static String sessionId;
/**
* HttpClient对象
*/
private static CloseableHttpClient httpclient = null;
// 这里就直接默认固定了,因为以下三个参数在新建的method中仍然可以重新配置并被覆盖.
static final int CONNECT_IONREQUEST_TIMEOUT = 5000; // ms毫秒,从池中获取链接超时时间
static final int CONNECTT_IMEOUT = 5000; // ms毫秒,建立链接超时时间
static final int SOCKET_TIMEOUT = 30000; // ms毫秒,读取超时时间
// 总配置,主要涉及是以下两个参数,如果要作调整没有用到properties会比较后麻烦,但鉴于一经粘贴,随处可用的特点,就不再做依赖性配置化处理了.
// 而且这个参数同一家公司基本不会变动.
static final int MAX_TOTAL = 50; // 最大总并发,很重要的参数
static final int MAX_PERROUTE = 10; // 每路并发,很重要的参数
// 正常情况这里应该配成MAP或LIST
// 细化配置参数,用来对每路参数做精细化处理,可以管控各ip的流量,比如默认配置请求baidu:80端口最大100个并发链接,
private static CloseableHttpClient getHttpClient() {
if (null == httpclient) {
synchronized (HttpClientUtil.class) {
if (null == httpclient) {
httpclient = init();
}
}
}
return httpclient;
}
/**
* 链接池初始化 这里最重要的一点理解就是. 让CloseableHttpClient 一直活在池的世界里, 但是HttpPost却一直用完就消掉.这样可以让链接一直保持着.
* @return 初始化
*/
private static CloseableHttpClient init() {
CloseableHttpClient newHttpclient = null;
// 设置连接池
PoolingHttpClientConnectionManager cm = getPoolingHttpClientConnectionManager();
// 请求重试处理
HttpRequestRetryHandler httpRequestRetryHandler = getHttpRequestRetryHandler();
// 配置请求的超时设置
RequestConfig requestConfig = RequestConfig.custom().setConnectionRequestTimeout(CONNECT_IONREQUEST_TIMEOUT)
.setConnectTimeout(CONNECTT_IMEOUT).setSocketTimeout(SOCKET_TIMEOUT).build();
newHttpclient = HttpClients.custom().setConnectionManager(cm).setDefaultRequestConfig(requestConfig)
.setRetryHandler(httpRequestRetryHandler).build();
return newHttpclient;
}
private static HttpRequestRetryHandler getHttpRequestRetryHandler() {
return new HttpRequestRetryHandler() {
@Override
public boolean retryRequest(IOException exception, int executionCount, HttpContext context) {
if (executionCount >= 2) { // 如果已经重试了2次,就放弃
return false;
}
if (exception instanceof NoHttpResponseException) { // 如果服务器丢掉了连接,那么就重试
return true;
}
if (exception instanceof SSLHandshakeException) { // 不要重试SSL握手异常
return true;
}
if (exception instanceof InterruptedIOException) { // 超时
return false;
}
if (exception instanceof UnknownHostException) { // 目标服务器不可达
return false;
}
if (exception instanceof ConnectTimeoutException) { // 连接被拒绝
return false;
}
if (exception instanceof SSLException) { // SSL握手异常
return false;
}
HttpClientContext clientContext = HttpClientContext.adapt(context);
HttpRequest request = clientContext.getRequest();
// 如果请求是幂等的,就再次尝试
if (!(request instanceof HttpEntityEnclosingRequest)) {
return true;
}
return false;
}};
}
private static PoolingHttpClientConnectionManager getPoolingHttpClientConnectionManager() {
LayeredConnectionSocketFactory sslsf = null;
try {
SSLContext sslContext = getSslContext();
sslsf = new SSLConnectionSocketFactory(sslContext, new X509HostnameVerifier() {
/**
* @param arg0 String
* @param arg1 SSLSession
* @return boolean
*/
public boolean verify(String arg0, SSLSession arg1) {
return true;
}
/**
*
* @param host String
* @param ssl SSLSocket
* @throws IOException
*/
public void verify(String host, SSLSocket ssl) throws IOException {
}
/**
*
* @param host String
* @param cert X509Certificate
* @throws SSLException
*/
public void verify(String host, X509Certificate cert) throws SSLException {
}
/**
*
* @param host String
* @param cns String[]
* @param subjectAlts String[]
* @throws SSLException 握手异常
*/
public void verify(String host, String[] cns, String[] subjectAlts) throws SSLException {
}
});
} catch (KeyManagementException e) {
} catch (NoSuchAlgorithmException e) {
} catch (KeyStoreException e) {
}
return getPoolingHttpClientConnectionManager(sslsf);
}
private static PoolingHttpClientConnectionManager getPoolingHttpClientConnectionManager(LayeredConnectionSocketFactory sslsf) {
if (null == sslsf) {
sslsf = SSLConnectionSocketFactory.getSocketFactory();
}
ConnectionSocketFactory plainsf = PlainConnectionSocketFactory.getSocketFactory();
Registry<ConnectionSocketFactory> registry = RegistryBuilder.<ConnectionSocketFactory>create()
.register("http", plainsf).register("https", sslsf).build();
PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager(registry);
// 将最大连接数增加
cm.setMaxTotal(MAX_TOTAL);
// 将每个路由基础的连接增加
cm.setDefaultMaxPerRoute(MAX_PERROUTE);
return cm;
}
private static SSLContext getSslContext() throws NoSuchAlgorithmException, KeyManagementException, KeyStoreException {
return new SSLContextBuilder().loadTrustMaterial(null, new TrustStrategy() {
@Override
public boolean isTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {
return true;
}
}).build();
}
/**
* Get请求
*
* @param uri 请求url
* @param headerMap 请求头集合
* @return JSONObject
*/
public static JSONObject get(String uri, Map<String, String> headerMap) {
return excute(uri, HttpGet.METHOD_NAME, null, headerMap);
}
/**
* Delete请求
*
* @param uri 请求url
* @param headerMap 请求头集合
* @return JSONObject
*/
public static JSONObject delete(String uri, Map<String, String> headerMap) {
return excute(uri, HttpDelete.METHOD_NAME, null, headerMap);
}
/**
* Put请求
*
* @param uri 请求url
* @param bodyParamsJsonObject body参数
* @param headerMap 请求头集合
* @return JSONObject
*/
public static JSONObject put(String uri, JSONObject bodyParamsJsonObject, Map<String, String> headerMap) {
return excute(uri, HttpPut.METHOD_NAME, bodyParamsJsonObject, headerMap);
}
/**
* Post请求
*
* @param uri 请求url
* @param bodyParamsJsonObject body参数
* @param headerMap 请求头集合
* @return JSONObject
*/
public static JSONObject post(String uri, JSONObject bodyParamsJsonObject, Map<String, String> headerMap) {
return excute(uri, HttpPost.METHOD_NAME, bodyParamsJsonObject, headerMap);
}
/**
* @param uri 请求url
* @param methodType 请求方法类型
* @param bodyParamsJsonObject body参数
* @param headerMap 请求头集合
* @return 返回json字符串
*/
public static JSONObject excute(String uri, String methodType, JSONObject bodyParamsJsonObject,
Map<String, String> headerMap) {
uri = Normalizer.normalize(uri, Form.NFKC);
// 1.创建请求对象
HttpRequestBase httpRequest = getHttpRequest(uri, methodType);
// 2.设置请求头Header
if (headerMap != null && !headerMap.isEmpty()) {
for (Map.Entry<String, String> entry : headerMap.entrySet()) {
httpRequest.setHeader(entry.getKey(), entry.getValue());
}
}
CloseableHttpResponse response = null;
try {
// 3.设置Body请求参数。只对put和post方法有效
setBody(methodType, bodyParamsJsonObject, (HttpEntityEnclosingRequestBase) httpRequest);
// 4.发起请求并解析响应
response = getHttpClient().execute(httpRequest);
if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
if (isNeedParseHeader(uri)) {
sessionId = response.getFirstHeader("Set-Cookie").getValue().split(";")[0];
} else {
HttpEntity entity = response.getEntity();
if (null != entity) {
String string = EntityUtils.toString(entity, "UTF-8");
JSONObject jsonObject = new JSONObject(string);
return jsonObject;
}
}
} else {
return null;
}
} catch (UnsupportedEncodingException e) {
} catch (ClientProtocolException e) {
} catch (Exception e) {
} finally {
if (null != response) {
try {
EntityUtils.consume(response.getEntity());
response.close();
} catch (IOException e) {
}
}
}
return null;
}
private static HttpEntity resEntity;
/**
* 上传文件
*
* @throws ParseException
* @throws IOException
*/
public static String upgradeSystem(String url, String token, String filePath) throws ParseException, IOException {
try {
// 要上传的文件的路径
// 把一个普通参数和文件上传给下面这个地址 是一个servlet
HttpPost httpPost = new HttpPost(url);
httpPost.setHeader("acCSRFToken", token);
String sessionIdNew = sessionId.split(";")[0];
httpPost.setHeader("Cookie", sessionIdNew);
httpPost.setHeader("X-Requested-With", "XMLHttpRequest");
httpPost.setHeader("Connection", "keep-alive");
// 把文件转换成流对象FileBody
File file = new File(filePath);
MultipartEntityBuilder mutiEntity = MultipartEntityBuilder.create();
mutiEntity.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
mutiEntity.addBinaryBody("uploadFile", file, ContentType.create("application/octet-stream"), "cloudlink.dat");
HttpEntity reqEntity = mutiEntity.build();
httpPost.setEntity(reqEntity);
// 发起请求 并返回请求的响应
CloseableHttpResponse response = getHttpClient().execute(httpPost);
try {
resEntity = response.getEntity();
if (resEntity != null) {
// 打印响应长度
// 打印响应内容
String result=EntityUtils.toString(resEntity, Charset.forName("UTF-8"));
return result;
}else{
return null;
}
} finally {
// 销毁
EntityUtils.consume(resEntity);
}
} finally {
}
}
private static void setBody(String methodType, JSONObject bodyParamsJsonObject, HttpEntityEnclosingRequestBase httpRequest) throws UnsupportedEncodingException {
if (bodyParamsJsonObject != null && !bodyParamsJsonObject.isEmpty()
&& (HttpPut.METHOD_NAME.equalsIgnoreCase(methodType)
|| HttpPost.METHOD_NAME.equalsIgnoreCase(methodType))) {
String bodyParams = bodyParamsJsonObject.toString().trim();
if (!bodyParams.isEmpty()) {
HttpEntity entity = new StringEntity(bodyParams);
httpRequest.setEntity(entity);
}
}
}
private static HttpRequestBase getHttpRequest(String uri, String methodType) {
HttpRequestBase httpRequest = null;
if (HttpDelete.METHOD_NAME.equalsIgnoreCase(methodType)) {
httpRequest = new HttpDelete(uri);
} else if (HttpPost.METHOD_NAME.equalsIgnoreCase(methodType)) {
httpRequest = new HttpPost(uri);
} else if (HttpPut.METHOD_NAME.equalsIgnoreCase(methodType)) {
httpRequest = new HttpPut(uri);
} else {
httpRequest = new HttpGet(uri);
}
return httpRequest;
}
private static boolean isNeedParseHeader(String uri) {
return uri.contains("WEB_RequestSessionIDAPI") || uri.contains("WEB_ChangeSessionIDAPI");
}
}