HttpClient完整使用示例

HttpClient完整使用示例

 

1 前言

HTTP 协议可能是现在 Internet 上使用得最多、最重要的协议了,越来越多的 Java 应用程序需要直接通过 HTTP 协议来访问网络资源。虽然JDK 的 java net包中已经提供了访问 HTTP 协议的基本功能,但是对于大部分应用程序来说,JDK 库本身提供的功能还不够丰富和灵活。HttpClient用来提供高效的、最新的、功能丰富的支持 HTTP 协议的客户端编程工具包,并且它支持 HTTP 协议的最新版本。

Jakarta Commons HttpClient项目已经终止维护了,取而代之的是Apache HttpComponents项目中的HttpClient模块,后者比前者效率更高且更加灵活,本文也是基于Apache HttpComponents项目中的HttpClient。

使用HttpClient发送请求和接收响应一般分为以下几步:

  1. 创建HttpClient对象。
  2. 创建某种请求方法对象,并按需指定请求信息(包括:URL、请求参数、Header、Cookie等信息)。例如:发送Get请求则创建HttpGet对象,发送Post请求则创建HttpPost对象。
  3. 调用HttpClient对象的execute方法来执行第2步中创建的请求方法对象,并得到HttpResponse响应对象。
  4. 通过HttpResponse响应对象按需读取返回结果(包括:返回数据、Header、Cookiet等信息)。
  5. 释放连接(无论执行方法是否成功,都必须释放连接)。

2 示例说明

本文主要介绍HttpClient的完整使用示例,所以创建了两个Spring Boot工程:

  1. HttpClientService工程:作为服务端工程,主要是为了提供Restful风格的API接口,供客户端调用。
  2. HttpClient工程:作为客户端工程,主要是使用HttpClient类库访问HttpClientService服务端工程中的接口,演示了使用HttpGet和HttpPost发送请求、获取结果等完整流程。

本文最重要的是HttpClient工程中的以下两个封装的工具类:

  1. HttpClientUtil:主要是封装了使用HttpClient发送Get请求和发送Post请求的方法。
  2. HttpResult:主要是封装了Get请求和Post请求的返回结果。

注意:如果读者关心的是HttpClient的完整使用示例,则可以通读全文,如果只关心HttpClient的封装,则只需要关注上述两个封装的工具类即可。

3 创建HttpClient客户端工程

3.1 版本说明

  1. Spring Boot: 2.1.13
  2. HttpClient: 4.5.6
  3. JDK: 1.8
  4. IDE: IDEA

3.2 创建项目

创建一个名为HttpClient的Spring Boot项目,并添加maven依赖和相应的Java代码,最后的项目结构如下图所示:
在这里插入图片描述
pom.xml文件内容如下所示:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.http.client</groupId>
    <artifactId>http-client</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>HttpClient</name>
    <description>HttpClient使用示例</description>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.3.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <properties>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>org.apache.httpcomponents</groupId>
            <artifactId>httpclient</artifactId>
            <version>4.5.6</version>
        </dependency>

    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

User类程序如下所示:

package com.http.client.model;

/**
 * 用户信息实体
 */
public class User {
    private String id;
    private String name;
    private String sex;

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }
}

HttpResult类程序如下所示:

package com.http.client.model;

import org.apache.http.Header;
import org.apache.http.cookie.Cookie;

import java.util.List;

/**
 * Http请求的响应结果封装类
 */
public class HttpResult {

    /**
     * 响应的Header信息
     */
    private Header[] headers;

    /**
     * 响应的Cookie信息
     */
    private List<Cookie> cookies;

    /**
     * 响应状态码
     */
    private int statusCode;

    /**
     * 响应内容的类型
     */
    private String contentType;

    /**
     * 响应的内容是否是文本类型
     */
    private boolean isTextType;

    /**
     * 响应的内容(字符串形式)
     */
    private String stringContent;

    /**
     * 响应的内容(字节数组形式)
     */
    private byte[] byteArrayContent;

    public Header[] getHeaders() {
        return headers;
    }

    public void setHeaders(Header[] headers) {
        this.headers = headers;
    }

    public List<Cookie> getCookies() {
        return cookies;
    }

    public void setCookies(List<Cookie> cookies) {
        this.cookies = cookies;
    }

