SpringBoot2模塊系列:httpclient(轉接Http和Https接口)

1 pom.xml

 <dependency>
  <groupId>org.apache.httpcomponents</groupId>
  <artifactId>httpcore</artifactId>
  <version>4.4.11</version>
</dependency>
<dependency>
  <groupId>org.apache.httpcomponents</groupId>
  <artifactId>httpclient</artifactId>
<version>4.5.3</version>
</dependency>

2 轉接http接口

package com.sb.util;

import java.io.IOException;
import java.net.URI;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.StatusLine;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.message.BasicHeader;
import org.apache.http.util.EntityUtils;

import org.apache.http.Consts;
import org.apache.http.NameValuePair;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.entity.ContentType;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.HttpStatus;

import net.sf.json.JSONObject;

public class HttpClientUtil {
    public static String doGet(String url, Map<String, String> param, Map<String, String> headers) {
        // 創建Httpclient對象
        CloseableHttpClient httpclient = HttpClients.createDefault();
        //設置請求超時時間(各項超時參數具體含義鏈接)
        RequestConfig requestConfig = RequestConfig.custom()
                .setConnectTimeout(10000)
                .setConnectionRequestTimeout(10000)
                .setSocketTimeout(10000)
                .build();

        String resultString = "";
        CloseableHttpResponse response = null;
        try {
            // 創建uri
            URIBuilder builder = new URIBuilder(url);
            if (param != null) {
                for (String key : param.keySet()) {
                    builder.addParameter(key, param.get(key));
                }
            }
            URI uri = builder.build();
            // 創建http GET請求
            HttpGet httpGet = new HttpGet(uri);
            //給這個請求設置請求配置
            httpGet.setConfig(requestConfig);
            httpGet.setHeader("User-Agent", "Mozilla/5.0 (Windows NT 6.1; rv:6.0.2) Gecko/20100101 Firefox/6.0.2");
            if(headers != null){
                for(String headerKey:headers.keySet()){
                    httpGet.addHeader(headerKey, headers.get(headerKey));
                }
                
            }
            // 執行請求
            response = httpclient.execute(httpGet);
            // 判斷返回狀態是否爲200
            if (response.getStatusLine().getStatusCode() == 200) {
                resultString = EntityUtils.toString(response.getEntity(), "UTF-8");
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (response != null) {
                    response.close();
                }
                httpclient.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return resultString;
    }
    /*
    *Post請求,傳參爲Map
    */
    public static String doPost(String url, Map<String, String> param) {
        // 創建Httpclient對象
        CloseableHttpClient httpClient = HttpClients.createDefault();
        //設置請求超時時間
        RequestConfig requestConfig = RequestConfig.custom()
                .setConnectTimeout(10000)
                .setConnectionRequestTimeout(10000)
                .setSocketTimeout(10000)
                .build();
        CloseableHttpResponse response = null;
        String resultString = "";
        try {
            // 創建Http Post請求
            HttpPost httpPost = new HttpPost(url);
            httpPost.setConfig(requestConfig);
            // 創建參數列表
            if (param != null) {
                List<NameValuePair> paramList = new ArrayList<NameValuePair>();
                for (String key : param.keySet()) {
                    paramList.add(new BasicNameValuePair(key, param.get(key)));
                    System.out.format("param list:"+paramList+"\n");
                }
                // 模擬表單
                UrlEncodedFormEntity entity = new UrlEncodedFormEntity(paramList);
                httpPost.setEntity(entity);
            }
            // 執行http請求
            response = httpClient.execute(httpPost);

            if(response.getStatusLine().getStatusCode() == HttpStatus.SC_OK){
                resultString = EntityUtils.toString(response.getEntity(), "utf-8");
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                response.close();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
        return resultString;
    }
	 /*
    *Post請求,傳參爲json字符串
    */
    public static String doPostJson(String url, String json) {
        // 創建Httpclient對象
        CloseableHttpClient httpClient = HttpClients.createDefault();

        //設置請求超時時間
        RequestConfig requestConfig = RequestConfig.custom()
                .setConnectTimeout(10000)
                .setConnectionRequestTimeout(10000)
                .setSocketTimeout(10000)
                .build();
        CloseableHttpResponse response = null;
        String resultString = "";
        try {
            // 創建Http Post請求
            HttpPost httpPost = new HttpPost(url);
            httpPost.setConfig(requestConfig);
            // 創建請求內容 ,發送json數據需要設置contentType
            StringEntity entity = new StringEntity(json, ContentType.APPLICATION_JSON);
            System.out.format("entity:"+entity+"\n");
            // httpPost.addHeader("Content-Type", "application/json");

            httpPost.setEntity(entity);
            // 執行http請求
            response = httpClient.execute(httpPost);
            
            if(response.getStatusLine().getStatusCode() == HttpStatus.SC_OK){
                resultString = EntityUtils.toString(response.getEntity(), "utf-8");
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                response.close();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
        return resultString;
    }
}

3 轉接https接口

3.1 跳過認證

package com.sb.util.https;  
import java.security.cert.CertificateException; 
import java.security.cert.X509Certificate; 
import javax.net.ssl.SSLContext; 
import javax.net.ssl.TrustManager; 
import javax.net.ssl.X509TrustManager; 
import org.apache.http.conn.ssl.SSLConnectionSocketFactory; 
public class HttpsTrustClientV45 extends HttpsClientV45 { 
  public HttpsTrustClientV45() {  
  } 
  
  @Override
  public void prepareCertificate() throws Exception { 
    // 跳過證書驗證 
    SSLContext ctx = SSLContext.getInstance("TLS"); 
    X509TrustManager tm = new X509TrustManager() { 
      @Override
      public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException { 
      } 
  
      @Override
      public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException { 
      } 
  
      @Override
      public X509Certificate[] getAcceptedIssuers() { 
        return null; 
      } 
    }; 
    // 設置成已信任的證書 
    ctx.init(null, new TrustManager[] { tm }, null); 
    this.connectionSocketFactory = new SSLConnectionSocketFactory(ctx); 
  } 
}

3.2 使用證書

package com.sb.util.https;

import java.io.File;
import java.io.FileInputStream;
import java.security.KeyStore;
import javax.net.ssl.SSLContext;

import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.TrustSelfSignedStrategy;
import org.apache.http.ssl.SSLContexts;


public class HttpsCertifiedClientV45 extends HttpsClientV45{
    public HttpsCertifiedClientV45(){}

    @Override 
    public void prepareCertificate() throws Exception{
        // 獲取密鑰庫
        KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
        FileInputStream inputStream = new FileInputStream(new File("classpath:**.keystore"));
        try{
            trustStore.load(inputStream, "password".toCharArray());
        }finally{
            inputStream.close();
        }
        SSLContext sslContext = SSLContexts.custom()
                                .loadTrustMaterial(trustStore, TrustSelfSignedStrategy.INSTANCE)
                                .build();
        this.connectionSocketFactory = new SSLConnectionSocketFactory(sslContext);
    }
}
  • 異常
    javax.net.ssl.SSLPeerUnverifiedException: Certificate for <218.17.121.227> doesn’t match any of the subject alternative names: [172.168.1.20]
  • 解決方案
this.connectionSocketFactory = new SSLConnectionSocketFactory(ctx, NoopHostnameVerifier.INSTANCE);

3.3 認證註冊

package com.sb.util.https;  
import org.apache.http.config.Registry; 
import org.apache.http.config.RegistryBuilder; 
import org.apache.http.conn.socket.ConnectionSocketFactory; 
import org.apache.http.conn.socket.PlainConnectionSocketFactory; 
import org.apache.http.impl.client.CloseableHttpClient; 
import org.apache.http.impl.client.HttpClientBuilder; 
import org.apache.http.impl.client.HttpClients; 
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;  
public abstract class HttpsClientV45 extends HttpClientBuilder { 
  private CloseableHttpClient client; 
  protected ConnectionSocketFactory connectionSocketFactory; 
  
  /** 
   * 初始化HTTPSClient 
   * 
   * @return 返回當前實例 
   * @throws Exception 
   */
  public CloseableHttpClient init() throws Exception { 
    this.prepareCertificate(); 
    this.regist(); 
  
    return this.client; 
  } 
  
  /** 
   * 準備證書驗證 
   * 
   * @throws Exception 
   */
  public abstract void prepareCertificate() throws Exception; 
  
  /** 
   * 註冊協議和端口, 此方法也可以被子類重寫 
   */
  protected void regist() { 
    // 設置協議http和https對應的處理socket鏈接工廠的對象 
    Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory>create() 
        .register("http", PlainConnectionSocketFactory.INSTANCE) 
        .register("https", this.connectionSocketFactory) 
        .build(); 
    PoolingHttpClientConnectionManager connManager = new PoolingHttpClientConnectionManager(socketFactoryRegistry); 
    HttpClients.custom().setConnectionManager(connManager); 
  
    // 創建自定義的httpclient對象 
    this.client = HttpClients.custom().setConnectionManager(connManager).build(); 
    // CloseableHttpClient client = HttpClients.createDefault(); 
  } 
}

3.4 請求方法

Get請求,參數不多的情況下可以在URL中直接拼接,傳入doGet中;
Post請求,解析Body有兩種方式,通過String解析,通過Map解析;

package com.sb.util.https;

import java.util.ArrayList; 
import java.util.List; 
import java.util.Map; 
import java.util.Map.Entry;
import java.util.Set;
import java.util.Iterator;  
import java.util.Arrays;

import org.apache.http.HttpEntity; 
import org.apache.http.HttpResponse; 
import org.apache.http.NameValuePair; 
import org.apache.http.Header;
import org.apache.http.client.HttpClient; 
import org.apache.http.client.entity.UrlEncodedFormEntity; 
import org.apache.http.client.methods.HttpGet; 
import org.apache.http.client.methods.HttpPost; 
import org.apache.http.client.methods.HttpRequestBase;
import org.apache.http.entity.ContentType;
import org.apache.http.message.BasicNameValuePair; 
import org.apache.http.util.EntityUtils;  
import org.apache.http.entity.StringEntity;

public class HttpsClientV45Util { 
  /**
     * Post請求,外部setBody解析Body
     * @param httpClient
     * @param url
     * @param paramHeader
     * @param paramBody
     * @return
     * @throws Exception
     */ 
  public static String doPost(HttpClient httpClient, String url, Map<String, String> paramHeader, 
      Map<String, String> paramBody) throws Exception { 
    String result = null; 
    HttpPost httpPost = new HttpPost(url); 
    setHeader(httpPost, paramHeader); 
    setBody(httpPost, paramBody, "UTF-8");  
    HttpResponse response = httpClient.execute(httpPost); 
    if (response != null) { 
      HttpEntity resEntity = response.getEntity(); 
      if (resEntity != null) { 
        result = EntityUtils.toString(resEntity, "UTF-8"); 
      } 
    } 
    return result; 
  } 
  /**
     * Post請求,內置解析Body
     * @param httpClient
     * @param url
     * @param paramHeader
     * @param paramBody
     * @return
     * @throws Exception
     */
  public static String doPostString(HttpClient httpClient, String url, Map<String, String> paramHeader, 
      String paramBody) throws Exception { 
    String result = null; 
    HttpPost httpPost = new HttpPost(url); 
    setHeader(httpPost, paramHeader); 
    StringEntity entity = new StringEntity(paramBody, ContentType.APPLICATION_JSON);
    httpPost.setEntity(entity); 
    HttpResponse response = httpClient.execute(httpPost); 
    if (response != null) { 
      HttpEntity resEntity = response.getEntity(); 
      if (resEntity != null) { 
        result = EntityUtils.toString(resEntity, "UTF-8"); 
      } 
    } 
    return result; 
  } 
  
  
  public static String doPostGetHeader(HttpClient httpClient, String url, Map<String, String> paramHeader, 
      String paramBody) throws Exception { 
    String result = null; 
    HttpPost httpPost = new HttpPost(url); 
    setHeader(httpPost, paramHeader); 
    StringEntity entity = new StringEntity(paramBody, ContentType.APPLICATION_JSON);
    System.out.format("entity:"+entity+"\n");
    httpPost.setEntity(entity);
    HttpResponse response = httpClient.execute(httpPost);
    // System.out.format("all headers"+response.getAllHeaders()+"\n"); 
    // System.out.format("all headers"+response.getAllHeaders()+"\n");
    Header[] headersAll = response.getAllHeaders();
    // for(Header header:headersAll){
    //   System.out.format("header all value:"+header.getValue()+"\n");
    // }
    Header[] headersPart = response.getHeaders("X-Subject-Token");
    String resultHeader = headersPart[0].getValue();
    return resultHeader;
    // for(Header header:headersPart){
    //   System.out.format("header part:"+header.getValue()+"\n");
    // }
    // if (response != null) { 
    //   HttpEntity resEntity = response.getEntity(); 
    //   if (resEntity != null) { 
    //     result = EntityUtils.toString(resEntity, "UTF-8"); 
    //   } 
    // } 
  
    // return result; 
  } 
    
  public static String doGet(HttpClient httpClient, String url, Map<String, String> paramHeader, 
      Map<String, String> paramBody) throws Exception { 
    # url爲拼接後的完整路徑
    String result = null; 
    HttpGet httpGet = new HttpGet(url); 
    setHeader(httpGet, paramHeader); 
  
    HttpResponse response = httpClient.execute(httpGet); 
    if (response != null) { 
      HttpEntity resEntity = response.getEntity(); 
      if (resEntity != null) { 
        result = EntityUtils.toString(resEntity, "UTF-8"); 
      } 
    } 
  
    return result; 
  } 
  
  private static void setHeader(HttpRequestBase request, Map<String, String> paramHeader) { 
    // 設置Header 
    if (paramHeader != null) { 
      Set<String> keySet = paramHeader.keySet(); 
      for (String key : keySet) { 
        request.addHeader(key, paramHeader.get(key)); 
      } 
    } 
  } 
  
  private static void setBody(HttpPost httpPost, Map<String, String> paramBody, String charset) throws Exception { 
    // 設置參數 
    if (paramBody != null) { 
      System.out.format("param body: "+paramBody+"\n");
      List<NameValuePair> list = new ArrayList<NameValuePair>();    
      Set<String> keySet = paramBody.keySet(); 
      for (String key : keySet) { 
        list.add(new BasicNameValuePair(key, paramBody.get(key))); 
      } 
      if (list.size() > 0) { 
        UrlEncodedFormEntity entity = new UrlEncodedFormEntity(list, charset); 
        httpPost.setEntity(entity); 
      } 
    } 
  } 
} 

4 測試

package com.sb.controller;

import java.util.Map;
import java.util.HashMap;
import java.util.List;
import java.util.ArrayList;
import com.sb.util.HttpClientUtil;
import com.sb.util.https.HttpsClientV45Util;
import com.sb.util.https.HttpsTrustClientV45;

import net.sf.json.JSONObject;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.apache.http.client.HttpClient;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.RestController;
import org.apache.http.client.HttpClient;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@CrossOrigin(origins="*", maxAge=3600)
@RestController
@RequestMapping("/api")
public class CallAPIController{
    @RequestMapping(value="/call/test-get", method=RequestMethod.POST)
    public Map testGet(@RequestBody Map infos){
        if(infos.containsKey("name") && infos.containsKey("sex")){
            String url = "http://127.0.0.1:8091/test-get";
            String str = HttpClientUtil.doGet(url, infos, null);
            Map outInfos = (Map)JSONObject.fromObject(str);
            return outInfos;
        }else{
            Map errorMap = new HashMap(){
                {
                    put("code", 400);
                    put("infos","請檢查輸入參數");
                }
            };
            return errorMap;
        }   
    }

    @RequestMapping(value="/call/test-post", method=RequestMethod.POST)
    public Map testPost(@RequestBody Map infos){
        if(infos.containsKey("name")&&infos.containsKey("sex")){
            String url="http://127.0.0.1:8091/test-json";
            // string json
            String param = JSONObject.fromObject(infos).toString();
            String str = HttpClientUtil.doPostJson(url, param);
            Map outInfos = (Map)JSONObject.fromObject(str);
            return outInfos;
        }else{
            Map errorMap = new HashMap(){
                {
                    put("code", 400);
                    put("infos", "輸入參數有誤,請檢查輸入參數");
                }
            };
            return errorMap;
        }
    }

    @RequestMapping(value="/call/token-get", method=RequestMethod.POST)
    public Map getToken(@RequestBody Map params, HttpServletRequest req){
        Map<String, String> paramHeader = new HashMap<String, String>();
        paramHeader.put("Accept", "application/json");
        String url = "https://****";
        String strJson = JSONObject.fromObject(params).toString();
        String result = null;
        System.out.format("str json:"+strJson+"\n");
        HttpClient httpClient = null;
        try{
            httpClient = new HttpsTrustClientV45().init();
            result = HttpsClientV45Util.doPostGetHeader(httpClient, url, paramHeader, strJson);
            // System.out.format("result:"+result+"\n");
        }catch(Exception e){
            e.printStackTrace();
        }
        Map token = new HashMap();
        token.put("code", 200);
        token.put("token", result);
        return token;
    }
}

【參考文獻】
[1]https://www.jb51.net/article/134997.htm
[2]https://blog.csdn.net/Xin_101/article/details/99542841
[3]https://blog.csdn.net/gnail_oug/article/details/80324120
[4]https://blog.csdn.net/Breezeg/article/details/100934849
[5]https://www.cnblogs.com/stonefeng/p/10429716.html

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章