http client 工具類

RegPoate 8年前發布 | 948 次閱讀 Java HttpClient

HttpConn    

public class HttpConn {

    private final static Logger logger = LoggerFactory.getLogger(HttpConn.class); 

    //MIME-TYPE
    public static final String MIME_TYPE_PLAIN = "text/plain";
    public static final String MIME_TYPE_XML = "text/xml";
    public static final String MIME_TYPE_HTML = "text/html";
    public static final String MIME_TYPE_JSON = "application/json";

    //REQUEST METHOD
    public static final String METHOD_GET = "GET"; 
    public static final String METHOD_POST = "POST";

    //HTTP STATUS
    public static final int HTTP_RESSTATUS_SUCCESS = 200;
    public static final int HTTP_RESSTATUS_NOT_FOUND = 404;

    //Default Values
    public static final String DETAULT_ENCODING = "UTF-8";
    public static final Charset DEFAULT_CHARSET = Consts.UTF_8;  
    public static final int REQUEST_TIMEOUT = 5 * 1000; // 請求超時時間
    public static final int CONNECTION_TIMEOUT = 10 * 1000; // 連接超時時間  
    public static final int SOCKET_TIMEOUT = 10 * 1000; // 數據傳輸超時  
    public static final int POOL_MAX_SIZE = 200; // 連接池最大連接數
    public static final int POOL_MAX_SIZE_PER_ROUTER = 200; // 每個路由最大連接數

    //Request Params
    private String reqUrl;
    private String reqMethod;
    private Map<String, String> reqParams;//請求參數
    private String reqPostString;//post內容
    private String reqCharset;
    private String reqContentType;//請求內容類型
    private String reqFileKey;//上傳文件在form-data的key值
    private String reqFilePath;//上傳的文件路徑
    //Response Infos
    private int resCode;
    private boolean resSuccess = false;//是否正常響應,即返回200
    private String resStatues;
    private long resLength;
    private String resEncoding;
    private String resContentType;
    private String resBody;
    private String resFilePath;
    private boolean resFileSaveSuccess = false;//響應文件是否保存成功

    //
    private static PoolingHttpClientConnectionManager cm = null;  
    private static CloseableHttpClient client = null;  

    private HttpUriRequest request = null;
    private CloseableHttpResponse response = null;