    public int getStatusCode() {
        return statusCode;
    }

    public void setStatusCode(int statusCode) {
        this.statusCode = statusCode;
    }

    public String getContentType() {
        return contentType;
    }

    public void setContentType(String contentType) {
        this.contentType = contentType;
    }

    public boolean isTextType() {
        return isTextType;
    }

    public void setTextType(boolean textType) {
        isTextType = textType;
    }

    public String getStringContent() {
        return stringContent;
    }

    public void setStringContent(String stringContent) {
        this.stringContent = stringContent;
    }

    public byte[] getByteArrayContent() {
        return byteArrayContent;
    }

    public void setByteArrayContent(byte[] byteArrayContent) {
        this.byteArrayContent = byteArrayContent;
    }
}

HttpClientUtil类程序如下所示:

package com.http.client.util;

import com.http.client.model.HttpResult;
import org.apache.http.Consts;
import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.StatusLine;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpResponseException;
import org.apache.http.client.ResponseHandler;
import org.apache.http.client.config.RequestConfig;
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.utils.URIBuilder;
import org.apache.http.config.ConnectionConfig;
import org.apache.http.config.SocketConfig;
import org.apache.http.cookie.Cookie;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.BasicCookieStore;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.nio.charset.Charset;
import java.nio.charset.CodingErrorAction;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * HttpClient发送Get请求和Post请求的封装类
 */
public class HttpClientUtil {

    /** 从连接池中获取连接的超时时间(单位:ms) */
    private static final int CONNECTION_REQUEST_TIMEOUT = 5000;

    /** 与服务器连接的超时时间(单位:ms) */
    private static final int CONNECTION_TIMEOUT = 5000;

    /** 从服务器获取响应数据的超时时间(单位:ms) */
    private static final int SOCKET_TIMEOUT = 10000;

    /** 连接池的最大连接数 */
    private static final int MAX_CONN_TOTAL = 100;

    /** 每个路由上的最大连接数 */
    private static final int MAX_CONN_PER_ROUTE = 50;

    /** 用户代理配置 */
    private static final String USER_AGENT = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.67 Safari/537.36";

    /** HttpClient对象 */
    private static CloseableHttpClient httpClient = null;

    /** Connection配置对象 */
    private static ConnectionConfig connectionConfig = null;

    /** Socket配置对象 */
    private static SocketConfig socketConfig = null;

    /** Request配置对象 */
    private static RequestConfig requestConfig = null;

    /** Cookie存储对象 */
    private static BasicCookieStore cookieStore = null;


    static {
        init();
    }

    /**
     * 全局对象初始化
     */
    private static void init() {
        // 创建Connection配置对象
        connectionConfig = ConnectionConfig.custom()
                .setMalformedInputAction(CodingErrorAction.IGNORE)
                .setUnmappableInputAction(CodingErrorAction.IGNORE)
                .setCharset(Consts.UTF_8).build();

        // 创建Socket配置对象
        socketConfig = SocketConfig.custom().setTcpNoDelay(true).build();

        // 创建Request配置对象
        requestConfig = RequestConfig.custom()
                .setConnectionRequestTimeout(CONNECTION_REQUEST_TIMEOUT)
                .setConnectTimeout(CONNECTION_TIMEOUT)
                .setSocketTimeout(SOCKET_TIMEOUT)
                .build();

        // 创建Cookie存储对象(服务端返回的Cookie保存在CookieStore中,下次再访问时才会将CookieStore中的Cookie发送给服务端)
        cookieStore = new BasicCookieStore();

        // 创建HttpClient对象
        httpClient = HttpClients.custom()
                .setDefaultConnectionConfig(connectionConfig)
                .setDefaultSocketConfig(socketConfig)
                .setDefaultRequestConfig(requestConfig)
                .setDefaultCookieStore(cookieStore)
                .setUserAgent(USER_AGENT)
                .setMaxConnTotal(MAX_CONN_TOTAL)
                .setMaxConnPerRoute(MAX_CONN_PER_ROUTE)
                .build();
    }

