更新时间:2023-01-06 GMT+08:00
分享

工程结构

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

图1 工程目录结构

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");
    }
}
分享:

    相关文档

    相关产品