工程结构
工程的主要目录结构如下:
Main.java
为函数的主入口,在main函数中需要配置三个参数:1.访问的函数名称 2.登录用户账户 3.登录用户密码
如图 args = new String[] {"WEB_CallSiteAPI","api","Change_Me"},
![](https://support.huaweicloud.com/ideahub-api/public_sys-resources/note_3.0-zh-cn.png)
这里的 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"); } }