     /**
     * 发送Get请求
     * @param url 请求的地址
     * @param parameters 请求的数据
     * @param cookies 请求的Cookie信息
     * @param headers 请求的头部信息
     * @param charset 请求数据的字符编码
     */
    public static HttpResult sendGet(String url, Map<String, String> parameters, Header[] headers, Cookie[] cookies, String charset){
        HttpResult httpResult = null;
        try {
            // 创建URI并设置参数
            URIBuilder builder = new URIBuilder(url);
            if (parameters != null && !parameters.isEmpty()) {
                builder.addParameters(assemblyParameter(parameters));
            }
            if (charset != null) {
                builder.setCharset(Charset.forName(charset));
            }
            URI uri = builder.build();

            // 创建HttpGet
            HttpGet httpGet = new HttpGet(uri);

            // 设置Header
            if (headers != null) {
                /**
                 * httpGet.setHeaders(headers),重新设置Header,前面set或者add的Header都会被去掉
                 * httpGet.setHeader(header):如果已经有了同名的Header,则覆盖同名的Header,如果没有,则添加Header
                 * httpGet.addHeader(header):不管是否已经有了同名的Header,都添加Header,可能会导致存在同名的Header
                 */
                httpGet.setHeaders(headers);
            }

            // 设置Cookie
            if (cookies != null) {
                /**
                 * Cookie必须通过Header来设置
                 */
                httpGet.setHeader("cookie", assemblyCookie(cookies));
            }

            // 发送Post请求并得到响应结果
            httpResult = httpClient.execute(httpGet, getResponseHandler());
        } catch (Exception e) {
            e.printStackTrace();
        }
        return httpResult;
    }

    /**
     * 发送Post请求(Form格式的数据)
     * @param url 请求的地址
     * @param parameters 请求的Form数据
     * @param cookies 请求的Cookie信息
     * @param headers 请求的头部信息
     * @param charset 请求数据的字符编码
     */
    public static HttpResult sendPostForm(String url, Map<String, String> parameters, Header[] headers, Cookie[] cookies, String charset) {
        HttpResult httpResult = null;
        try {
            // 创建HttpPost
            HttpPost httpPost = new HttpPost(url);

            // 设置请求数据
            if (parameters != null && !parameters.isEmpty()) {
                httpPost.setEntity(assemblyFormEntity(parameters, charset));
            }

            // 设置Header
            if (headers != null) {
                /**
                 * httpGet.setHeaders(headers),重新设置Header,前面set或者add的Header都会被去掉
                 * httpGet.setHeader(header):如果已经有了同名的Header,则覆盖同名的Header,如果没有,则添加Header
                 * httpGet.addHeader(header):不管是否已经有了同名的Header,都添加Header,可能会导致存在同名的Header
                 */
                httpPost.setHeaders(headers);
            }

            // 设置Cookie
            if (cookies != null) {
                /**
                 * Cookie必须通过Header来设置
                 */
                httpPost.setHeader("cookie", assemblyCookie(cookies));
            }

            // 发送Post请求并得到响应结果
            httpResult = httpClient.execute(httpPost, getResponseHandler());
        } catch (Exception e) {
            e.printStackTrace();
        }
        return httpResult;
    }

    /**
     * 发送Post请求(Json格式的数据)
     * @param url 请求的地址
     * @param jsonData 请求的Json数据
     * @param cookies 请求的Cookie信息
     * @param headers 请求的头部信息
     * @param charset 请求数据的字符编码
     */
    public static HttpResult sendPostJson(String url, String jsonData, Header[] headers, Cookie[] cookies, String charset) {
        HttpResult httpResult = null;

        try {
            // 创建HttpPost
            HttpPost httpPost = new HttpPost(url);

            // 设置请求数据
            httpPost.setEntity(assemblyStringEntity(jsonData, charset));

            // 设置Header
            if (headers != null) {
                /**
                 * httpGet.setHeaders(headers),重新设置Header,前面set或者add的Header都会被去掉
                 * httpGet.setHeader(header):如果已经有了同名的Header,则覆盖同名的Header,如果没有,则添加Header
                 * httpGet.addHeader(header):不管是否已经有了同名的Header,都添加Header,可能会导致存在同名的Header
                 */
                httpPost.setHeaders(headers);
            }

            // 设置Cookie
            if (cookies != null) {
                /**
                 * Cookie必须通过Header来设置
                 */
                httpPost.setHeader("cookie", assemblyCookie(cookies));
            }

            // 发送Post请求并得到响应结果
            httpResult = httpClient.execute(httpPost, getResponseHandler());
        } catch (Exception e) {
            e.printStackTrace();
        }
        return httpResult;
    }