    /**
     * 初始化連接池與Client
     * */
    static{
        try {
            // 初始化SSL環境
            SSLContextBuilder sslContextbuilder = new SSLContextBuilder();  
            sslContextbuilder.useTLS();  
            SSLContext sslContext = sslContextbuilder.loadTrustMaterial(null, new TrustStrategy() {  
                // 信任所有  
                public boolean isTrusted(X509Certificate[] chain, String authType) throws CertificateException  
                {  
                    return true;  
                }  

            }).build();

            //注冊協議
            ConnectionSocketFactory plainCSF = PlainConnectionSocketFactory.INSTANCE;
            ConnectionSocketFactory sslCSF = new SSLConnectionSocketFactory(sslContext, SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
            Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory> create()  
                    .register("http", plainCSF)  
                    .register("https", sslCSF)
                    .build(); 

            // 創建連接池
            cm = new PoolingHttpClientConnectionManager(socketFactoryRegistry); 

            // 初始化Socket配置
            SocketConfig socketConfig = SocketConfig.custom()
                                        .setTcpNoDelay(true)
                                        .build();  
            cm.setDefaultSocketConfig(socketConfig);  

            // Http消息約束
//            MessageConstraints messageConstraints = MessageConstraints.custom().
//                          setMaxHeaderCount(200).
//                          setMaxLineLength(2000).build();  

            // http連接設置 
            ConnectionConfig connectionConfig = ConnectionConfig.custom()  
                    .setMalformedInputAction(CodingErrorAction.IGNORE)  //忽略不合法的輸入
                    .setUnmappableInputAction(CodingErrorAction.IGNORE)   //忽略不匹配的輸入
                    .setCharset(DEFAULT_CHARSET)  
//                    .setMessageConstraints(messageConstraints)
                    .build();  

            cm.setDefaultConnectionConfig(connectionConfig);  
            cm.setMaxTotal(POOL_MAX_SIZE);  //連接池最大連接數
            cm.setDefaultMaxPerRoute(POOL_MAX_SIZE_PER_ROUTER);  //每個路由最大連接數  

            // 請求設置
            RequestConfig requestConfig = RequestConfig.custom()
                                            .setConnectionRequestTimeout(REQUEST_TIMEOUT) //請求超時
                                            .setSocketTimeout(SOCKET_TIMEOUT)  //Socket超時
                                            .setConnectTimeout(CONNECTION_TIMEOUT)  //連接超時
                                            .build();

            // 創建HttpClient  
            client = HttpClients.custom()
                        .disableRedirectHandling()
                        .setConnectionManager(cm)
                        .setDefaultRequestConfig(requestConfig)
                        .build();  

            // 啟動連接池監控線程
            HttpConnMonitorThread monitor = new HttpConnMonitorThread(cm);
            monitor.start();
        } catch (KeyManagementException e) {
            logger.error("", e);
        } catch (NoSuchAlgorithmException e) {
            logger.error("", e);
        } catch (KeyStoreException e) {
            logger.error("", e);
        }  
    }

    /**
     * 設置請求、連接、獲取響應
     * */
    public boolean connect() throws ParseException, UnsupportedEncodingException, IOException {
        try {
            setReqInfo();
            if(CommonUtil.isEmpty(this.request)){
                throw new RuntimeException("HttpConn ,初始化請求失敗!");
            }
            //執行連接,返回響應
            HttpClientContext context = HttpClientContext.create();
            this.response = client.execute(this.request, context);
            //處理響應結果
            if(CommonUtil.isEmpty(this.response)){
                throw new RuntimeException("HttpConn ,響應獲取失敗!");
            }
            setResInfo();
        } finally {
            try {
                if(this.response != null)
                    this.response.close();
            } catch (IOException e) {
                logger.error(e.getMessage());
            }
        } 
        return true;
    }

    /**
     * 設置請求參數
     * */
    private void setReqInfo() throws ParseException, UnsupportedEncodingException, IOException{
        if(!CommonUtil.isEmpty(this.reqFilePath))//上傳,使用POST
            this.reqMethod = METHOD_POST;
        if(!CommonUtil.isEmpty(this.reqPostString))//post參數,使用POST
            this.reqMethod = METHOD_POST;
        if(CommonUtil.isEmpty(this.reqMethod))
            this.reqMethod = METHOD_GET;

        if(CommonUtil.isEmpty(this.reqContentType)) //設置內容類型,默認為text/plain
            this.reqContentType = MIME_TYPE_PLAIN;
        if(CommonUtil.isEmpty(this.reqCharset))  //設置編碼格式
            this.reqCharset = DETAULT_ENCODING;

        //將請求參數轉換為字符串形式
        String paramString = null;
        if(!CommonUtil.isEmpty(this.reqParams)){
            List<NameValuePair> paramList = new ArrayList<NameValuePair>();
            Iterator<Map.Entry<String, String>> it = this.reqParams.entrySet().iterator();
            while(it.hasNext()){
                Map.Entry<String, String> entry = it.next();
                paramList.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));
            }
            paramString = EntityUtils.toString(new UrlEncodedFormEntity(paramList, this.reqCharset == null?DETAULT_ENCODING : this.reqCharset));
        }

