1. 程式人生 > >跨域請求httpclient

跨域請求httpclient

t對象 pair etl actor sock slf4j .cn factor odi

httpclient:是Apache工具包,util,它可以作為一個爬蟲,直接爬取某個互聯網上的頁面。獲取到時頁面最終的源文件html。直接可以獲取頁面返回json。就可以直接在代碼內部模擬發起http請求。請求的結果也被捕捉。在代碼內部將獲取的json,利用JacksonObjectMapper對象,把json字符串轉成java對象。

技術分享

與Spring框架整合:

1、引入jar支持

<!-- httpclient -->
<dependency>
    <groupId>org.apache.httpcomponents</groupId>
    <
artifactId>httpclient</artifactId> <version>4.3.5</version> </dependency> <dependency> <groupId>org.apache.httpcomponents</groupId> <artifactId>httpmime</artifactId> <version>4.3.1</version> </dependency>

2、applicationContext-httpclient.xml:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:p="http://www.springframework.org/schema/p" 
    xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.0.xsd"> <!-- 定義httpclient連接池 --> <bean id="httpClientConnectionManager" class="org.apache.http.impl.conn.PoolingHttpClientConnectionManager" destroy-method="close"> <!-- 設置連接總數 --> <property name="maxTotal" value="${http.pool.maxTotal}"></property> <!-- 設置每個地址的並發數 --> <property name="defaultMaxPerRoute" value="${http.pool.defaultMaxPerRoute}"></property> </bean> <!-- 定義 HttpClient工廠,這裏使用HttpClientBuilder構建--> <bean id="httpClientBuilder" class="org.apache.http.impl.client.HttpClientBuilder" factory-method="create"> <property name="connectionManager" ref="httpClientConnectionManager"></property> </bean> <!-- 得到httpClient的實例 --> <bean id="httpClient" factory-bean="httpClientBuilder" factory-method="build"/> <!-- 定期清理無效的連接 --> <bean class="com.jt.common.util.IdleConnectionEvictor" destroy-method="shutdown"> <constructor-arg index="0" ref="httpClientConnectionManager" /> <!-- 間隔一分鐘清理一次 --> <constructor-arg index="1" value="600000" /> </bean> <!-- 定義requestConfig的工廠 --> <bean id="requestConfigBuilder" class="org.apache.http.client.config.RequestConfig.Builder"> <!-- 從連接池中獲取到連接的最長時間 --> <property name="connectionRequestTimeout" value="${http.request.connectionRequestTimeout}"/> <!-- 創建連接的最長時間 --> <property name="connectTimeout" value="${http.request.connectTimeout}"/> <!-- 數據傳輸的最長時間 --> <property name="socketTimeout" value="${http.request.socketTimeout}"/> <!-- 提交請求前測試連接是否可用 --> <property name="staleConnectionCheckEnabled" value="${http.request.staleConnectionCheckEnabled}"/> </bean> <!-- 得到requestConfig實例 --> <bean id="requestConfig" factory-bean="requestConfigBuilder" factory-method="build" /> </beans>

3、把httpClient對象封裝成偽service。在程序中註入,封裝doGet,doPost,doJson- ---- HttpClientService:

package com.jt.common.service;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

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.methods.HttpPost;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class HttpClientService {

    private static final Logger LOGGER = LoggerFactory.getLogger(HttpClientService.class);

    @Autowired(required=false)
    private CloseableHttpClient httpClient;

    @Autowired(required=false)
    private RequestConfig requestConfig;

    /**
     * 執行get請求
     * 
     * @param url
     * @return
     * @throws Exception
     */
    public String doGet(String url,Map<String, String> params,String encode) throws Exception {
        LOGGER.info("執行GET請求,URL = {}", url);
        if(null != params){
            URIBuilder builder = new URIBuilder(url);
            for (Map.Entry<String, String> entry : params.entrySet()) {
                builder.setParameter(entry.getKey(), entry.getValue());
            }
            url = builder.build().toString();
        }
        // 創建http GET請求
        HttpGet httpGet = new HttpGet(url);
        httpGet.setConfig(requestConfig);
        CloseableHttpResponse response = null;
        try {
            // 執行請求
            response = httpClient.execute(httpGet);
            // 判斷返回狀態是否為200
            if (response.getStatusLine().getStatusCode() == 200) {
                if(encode == null){
                    encode = "UTF-8";
                }
                return EntityUtils.toString(response.getEntity(), encode);
            }
        } finally {
            if (response != null) {
                response.close();
            }
            // 此處不能關閉httpClient,如果關閉httpClient,連接池也會銷毀
        }
        return null;
    }
    
    public String doGet(String url, String encode) throws Exception{
        return this.doGet(url, null, encode);
    }
    
    public String doGet(String url) throws Exception{
        return this.doGet(url, null, null);
    }

    /**
     * 帶參數的get請求
     * 
     * @param url
     * @param params
     * @return
     * @throws Exception
     */
    public String doGet(String url, Map<String, String> params) throws Exception {
        return this.doGet(url, params, null);
    }

    /**
     * 執行POST請求
     * 
     * @param url
     * @param params
     * @return
     * @throws Exception
     */
    public String doPost(String url, Map<String, String> params,String encode) throws Exception {
        // 創建http POST請求
        HttpPost httpPost = new HttpPost(url);
        httpPost.setConfig(requestConfig);

        if (null != params) {
            // 設置2個post參數,一個是scope、一個是q
            List<NameValuePair> parameters = new ArrayList<NameValuePair>(0);
            for (Map.Entry<String, String> entry : params.entrySet()) {
                parameters.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));
            }

            // 構造一個form表單式的實體
            UrlEncodedFormEntity formEntity = null;
            if(encode!=null){
                formEntity = new UrlEncodedFormEntity(parameters,encode);
            }else{
                formEntity = new UrlEncodedFormEntity(parameters);
            }
            // 將請求實體設置到httpPost對象中
            httpPost.setEntity(formEntity);
        }

        CloseableHttpResponse response = null;
        try {
            // 執行請求
            response = httpClient.execute(httpPost);
            // 判斷返回狀態是否為200
            if (response.getStatusLine().getStatusCode() == 200) {
                return EntityUtils.toString(response.getEntity(), "UTF-8");
            }
        } finally {
            if (response != null) {
                response.close();
            }
        }
        return null;
    }


    /**
     * 執行POST請求
     * 
     * @param url
     * @param params
     * @return
     * @throws Exception
     */
    public String doPost(String url, Map<String, String> params) throws Exception {
        // 創建http POST請求
        HttpPost httpPost = new HttpPost(url);
        httpPost.setConfig(requestConfig);

        if (null != params) {
            // 設置2個post參數,一個是scope、一個是q
            List<NameValuePair> parameters = new ArrayList<NameValuePair>(0);
            for (Map.Entry<String, String> entry : params.entrySet()) {
                parameters.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));
            }

            // 構造一個form表單式的實體
            UrlEncodedFormEntity formEntity = new UrlEncodedFormEntity(parameters);
            // 將請求實體設置到httpPost對象中
            httpPost.setEntity(formEntity);
        }

        CloseableHttpResponse response = null;
        try {
            // 執行請求
            response = httpClient.execute(httpPost);
            // 判斷返回狀態是否為200
            if (response.getStatusLine().getStatusCode() == 200) {
                return EntityUtils.toString(response.getEntity(), "UTF-8");
            }
        } finally {
            if (response != null) {
                response.close();
            }
        }
        return null;
    }

    public String doPostJson(String url, String json) throws Exception {
        // 創建http POST請求
        HttpPost httpPost = new HttpPost(url);
        httpPost.setConfig(requestConfig);
        
        if(null != json){
            //設置請求體為 字符串
            StringEntity stringEntity = new StringEntity(json,"UTF-8");
            httpPost.setEntity(stringEntity);
        }

        CloseableHttpResponse response = null;
        try {
            // 執行請求
            response = httpClient.execute(httpPost);
            // 判斷返回狀態是否為200
            if (response.getStatusLine().getStatusCode() == 200) {
                return EntityUtils.toString(response.getEntity(), "UTF-8");
            }
        } finally {
            if (response != null) {
                response.close();
            }
        }
        return null;
    }

}

4、在程序中註入httpClientService,直接調用doGet。

5、在applicationContext.xml中加入<value>classpath:httpclient.properties</value>

  httpclient.properties:

#從連接池中獲取到連接的最長時間
http.request.connectionRequestTimeout=500
#5000
http.request.connectTimeout=5000
#數據傳輸的最長時間
http.request.socketTimeout=30000
#提交請求前測試連接是否可用
http.request.staleConnectionCheckEnabled=true

#設置連接總數
http.pool.maxTotal=200
#設置每個地址的並發數
http.pool.defaultMaxPerRoute=100

跨域請求httpclient