    /**
     * 获取响应结果处理器(把响应结果封装成HttpResult对象)
     */
    private static ResponseHandler<HttpResult> getResponseHandler() {
        ResponseHandler<HttpResult> responseHandler = new ResponseHandler<HttpResult>() {
            @Override
            public HttpResult handleResponse(HttpResponse httpResponse) throws ClientProtocolException, IOException {
                if (httpResponse == null) {
                    throw new ClientProtocolException("HttpResponse is null");
                }

                StatusLine statusLine = httpResponse.getStatusLine();
                HttpEntity httpEntity = httpResponse.getEntity();
                if (statusLine == null) {
                    throw new ClientProtocolException("HttpResponse contains no StatusLine");
                }
                if (statusLine.getStatusCode() != 200) {
                    throw new HttpResponseException(statusLine.getStatusCode(), statusLine.getReasonPhrase());
                }
                if (httpEntity == null) {
                    throw new ClientProtocolException("HttpResponse contains no HttpEntity");
                }

                HttpResult httpResult = new HttpResult();
                httpResult.setStatusCode(statusLine.getStatusCode());
                ContentType contentType = ContentType.getOrDefault(httpEntity);
                httpResult.setContentType(contentType.toString());
                boolean isTextType = isTextType(contentType);
                httpResult.setTextType(isTextType);
                if (isTextType) {
                    httpResult.setStringContent(EntityUtils.toString(httpEntity));
                } else {
                    httpResult.setByteArrayContent(EntityUtils.toByteArray(httpEntity));
                }
                httpResult.setCookies(cookieStore.getCookies());
                httpResult.setHeaders(httpResponse.getAllHeaders());

                return httpResult;
            }
        };
        return responseHandler;
    }

    /**
     * 组装Get请求的请求参数
     * @param parameters 参数信息集合
     */
    private static List<NameValuePair> assemblyParameter(Map<String, String> parameters) {
        List<NameValuePair> allParameter = new ArrayList<>();
        if (parameters != null && !parameters.isEmpty()) {
            for (String name : parameters.keySet()) {
                NameValuePair parameter = new BasicNameValuePair(name, parameters.get(name));
                allParameter.add(parameter);
            }
        }
        return allParameter;
    }

    /**
     * 组装Post请求的Form请求体
     * @param parameters 请求的表单参数
     * @param charset 请求参数的字符编码
     */
    private static UrlEncodedFormEntity assemblyFormEntity(Map<String, String> parameters, String charset) {
        List<NameValuePair> formParameters = assemblyParameter(parameters);
        UrlEncodedFormEntity formEntity = null;
        try {
            if (charset != null) {
                formEntity = new UrlEncodedFormEntity(formParameters, charset);
            } else {
                formEntity = new UrlEncodedFormEntity(formParameters);
            }
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return formEntity;
    }

    /**
     * 组装Post请求的Json请求体
     * @param jsonData 请求的Json数据
     * @param charset 请求参数的字符编码
     */
    private static StringEntity assemblyStringEntity(String jsonData, String charset) {
		/**
         * jsonData不能为null和"",否则无法创建StringEntity。
         * Json类型的请求体,必须传一个不为null的StringEntity给服务端。
         * 如果jsonData为null或""时,则进行特殊处理。
         */
        if (jsonData == null || jsonData.equals("")) {
            jsonData = "{}";
        }
        StringEntity stringEntity = new StringEntity(jsonData, ContentType.APPLICATION_JSON);
        if (charset != null) {
            stringEntity.setContentEncoding(charset);
        }
        return stringEntity;
    }

    /**
     * 组装Cookie
     * @param cookies 所有的Cookie数据
     */
    private static String assemblyCookie(Cookie[] cookies) {
        StringBuilder sb = new StringBuilder();
        if (cookies != null) {
            for(Cookie cookie : cookies) {
                sb.append(cookie.getName()).append("=").append(cookie.getValue()).append(";");
            }
        }
        return sb.toString();
    }

    /**
     * 判断响应的内容是否是文本类型
     * @param contentType 响应内容的类型
     */
    private static boolean isTextType(ContentType contentType) {
        if (contentType == null) {
            throw new RuntimeException("ContentType is null");
        }
        if (contentType.getMimeType().startsWith("text")) {
            return true;
        } else if (contentType.getMimeType().startsWith("image")) {
            return false;
        } else if (contentType.getMimeType().startsWith("application")) {
            if (contentType.getMimeType().contains("json") || contentType.getMimeType().contains("xml")) {
                return true;
            } else {
                return false;
            }
        } else if (contentType.getMimeType().startsWith("multipart")) {
            return false;
        } else {
            return true;
        }
    }

}

HttpClientApplication主启动类程序如下所示:

package com.http.client;

import com.http.client.model.HttpResult;
import com.http.client.util.HttpClientUtil;
import org.apache.http.Header;
import org.apache.http.cookie.Cookie;
import org.apache.http.impl.cookie.BasicClientCookie;
import org.apache.http.message.BasicHeader;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

/**
 * HttpClient使用方法封装类的测试主程序
 */
@SpringBootApplication
public class HttpClientApplication {