        //GET請求
        if(this.reqMethod.equalsIgnoreCase(METHOD_GET)){
            //設置請求參數
            if(!CommonUtil.isEmpty(paramString)){
                if(this.reqUrl.trim().lastIndexOf("?") == -1){
                    this.reqUrl += "?" + paramString;
                }else{
                    this.reqUrl += "&" + paramString;
                }
            }
            //創建Get請求
            HttpGet get = new HttpGet(this.reqUrl);
            this.request = get;
        }
        //POST請求
        else if(this.reqMethod.equals(METHOD_POST)){
            HttpPost post = new HttpPost(this.reqUrl);
            //post請求參數
            if(!CommonUtil.isEmpty(this.reqPostString) || !CommonUtil.isEmpty(paramString)){
                reqPostString = (reqPostString==null ? paramString : reqPostString);
                StringEntity entity = null;
                entity = new StringEntity(this.reqPostString, ContentType.create(this.reqContentType,this.reqCharset));
                post.setEntity(entity);
            }
            //上傳文件
            else if(!CommonUtil.isEmpty(this.reqFilePath)){
                MultipartEntityBuilder entityBuilder = MultipartEntityBuilder.create();
                //以瀏覽器兼容模式運行,防止文件名亂碼
                entityBuilder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
//              entityBuilder.setCharset(Consts.UTF_8);//設置編碼格式
                //設置文件信息
                File uploadFile = new File(this.reqFilePath);
                if(!uploadFile.exists()){
                    throw new RuntimeException("HttpConn:\""+reqFilePath+"\"路徑不存在!");
                }else{
                    if(CommonUtil.isEmpty(this.reqFileKey))
                        throw new RuntimeException("HttpConn: resFileKey為空!");
                    entityBuilder.addBinaryBody(this.reqFileKey, uploadFile);
                }
                //設置參數信息
                if(!CommonUtil.isEmpty(this.reqParams)){
                    Iterator<Map.Entry<String, String>> it = this.reqParams.entrySet().iterator();
                    while(it.hasNext()){
                        Map.Entry<String, String> entry = it.next();
                        String key = entry.getKey();
                        StringBody body = new StringBody(entry.getValue(), ContentType.create("text/plain", DETAULT_ENCODING));
                        entityBuilder.addPart(key, body);
                    }
                }
                post.setEntity(entityBuilder.build());
            }

            this.request = post;
        }
    }

    /**
     * 處理響應數據
     * @throws IllegalStateException
     * @throws IOException
     */
    private void setResInfo() throws IllegalStateException, IOException {
        HttpEntity resEntity = this.response.getEntity();
        //返回狀態
        this.resCode = this.response.getStatusLine().getStatusCode();
        this.resStatues = this.response.getStatusLine().toString();
        this.resLength = resEntity.getContentLength();
        if(!CommonUtil.isEmpty(resEntity.getContentEncoding()))
            this.resEncoding = resEntity.getContentEncoding().getValue();
        if(this.resCode == HTTP_RESSTATUS_SUCCESS){
            resSuccess = true;
            //返回數據
            this.resContentType = resEntity.getContentType().getValue();
            if(CommonUtil.isEmpty(this.resEncoding)){
                this.resEncoding = getEncoding(this.resContentType);
            }
            InputStream is = null;
            FileOutputStream fos = null;
            try{
                is = resEntity.getContent();
                //保存為文件
                if(!CommonUtil.isEmpty(this.resFilePath)){
                    if(!CommonUtil.isFilePath(this.resFilePath)){
                        //從請求頭獲取文件名
                        String fileName = getValueFromHeader("Content-disposition", "filename");
                        if(fileName != null){
                            this.resFilePath += "_"+fileName;
                        }
                    }
                    File downFile = new File(this.resFilePath);
                    downFile.getParentFile().mkdirs();
                    fos = new FileOutputStream(downFile);
                    resEntity.writeTo(fos);
                    this.resFileSaveSuccess = true;
                }
                //保存為字符串
                else{
                    if(CommonUtil.isEmpty(this.resEncoding))
                        this.resBody = EntityUtils.toString(resEntity, Consts.UTF_8);
                    else
                        this.resBody = EntityUtils.toString(resEntity, this.resEncoding);
                }

            }finally{
                try {
                    if(is != null)
                        is.close();
                    if(fos != null)
                        fos.close();
                } catch (Exception e) {
                    throw new RuntimeException("HttpConn : " + e.getMessage());
                }
            }
        }else{
            this.request.abort();//中止請求
            throw new RuntimeException("HttpConn ,error status code : " + this.resCode);
        }
        //銷毀
        EntityUtils.consume(resEntity);
    }

    /**
     * 從content-type獲取編碼格式
     * @param contentType
     * @return
     */
    private String getEncoding(String contentType) {
        String encoding = null;
        int tmp = contentType.indexOf(";");
        if(tmp > 0){
            encoding = contentType.substring(tmp+1);
            encoding = encoding.trim();
            tmp = encoding.indexOf("=");
            if(tmp > 0){
                String[] entry = encoding.split("=");
                if(entry[0].equalsIgnoreCase("charset") || entry[0].equalsIgnoreCase("encoding"))
                    encoding = entry[1].trim();
            }
        }

        return encoding;
    }


    /**
     * 從請求頭中獲取參數值
     * @param headerName
     * @param key
     * @return
     */
    private String getValueFromHeader(String headerName, String key) {
        String value = null;
        Header header = this.response.getFirstHeader(headerName);

        if(!CommonUtil.isEmpty(header)){
            if(CommonUtil.isEmpty(key)){
                value = header.getValue();
            }else{
                HeaderElement[] elms = header.getElements();
                for(HeaderElement elm : elms){
                    NameValuePair pair = elm.getParameterByName(key);
                    if(pair != null){
                        value = pair.getValue();
                        break;
                    }
                }
            }
        }

        return value;
    }

    public void setReqFilePath(String reqFileKey, String reqFilePath) {
        this.reqFileKey = reqFileKey;
        this.reqFilePath = reqFilePath;
    }

    public int getResCode() {
        return resCode;
    }

    public String getResStatues() {
        return resStatues;
    }

    public String getResType() {
        return resContentType;
    }

    public String getResBody() {
        return resBody;
    }

    public void setReqUrl(String reqUrl) {
        this.reqUrl = reqUrl;
    }

    public void setReqMethod(String reqMethod) {
        this.reqMethod = reqMethod;
    }

    public void setReqParams(Map<String, String> reqParams) {
        this.reqParams = reqParams;
    }

    public void setReqPostString(String reqPostString) {
        this.reqPostString = reqPostString;
    }



    public void setReqContentType(String reqContentType) {
        this.reqContentType = reqContentType;
    }


    public void setResFilePath(String resFilePath) {
        this.resFilePath = resFilePath;
    }


    public long getResLength() {
        return resLength;
    }


    public String getResEncoding() {
        return resEncoding;
    }


    public String getResContentType() {
        return resContentType;
    }


    public boolean isResFileSaveSuccess() {
        return resFileSaveSuccess;
    }


    public void setReqCharset(String reqCharset) {
        this.reqCharset = reqCharset;
    }


    public boolean isResSuccess() {
        return resSuccess;
    }


    public void setResSuccess(boolean resSuccess) {
        this.resSuccess = resSuccess;
    }


}

HttpConnMonitorThread    

public class HttpConnMonitorThread extends Thread{

    private final static Logger logger = LoggerFactory.getLogger(HttpConnMonitorThread.class); 

    private final HttpClientConnectionManager cm;
    private volatile boolean shutdown;

    private final static int WATING_TIME = 60 * 1000; // 輪詢時間
    private final static int IDLE_TIME = 30; // 空閑時間

    public HttpConnMonitorThread(HttpClientConnectionManager cm) {
        super();
        this.cm = cm;
    }

    @Override
    public void run() {
        try {
            while (!shutdown) {
                synchronized (this) {
                    wait(WATING_TIME);
                    // 關閉過期連接
                    cm.closeExpiredConnections();
                    logger.info(">>>>>close expired connections.");
                    // 關閉空閑連接
                    cm.closeIdleConnections(IDLE_TIME, TimeUnit.SECONDS);
                    logger.info(">>>>>close idle connections.");
                }
            }
        } catch (InterruptedException ex) {
            logger.error("HttpConn Monitor error! ", ex);
        }
    }

    /**
     * 關閉輪詢
     */
    public void shutdown() {
        shutdown = true;
        synchronized (this) {
            notifyAll();
        }
    }

}
 本文由用戶 RegPoate 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!