• HttpClient


    简介

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

            HTTP 和浏览器有点像,但却不是浏览器。很多人觉得既然 HttpClient 是一个 HTTP 客户端编程工具,很多人把他当做浏览器来理解,但是其实 HttpClient 不是浏览器,它是一个 HTTP 通信库,因此它只提供一个通用浏览器应用程序所期望的功能子集,最根本的区别是 HttpClient  中没有用户界面,浏览器需要一个渲染引擎来显示页面,并解释用户输入,例如鼠标点击显示页面上的某处,有一个布局引擎,计算如何显示 HTML 页面,包括级联样式表和图像。javascript 解释器运行嵌入 HTML 页面或从 HTML 页面引用的 javascript 代码。来自用户界面的事件被传递到 javascript 解释器进行处理。除此之外,还有用于插件的接口,可以处理 Applet,嵌入式媒体对象(如 pdf 文件,Quicktime 电影和 Flash 动画)或 ActiveX 控件(可以执行任何操作)。HttpClient 只能以编程的方式通过其 API 用于传输和接受 HTTP 消息。

    HttpClient 的主要功能:

    • 实现了所有 HTTP 的方法(GET、POST、PUT、HEAD、DELETE、HEAD、OPTIONS 等)
    • 支持 HTTPS 协议
    • 支持代理服务器(Nginx 等)等
    • 支持自动(跳转)转向
    • ……

    环境说明:JDK1.8、SpringBoot

    准备环节

    引入依赖

    <!-- fastjson -->
    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>fastjson</artifactId>
        <version>1.2.47</version>
    </dependency>
    
    <!-- httpclient -->
    <dependency>
        <groupId>org.apache.httpcomponents</groupId>
        <artifactId>httpclient</artifactId>
        <version>4.5.5</version>
    </dependency>

    注意:

    • 本人引入此依赖的目的是,在后续示例中,会用到“将对象转化为 json 字符串的功能”,也可以引其他有此功能的依赖。
    • SpringBoot 的基本依赖配置,这里就不再多说了。

    详细使用示例

    声明:此示例中,以 JAVA 发送 HttpClient(在 test 里面单元测试发送的);也是以 JAVA 接收的(在 controller 里面接收的)。

    声明:下面的代码,本人亲测有效。注意:函数中的异常没有捕获,正常情况需要捕获,且资源关闭需要放到 finally 中。

    GET 无参

    HttpClient 发送示例:

    /**
     * GET---无参测试
     */
    @Test
    public void doGetTestOne() throws Exception {
        // 获得Http客户端(可以理解为:你得先有一个浏览器;注意:实际上HttpClient与浏览器是不一样的)
        CloseableHttpClient httpClient = HttpClientBuilder.create().build();
        // 创建Get请求
        HttpGet httpGet = new HttpGet("http://127.0.0.1:8888/doGetControllerOne");
    
        // 响应模型
        CloseableHttpResponse response = httpClient.execute(httpGet);// 由客户端执行(发送)Get请求
        // 从响应模型中获取响应实体
        HttpEntity responseEntity = response.getEntity();
        System.out.println("响应状态为:" + response.getStatusLine());
        if (responseEntity != null) {
            System.out.println("响应内容长度为:" + responseEntity.getContentLength());
            System.out.println("响应内容为:" + EntityUtils.toString(responseEntity));
        }
        if (response != null) {
            response.close();
        }
        // 释放资源
        if (httpClient != null) {
            httpClient.close();
        }
    }

    接收示例:

    /**
     * GET无参
     */
    @RequestMapping("/doGetControllerOne")
    public String doGetControllerOne() {
        return "123";
    }

    控制台打印:

    响应状态为:HTTP/1.1 200 
    响应内容长度为:3
    响应内容为:123

    GET有参(方式一:直接拼接URL)

    HttpClient 发送示例:

    /**
     * GET---有参测试 (方式一:手动在url后面加上参数)
     */
    @Test
    public void doGetTestWayOne() throws Exception {
        // 获得Http客户端(可以理解为:你得先有一个浏览器;注意:实际上HttpClient与浏览器是不一样的)
        CloseableHttpClient httpClient = HttpClientBuilder.create().build();
    
        // 参数
        StringBuilder params = new StringBuilder();
        // 字符数据最好encoding以下;这样一来,某些特殊字符才能传过去(如:某人的名字就是“&”,不encoding的话,传不过去)
        params.append("name=").append(URLEncoder.encode("张三", "utf-8"));
        params.append("&");
        params.append("age=24");
    
        // 创建Get请求
        HttpGet httpGet = new HttpGet("http://localhost:8888/doGetControllerTwo" + "?" + params);
        // 响应模型
        CloseableHttpResponse response = null;
        // 配置信息
        RequestConfig requestConfig = RequestConfig.custom()
                // 设置连接超时时间(单位毫秒)
                .setConnectTimeout(5000)
                // 设置请求超时时间(单位毫秒)
                .setConnectionRequestTimeout(5000)
                // socket读写超时时间(单位毫秒)
                .setSocketTimeout(5000)
                // 设置是否允许重定向(默认为true)
                .setRedirectsEnabled(true).build();
    
        // 将上面的配置信息 运用到这个Get请求里
        httpGet.setConfig(requestConfig);
    
        // 由客户端执行(发送)Get请求
        response = httpClient.execute(httpGet);
        // 从响应模型中获取响应实体
        HttpEntity responseEntity = response.getEntity();
        System.out.println("响应状态为:" + response.getStatusLine());
        if (responseEntity != null) {
            System.out.println("响应内容长度为:" + responseEntity.getContentLength());
            System.out.println("响应内容为:" + EntityUtils.toString(responseEntity));
        }
        if (response != null) {
            response.close();
        }
        // 释放资源
        if (httpClient != null) {
            httpClient.close();
        }
    }

    接收示例:

    /**
     * GET有参
     */
    @RequestMapping("/doGetControllerTwo")
    public String doGetControllerTwo(String name, Integer age) {
        return "没想到[" + name + "]都" + age + "岁了!";
    }

    控制台打印:

    响应状态为:HTTP/1.1 200 
    响应内容长度为:29
    响应内容为:没想到[张三]都24岁了!

    GET 有参(方式二:使用 URI 获得 HttpGet)

    HttpClient 发送示例:

    /**
     * GET---有参测试 (方式二:将参数放入键值对类中,再放入URI中,从而通过URI得到HttpGet实例)
     */
    @Test
    public void doGetTestWayTwo() throws Exception {
        // 获得Http客户端(可以理解为:你得先有一个浏览器;注意:实际上HttpClient与浏览器是不一样的)
        CloseableHttpClient httpClient = HttpClientBuilder.create().build();
    
        // 参数
        URI uri = null;
        // 将参数放入键值对类NameValuePair中,再放入集合中
        List<NameValuePair> params = new ArrayList<>();
        params.add(new BasicNameValuePair("name", "&"));
        params.add(new BasicNameValuePair("age", "18"));
        // 设置uri信息,并将参数集合放入uri;
        // 注:这里也支持一个键值对一个键值对地往里面放setParameter(String key, String value)
        uri = new URIBuilder().setScheme("http").setHost("localhost")
                .setPort(8888).setPath("/doGetControllerTwo")
                .setParameters(params).build();
        // 创建Get请求
        HttpGet httpGet = new HttpGet(uri);
    
        // 响应模型
        CloseableHttpResponse response = null;
        // 配置信息
        RequestConfig requestConfig = RequestConfig.custom()
                // 设置连接超时时间(单位毫秒)
                .setConnectTimeout(5000)
                // 设置请求超时时间(单位毫秒)
                .setConnectionRequestTimeout(5000)
                // socket读写超时时间(单位毫秒)
                .setSocketTimeout(5000)
                // 设置是否允许重定向(默认为true)
                .setRedirectsEnabled(true).build();
    
        // 将上面的配置信息 运用到这个Get请求里
        httpGet.setConfig(requestConfig);
    
        // 由客户端执行(发送)Get请求
        response = httpClient.execute(httpGet);
        // 从响应模型中获取响应实体
        HttpEntity responseEntity = response.getEntity();
        System.out.println("响应状态为:" + response.getStatusLine());
        if (responseEntity != null) {
            System.out.println("响应内容长度为:" + responseEntity.getContentLength());
            System.out.println("响应内容为:" + EntityUtils.toString(responseEntity));
        }
        // 释放资源
        if (httpClient != null) {
            httpClient.close();
        }
        if (response != null) {
            response.close();
        }
    }

    接收示例:同上

    控制台打印:

    响应状态为:HTTP/1.1 200 
    响应内容长度为:24
    响应内容为:没想到[&]都18岁了!

    POST 无参

    HttpClient 发送示例:

    /**
     * POST---无参测试
     */
    @Test
    public void doPostTestOne() throws Exception {
    
        // 获得Http客户端(可以理解为:你得先有一个浏览器;注意:实际上HttpClient与浏览器是不一样的)
        CloseableHttpClient httpClient = HttpClients.createDefault();
    
        // 创建Post请求
        HttpPost httpPost = new HttpPost("http://localhost:8888/doPostControllerOne");
        // 响应模型
        CloseableHttpResponse response = httpClient.execute(httpPost);// 由客户端执行(发送)Post请求
        // 从响应模型中获取响应实体
        HttpEntity responseEntity = response.getEntity();
    
        System.out.println("响应状态为:" + response.getStatusLine());
        if (responseEntity != null) {
            System.out.println("响应内容长度为:" + responseEntity.getContentLength());
            System.out.println("响应内容为:" + EntityUtils.toString(responseEntity));
        }
    
        // 释放资源
        if (response != null) {
            response.close();
        }
        if (httpClient != null) {
            httpClient.close();
        }
    }

    接收示例:

    /**
     * POST无参
     */
    @RequestMapping(value = "/doPostControllerOne", method = RequestMethod.POST)
    public String doPostControllerOne() {
        return "这个post请求没有任何参数!";
    }

    控制台打印:

    响应状态为:HTTP/1.1 200 
    响应内容长度为:35
    响应内容为:这个post请求没有任何参数!

    POST 有参(普通参数,方式一:直接拼接URL)

    注:POST 传递普通参数时,方式与 GET 一样即可,这里以直接在 url 后缀上参数的方式示例。

    HttpClient 发送示例:

    /**
     * POST---有参测试(基本参数)
     */
    @Test
    public void doPostTestFour() throws Exception {
        // 获得Http客户端(可以理解为:你得先有一个浏览器;注意:实际上HttpClient与浏览器是不一样的)
        CloseableHttpClient httpClient = HttpClientBuilder.create().build();
    
        // 参数
        StringBuilder params = new StringBuilder();
        // 字符数据最好encoding以下;这样一来,某些特殊字符才能传过去(如:某人的名字就是“&”,不encoding的话,传不过去)
        params.append("name=").append(URLEncoder.encode("&", "utf-8"));
        params.append("&");
        params.append("age=24");
    
        // 创建Post请求
        HttpPost httpPost = new HttpPost("http://localhost:8888/doPostControllerFour" + "?" + params);
    
        // 设置ContentType(注:如果只是传普通参数的话,ContentType不一定非要用application/json)
        httpPost.setHeader("Content-Type", "application/json;charset=utf8");
    
        // 响应模型
        CloseableHttpResponse response = null;
        // 由客户端执行(发送)Post请求
        response = httpClient.execute(httpPost);
        // 从响应模型中获取响应实体
        HttpEntity responseEntity = response.getEntity();
    
        System.out.println("响应状态为:" + response.getStatusLine());
        if (responseEntity != null) {
            System.out.println("响应内容长度为:" + responseEntity.getContentLength());
            System.out.println("响应内容为:" + EntityUtils.toString(responseEntity));
        }
    
        // 释放资源
        if (response != null) {
            response.close();
        }
        if (httpClient != null) {
            httpClient.close();
        }
    }

    接收示例:

    /**
     * POST有参(普通参数)
     */
    @RequestMapping(value = "/doPostControllerFour", method = RequestMethod.POST)
    public String doPostControllerThree1(String name, Integer age) {
        return "[" + name + "]居然才[" + age + "]岁!!!";
    }

    控制台打印:

    响应状态为:HTTP/1.1 200 
    响应内容长度为:22
    响应内容为:[&]居然才[24]岁!!!

    POST 有参(普通参数,方式二:setEntity)

    /**
     * POST有参(普通参数)
     */
    @Test
    public void doPostTestFour2() throws Exception {
        // 创建默认的httpClient实例.
        CloseableHttpClient httpClient = HttpClients.createDefault();
        // 创建httppost
        HttpPost httppost = new HttpPost("http://localhost:8888/doPostControllerFour");
        // 创建参数队列
        List<NameValuePair> formparams = new ArrayList<NameValuePair>();
        formparams.add(new BasicNameValuePair("name", "&"));
        formparams.add(new BasicNameValuePair("age", "24"));
        UrlEncodedFormEntity uefEntity = new UrlEncodedFormEntity(formparams, "UTF-8");
    
        httppost.setEntity(uefEntity);
        System.out.println("executing request " + httppost.getURI());
        CloseableHttpResponse response = httpClient.execute(httppost);
        HttpEntity responseEntity = response.getEntity();
        System.out.println("响应状态为:" + response.getStatusLine());
        if (responseEntity != null) {
            System.out.println("响应内容长度为:" + responseEntity.getContentLength());
            System.out.println("响应内容为:" + EntityUtils.toString(responseEntity));
        }
    
        // 释放资源
        if (response != null) {
            response.close();
        }
        if (httpClient != null) {
            httpClient.close();
        }
    }

    接收示例和控制台打印同上

    POST 有参(对象参数)

    先给出 User 类

    /**
     * 用户实体类模型
     */
    public class User {
    
        /**
         * 姓名
         */
        private String name;
    
        /**
         * 年龄
         */
        private Integer age;
    
        /**
         * 性别
         */
        private String gender;
    
        /**
         * 座右铭
         */
        private String motto;
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public Integer getAge() {
            return age;
        }
    
        public void setAge(Integer age) {
            this.age = age;
        }
    
        public String getGender() {
            return gender;
        }
    
        public void setGender(String gender) {
            this.gender = gender;
        }
    
        public String getMotto() {
            return motto;
        }
    
        public void setMotto(String motto) {
            this.motto = motto;
        }
    
        @Override
        public String toString() {
            return age + "岁" + gender + "人[" + name + "]的座右铭居然是: " + motto + "!!!";
        }
    
    }
    User 类

    HttpClient 发送示例:

    /**
     * POST---有参测试(对象参数)
     */
    @Test
    public void doPostTestTwo() throws Exception {
    
        // 获得Http客户端(可以理解为:你得先有一个浏览器;注意:实际上HttpClient与浏览器是不一样的)
        CloseableHttpClient httpClient = HttpClientBuilder.create().build();
    
        // 创建Post请求
        HttpPost httpPost = new HttpPost("http://localhost:8888/doPostControllerTwo");
        User user = new User();
        user.setName("潘晓婷");
        user.setAge(18);
        user.setGender("女");
        user.setMotto("姿势要优雅~");
        // 我这里利用阿里的fastjson,将Object转换为json字符串;
        // (需要导入com.alibaba.fastjson.JSON包)
        String jsonString = JSON.toJSONString(user);
    
        StringEntity entity = new StringEntity(jsonString, "UTF-8");
    
        // post请求是将参数放在请求体里面传过去的;这里将entity放入post请求体中
        httpPost.setEntity(entity);
    
        httpPost.setHeader("Content-Type", "application/json;charset=utf8");
    
        // 响应模型
        CloseableHttpResponse response = httpClient.execute(httpPost);// 由客户端执行(发送)Post请求
        // 从响应模型中获取响应实体
        HttpEntity responseEntity = response.getEntity();
    
        System.out.println("响应状态为:" + response.getStatusLine());
        if (responseEntity != null) {
            System.out.println("响应内容长度为:" + responseEntity.getContentLength());
            System.out.println("响应内容为:" + EntityUtils.toString(responseEntity));
        }
        // 释放资源
        if (response != null) {
            response.close();
        }
        if (httpClient != null) {
            httpClient.close();
        }
    }

    接收示例:

    /**
     * POST有参(对象参数)
     */
    @RequestMapping(value = "/doPostControllerTwo", method = RequestMethod.POST)
    public String doPostControllerTwo(@RequestBody User user) {
        return user.toString();
    }

    控制台打印:

    响应状态为:HTTP/1.1 200 
    响应内容长度为:64
    响应内容为:18岁女人[潘晓婷]的座右铭居然是: 姿势要优雅~!!!

    POST 有参(普通参数 + 对象参数)

    注:POST 传递普通参数时,方式与 GET 一样即可,这里以通过 URI 获得 HttpPost 的方式为例。

    HttpClient 发送示例:

    /**
     * POST---有参测试(普通参数 + 对象参数)
     */
    @Test
    public void doPostTestThree() throws Exception {
    
        // 获得Http客户端(可以理解为:你得先有一个浏览器;注意:实际上HttpClient与浏览器是不一样的)
        CloseableHttpClient httpClient = HttpClientBuilder.create().build();
    
        // 创建Post请求
        // 参数
        URI uri = null;
        // 将参数放入键值对类NameValuePair中,再放入集合中
        List<NameValuePair> params = new ArrayList<>();
        params.add(new BasicNameValuePair("flag", "4"));
        params.add(new BasicNameValuePair("meaning", "这是什么鬼?"));
        // 设置uri信息,并将参数集合放入uri;
        // 注:这里也支持一个键值对一个键值对地往里面放setParameter(String key, String value)
        uri = new URIBuilder().setScheme("http").setHost("localhost").setPort(8888)
                .setPath("/doPostControllerThree").setParameters(params).build();
    
    
        HttpPost httpPost = new HttpPost(uri);
    
        // 创建user参数
        User user = new User();
        user.setName("潘晓婷");
        user.setAge(18);
        user.setGender("女");
        user.setMotto("姿势要优雅~");
    
        // 将user对象转换为json字符串,并放入entity中
        StringEntity entity = new StringEntity(JSON.toJSONString(user), "UTF-8");
    
        // post请求是将参数放在请求体里面传过去的;这里将entity放入post请求体中
        httpPost.setEntity(entity);
    
        httpPost.setHeader("Content-Type", "application/json;charset=utf8");
    
        // 响应模型
        CloseableHttpResponse response = null;
        // 由客户端执行(发送)Post请求
        response = httpClient.execute(httpPost);
        // 从响应模型中获取响应实体
        HttpEntity responseEntity = response.getEntity();
    
        System.out.println("响应状态为:" + response.getStatusLine());
        if (responseEntity != null) {
            System.out.println("响应内容长度为:" + responseEntity.getContentLength());
            System.out.println("响应内容为:" + EntityUtils.toString(responseEntity));
        }
    
        // 释放资源
        if (response != null) {
            response.close();
        }
        if (httpClient != null) {
            httpClient.close();
        }
    }

    接收示例:

    /**
     * POST有参(普通参数 + 对象参数)
     */
    @RequestMapping(value = "/doPostControllerThree", method = RequestMethod.POST)
    public String doPostControllerThree(@RequestBody User user,Integer flag, String meaning) {
        return user.toString() + "
    " + flag + ">>>" + meaning;
    }

    控制台打印:

    响应状态为:HTTP/1.1 200 
    响应内容长度为:87
    响应内容为:18岁女人[潘晓婷]的座右铭居然是: 姿势要优雅~!!!
    4>>>这是什么鬼?

    本文转载自:https://blog.csdn.net/justry_deng/article/details/81042379

    参考:https://blog.csdn.net/w372426096/article/details/82713315

  • 相关阅读:
    JavaWeb(一)
    有趣的天平秤假币问题
    栈应用——逆波兰式表达式的值
    栈应用——最长括号匹配
    倾力总结40条常见的移动端Web页面问题解决方案
    Emmet:HTML/CSS代码快速编写神器
    我的 Github 个人博客是怎样炼成的
    解决mac下atom安装插件失败问题
    Github建站全攻略
    OS X快捷键最最齐全版(官方版)
  • 原文地址:https://www.cnblogs.com/jwen1994/p/14110368.html
Copyright © 2020-2023  润新知