    /**
     * 文本类型返回结果测试URL
     */
    private static String httpGetByParameterUrl = "http://localhost:8080/api/httpGetByParameter";
    private static String httpGetByEntityUrl = "http://localhost:8080/api/httpGetByEntity";
    private static String httpPostByFormUrl = "http://localhost:8080/api/httpPostByForm";
    private static String httpPostByJsonUrl = "http://localhost:8080/api/httpPostByJson";

    /**
     * 二进制类型返回结果测试URL
     */
    private static String httpGetBinaryUrl = "https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1551940859395&di=f7cfc5afa3b2768161b351522af87409&imgtype=0&src=http%3A%2F%2Fimg.zcool.cn%2Fcommunity%2F0148e758afd26fa801219c77fbda55.jpg";


    public static void main(String[] args) throws IOException {
        SpringApplication.run(HttpClientApplication.class, args);
        
		// 测试HttpClientUtil的sendGet():服务端使用Parameter的形式接收Get请求发送过来的数据,并返回文本数据
		// testHttpClientUtil_sendGet(httpGetByParameterUrl);

		// 测试HttpClientUtil的sendGet():服务端使用实体类的形式接收Get请求发送过来的数据,并返回文本数据
		// testHttpClientUtil_sendGet(httpGetByEntityUrl);

		// 测试HttpClientUtil的sendGet():服务端返回字节数据
		// testHttpClientUtil_sendGet_ByteArray(httpGetBinaryUrl);

		// 测试HttpClientUtil的sendPostForm():服务端接收Post请求发送过来的Form形式的数据,并返回文本数据
		// testHttpClientUtil_sendPostForm(httpPostByFormUrl);

		// 测试HttpClientUtil的sendPostJson():服务端接收Post请求发送过来的Json形式的数据,并返回文本数据
		// testHttpClientUtil_sendPostJson(httpPostByJsonUrl);
    }

    /**
     * 测试HttpClientUtil的sendGet()
     */
    public static void testHttpClientUtil_sendGet(String url) throws IOException {
        // 创建请求参数
        Map<String, String> parameters = getParameterUser();
        Header[] headers = getHeaders();
        BasicClientCookie[] cookies = getCookies();

        // 发送Get请求并得到响应结果
        HttpResult httpResult = HttpClientUtil.sendGet(url, parameters, headers, cookies, "UTF-8");

        // 处理响应结果
        handleHttpResult(httpResult);
    }

    /**
     * 测试HttpClientUtil的sendGet()
     */
    public static void testHttpClientUtil_sendGet_ByteArray(String url) throws IOException {
        // 发送Get请求并得到响应结果
        HttpResult httpResult = HttpClientUtil.sendGet(url, null, null, null, "UTF-8");

        // 处理响应结果
        handleHttpResult(httpResult);
    }
    
    /**
     * 测试HttpClientUtil的sendPostForm()
     */
    public static void testHttpClientUtil_sendPostForm(String url) throws IOException {
        // 创建请求参数
        Map<String, String> parameters = getParameterUser();
        Header[] headers = getHeaders();
        BasicClientCookie[] cookies = getCookies();

        // 发送Post请求并得到响应结果
        HttpResult httpResult = HttpClientUtil.sendPostForm(url, parameters, headers, cookies, "UTF-8");

        // 处理响应结果
        handleHttpResult(httpResult);
    }

    /**
     * 测试HttpClientUtil的sendPostJson()
     */
    public static void testHttpClientUtil_sendPostJson(String url) throws IOException {
        // 创建请求参数
        String jsonData = getJsonUser();
        Header[] headers = getHeaders();
        BasicClientCookie[] cookies = getCookies();

        // 发送Post请求并得到响应结果
        HttpResult httpResult = HttpClientUtil.sendPostJson(url, jsonData, headers, cookies, "UTF-8");

        // 处理响应结果
        handleHttpResult(httpResult);
    }

    /**
     * 创建并获取Form形式的用户信息
     */
    private static Map<String, String> getParameterUser() {
        Map<String, String> parameterUser = new HashMap<>();
        parameterUser.put("id", "1001");
        parameterUser.put("name", "JavaBigData1024");
        parameterUser.put("sex", "true");
        return parameterUser;
    }

    /**
     * 创建并获取Json形式的用户信息
     */
    private static String getJsonUser() {
        String jsonUser = "{\n" +
                "    \"id\":\"1001\",\n" +
                "    \"name\":\"JavaBigData1024\",\n" +
                "    \"sex\":\"true\"\n" +
                "}";
        return jsonUser;
    }

    /**
     * 创建并获取Header信息
     */
    private static Header[] getHeaders() {
        Header[] headers = new Header[2];
        headers[0] = new BasicHeader("sendHeaderName_1", "sendHeaderValue_1");
        headers[1] = new BasicHeader("sendHeaderName_2", "sendHeaderValue_2");
        return headers;
    }

    /**
     * 创建并获取Cookie信息
     */
    private static BasicClientCookie[] getCookies() {
        BasicClientCookie[] cookies = new BasicClientCookie[2];
        cookies[0] = new BasicClientCookie("sendCookieName_1", "sendCookieValue_1");
        cookies[0].setVersion(0);
        cookies[0].setDomain("xxx.cn");
        cookies[0].setPath("/x");
        cookies[1] = new BasicClientCookie("sendCookieName_2", "sendCookieValue_2");
        cookies[1].setVersion(0);
        cookies[1].setDomain("xxx.cn");
        cookies[1].setPath("/x");
        return cookies;
    }

    /**
     * 处理响应结果
     */
    private static void handleHttpResult(HttpResult httpResult) throws IOException {
        System.out.println("响应状态码:" + httpResult.getStatusCode());
        System.out.println("响应结果类型:" + httpResult.getContentType());
        System.out.println("响应结果是否是文本:" +httpResult.isTextType());
        if(httpResult.isTextType()) {
            System.out.println("\n响应的文本结果如下:");
            System.out.println(httpResult.getStringContent());
        } else {
            System.out.println("\n响应的字节结果如下");
            System.out.println(httpResult.getByteArrayContent());
            File image = new File("E:/image.jpg");
            FileOutputStream fos = new FileOutputStream(image);
            fos.write(httpResult.getByteArrayContent());
            fos.flush();
            fos.close();
        }

        if(httpResult.getHeaders() != null) {
            System.out.println("\n响应的Header如下:");
            for(Header header : httpResult.getHeaders()) {
                System.out.println(header.getName() + " : " +header.getValue());
            }
        }

        if(httpResult.getCookies() != null) {
            System.out.println("\n响应的Cookie如下:");
            for (Cookie cookie : httpResult.getCookies()) {
                System.out.println(cookie.getName() + " : " + cookie.getValue() + " : " + cookie.getDomain() + " : " + cookie.getPath());
            }
        }
    }

}

4 创建HttpClientService服务端工程

4.1 版本说明

  1. Spring Boot: 2.1.13
  2. JDK: 1.8
  3. IDE: IDEA

4.2 创建项目

创建一个名为HttpClientService的Spring Boot项目,并添加maven依赖和相应的Java代码,最后的项目结构如下图所示:
在这里插入图片描述
application.yml配置文件如下所示:

server:
  port: 8080

pom.xml文件内容如下所示:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.http.client.service</groupId>
    <artifactId>http-client-service</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>HttpClientService</name>
    <description>HttpClient服务提供者</description>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.3.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <properties>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

User类程序如下所示:

package com.http.client.service.model;

/**
 * 用户信息实体
 */
public class User {
    private String id;
    private String name;
    private String sex;

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }
}

HttpClientController类程序如下所示:

package com.http.client.service.controller;

import com.http.client.service.model.User;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Enumeration;

/**
 * Restful接口服务入口
 */
@RestController
@RequestMapping("/api")
public class HttpClientController {

    /**
     * HttpGet方法接口(以Parameter的形式接收数据)
     */
    @GetMapping(value = "/httpGetByParameter")
    public String httpGetByParameter(HttpServletRequest request, HttpServletResponse response,
                                 @RequestParam("id") String id, @RequestParam("name") String name,
                                 @RequestParam("sex") String sex) {
        System.out.println("请求的User如下:");
        System.out.println("id=" + id);
        System.out.println("name=" + name);
        System.out.println("sex=" + sex);
        handleHeaderAndCookie(request, response);
        return "getByParameterSuccess";
    }

    /**
     * HttpGet方法接口(以实体对象的形式接收数据)
     */
    @GetMapping(value = "/httpGetByEntity")
    public String httpGetByEntity(HttpServletRequest request, HttpServletResponse response, User user) {
        System.out.println("请求的User如下:\n" + user.toString());
        handleHeaderAndCookie(request, response);
        return "getByEntitySuccess";
    }

    /**
     * HttpPost方法接口(以Form的形式接收数据)
     */
    @PostMapping(value = "/httpPostByForm")
    public String httpPostByForm(HttpServletRequest request, HttpServletResponse response, User user) {
        System.out.println("请求的User如下:\n" + user.toString());
        handleHeaderAndCookie(request, response);
        return "postByFormSuccess";
    }

    /**
     * HttpPost方法接口(以Json的形式接收数据)
     */
    @PostMapping(value = "/httpPostByJson")
    public String httpPostByJson(HttpServletRequest request, HttpServletResponse response, @RequestBody User user) {
        System.out.println("请求的User如下:\n" + user.toString());
        handleHeaderAndCookie(request, response);
        return "postByJsonSuccess";
    }

    /**
     * Header处理和Cookie处理
     */
    private void handleHeaderAndCookie(HttpServletRequest request, HttpServletResponse response) {
        // 打印从客户端接收到的Header
        Enumeration<String> headerNames =  request.getHeaderNames();
        if (headerNames != null) {
            System.out.println("\n请求的Header如下:");
            while (headerNames.hasMoreElements()) {
                String headerName = headerNames.nextElement();
                String headerValue = request.getHeader(headerName);
                System.out.println("HeaderName:" + headerName + "; HeaderValue:" + headerValue);
            }
        }

        // 打印从客户端接收到的Cookie
        Cookie[] cookies = request.getCookies();
        if (cookies != null) {
            System.out.println("\n请求的Cookie如下:");
            for (Cookie cookie : cookies) {
                String cookieName = cookie.getName();
                String cookieValue = cookie.getValue();
                String cookieDomain = cookie.getDomain();
                String cookiePath = cookie.getPath();
                System.out.println("CookieName:" + cookieName + "; CookieValue:" + cookieValue + "; CookieDomain:" + cookieDomain + "; CookiePath:" + cookiePath);
            }
        }

        // 返回Header给客户端
        response.addHeader("responseHeaderName_1", "responseHeaderValue_1");
        response.addHeader("responseHeaderName_2", "responseHeaderValue_2");

        // 返回Cookie给客户端
        response.addCookie(new Cookie("responseCookieName_1", "responseCookieValue_1"));
        response.addCookie(new Cookie("responseCookieName_2", "responseCookieValue_2"));
    }

}

HttpClientServiceApplication主启动类程序如下所示:

package com.http.client.service;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ComponentScan;

/**
 * Restful接口服务主程序
 */
@ComponentScan("com.http.client.service.controller")
@SpringBootApplication
public class HttpClientServiceApplication {

    public static void main(String[] args) {
        SpringApplication.run(HttpClientServiceApplication.class, args);
    }

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

5 测试

1 启动HttpClientService服务端工程

直接运行HttpClientServiceApplication主启动类即可启动该Restful API接口服务端工程。

2 测试使用HttpClient发送Get请求

去掉HttpClientApplication主启动类main()方法中以下这一行前面的注释,然后直接运行HttpClientApplication主启动类,即可测试使用HttpClient发送Get请求:

// testHttpClientUtil_sendGet(httpGetByParameterUrl); 
  • 1

运行成功后,在HttpClientService工程的控制台可以看到如下输出:
在这里插入图片描述
在HttpClient工程的控制台可以看到如下输出:
在这里插入图片描述
从上图可见,在HttpClient工程中使用HttpClient发送的Get请求成功访问了HttpClientService工程中的httpGetByParameter()接口,此外,Get请求发送的用户数据、Header、Cookie都发送成功,而且Get请求也成功的获取到了响应数据、Header、Cookie。

同样可测testHttpClientUtil_sendGet_ ByteArray(httpGetByEntity)和testHttpClientUtil_sendGet(httpGetBinaryUrl)。

3 测试使用HttpClient发送Post请求

去掉HttpClientApplication主启动类main()方法中以下这一行前面的注释,然后直接运行HttpClientApplication主启动类,即可测试使用HttpClient发送Postt请求:

// testHttpClientUtil_sendPostForm(httpPostByFormUrl);

 

运行成功后,在HttpClientService工程的控制台可以看到如下输出:
在这里插入图片描述
在HttpClient工程的控制台可以看到如下输出:
在这里插入图片描述
从上图可见,在HttpClient工程中使用HttpClient发送的Post请求成功访问了HttpClientService工程中的httpPostByForm()接口,此外,Post请求发送的用户数据、Header、Cookie都发送成功,而且Post请求也成功的获取到了响应数据、Header、Cookie。

同样可测testHttpClientUtil_sendPostJson(httpPostByJsonUrl) 。

4 测试CookieStore的作用

由于HttpClient类库中的CookieStore是用于保存从服务器端返回的Cookie,下次再访问该服务器时才将之前保存在CookieStore中的Cookie发送给该服务器,因此,测试CookieStore的作用需要两步:先从服务器端获取Cookie、再向服务器端发送Cookie,即要连续发送两次请求。

为了模拟连续发送两次请求(第一次为Get请求,第二次为Post请求),去掉HttpClientApplication主启动类main()方法中以下这两行前面的注释,然后直接运行HttpClientApplication主启动类,即可测试CookieStore的作用,:

// testHttpClientUtil_sendGet(httpGetByEntityUrl);
// testHttpClientUtil_sendPostJson(httpPostByJsonUrl);

 

运行成功后,在HttpClientService工程的控制台可以看到如下输出:
第一次Get请求:
在这里插入图片描述
第二次Post请求:
在这里插入图片描述
在HttpClient工程的控制台可以看到如下输出:
第一次Get请求:
在这里插入图片描述
第二次Post请求:
在这里插入图片描述
从上图可见,连续发送的两次请求都请求成功并且成功获取到响应结果。第一次Get请求后,HttpClientService服务端只接收到了HttpClient客户端发送过来的Cookie,而在第二次Post请求后,HttpClientService服务端不仅接收到了HttpClient客户端发送过来的Cookie,而且还接收到了第一次Get请求后返回给HttpClient客户端的Cookie。由此可见,CookieStore确实保存了第一次Get请求从服务器端返回的Cookie,而在第二次Post请求时又将第一次Get请求返回的Cookie发送给了服务器。

此外,还可以看出,服务端返回的Cookie是以Header的形式返回的,具体而言是服务端返回名为"Set-Cookie"的Header给客户端,而客户端收到名为"Set-Cookie"的Header后,则解析为Cookie并保存到CookieStore中。

6 总结

HttpClient类库提供的功能十分丰富,也很全面,而本文则只是简要的介绍了最常用的使用HttpClient发送Get请求和Post请求这两种情况,相信对于帮助读者了解并简单的使用HttpClient还是足够的。

如果觉得本文对您有帮助,请关注博主的微信公众号,会经常分享一些Java和大数据方面的技术案例!
在这里插入图片描述

 

 

 

获取httpClient发出去的请求报文:

请求头部

postMethod.getAllHeaders()

请求行

postMethod.getRequestLine()

请求数据

postMethod.getEntity()
  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值