Apache HttpClient

文章目录

  • Apache HttpClient
    • 简介
    • Apache HttpClient特性
    • 使用流程
    • 使用实例
  • -END-

Apache HttpClient

简介

HttpClient 是 Apache Jakarta Common 下的子项目,用来提供高效的、最新的、功能丰富的支持 HTTP 协议的客户端编程工具包,并且它支持 HTTP 协议最新的版本和建议。HttpClient 已经应用在很多的项目中,比如 Apache Jakarta 上很著名的另外两个开源项目 Cactus 和 HTMLUnit 都使用了 HttpClient。

​ 使用HttpClient、可以灵活地发送HTTP请求,并且Apache HttpClient提供了很多自定义的请求内容的API(包括连接超时时间设置等)。方便了开发人员测试接口(基于HTTP协议的),既提高了开发效率,也方便了提高代码的健壮性。(后续的RestTemplate的底层也是HttpClient)因此熟悉掌握HttpClient是很重要的必修内容,掌握了HttpClient后,对于HTTP的协议的了解也会更加深刻。


Apache HttpClient特性

  • 基于标准,纯净的Java语言。实现了HTTP1.0和HTTP1.1
  • 以可扩展的面向对象的结构实现了 HTTP 全部的方法(GET, POST, PUT, DELETE, HEAD, OPTIONS, and TRACE)。
  • 支持 HTTPS 协议。
  • 通过 HTTP 代理建立透明的连接。
  • 利用 CONNECT 方法通过 HTTP 代理建立隧道的 HTTPS 连接。
  • Basic,Digest,NTLMv1,NTLMv2,NTLM2Session,SNPNEGO/Kerberos 认证方案。
  • 插件式的自定义认证方案。
  • 便携可靠的套接字工厂使它更容易的使用第三方解决方案。
  • 连接管理器支持多线程应用。支持设置最大连接数,同时支持设置每个主机的最大连接数,发现并关闭过期的连接。
  • 自动处理 Set-Cookie 中的 Cookie。
  • 插件式的自定义 Cookie 策略。
  • Request 的输出流可以避免流中内容直接缓冲到 Socket 服务器。
  • Response 的输入流可以有效的从 Socket 服务器直接读取相应内容。
  • 在 HTTP 1.0 和 HTTP 1.1 中利用 KeepAlive 保持持久连接。
  • 直接获取服务器发送的 response code 和 headers。
  • 设置连接超时的能力。
  • 实验性的支持 HTTP 1.1 response caching。

使用流程

  • 导入依赖

    	<dependencies>
            <dependency>
                <groupId>org.apache.httpcomponentsgroupId>
                <artifactId>httpclientartifactId>
                <version>4.5.13version>
            dependency>
            <dependency>
                <groupId>org.apache.httpcomponentsgroupId>
                <artifactId>httpmimeartifactId>
                <version>4.5.13version>
            dependency>
        dependencies>
    
  • 创建HttpClient对象(http客户端对象)

    CloseableHttpClient client = HttpClientBuilder.create().build();//方式一
    CloseableHttpClient client = HttpClients.createDefault();//方式二
    

    两种方式相同,因为方式二的底层就是方式一。

  • 创建请求方法的实例,并指定URL。因为HttpClient是实现了所有Http请求方法,我们只需要创建请求方法实例(Httpxxx),在方法实例中指定URL即可,例如我们要发送Get请求,就创建HttpGet对象。

  • 如果需要发送带有参数的请求,可调用HttpGet、HttpPost共同的setParam(HttpParams params)来添加参数(该方法已经过时/弃用了);HttpGet推荐使用单独创建uri,构建自己的带参数的get请求的uri。HttpPost请求则是调用setEntity(HttpEntity entity)方法来设置请求参数(可以设置对象)。

  • 发送请求则是HttpClient的工作,调用HttpClientexecute(HttpUriRequeset request)发送请求,该方法会返回一个HttpResponse(响应模板)

  • 调用HttpResponsegetAllHeader()getHeaders(Sring name)等方法可以获取服务器的响应头,除此之外还可以获取状态码等。通过HttpResponsegetEntity()方法可以获取响应的响应实体,该对象包装了服务器的响应内容,程序可以通过该对象获取服务器的响应内容。

  • 最后需要释放资源,关闭HttpClientreseponse的资源连接

使用实例

GET请求

public class GetClient {
    /**
     * GET---无参测试
     */
    public void doGetTestOne(){
        //获得http客户端
        CloseableHttpClient client = HttpClientBuilder.create().build();
        //创建get请求
        HttpGet httpGet = new HttpGet("https://www.cuit.edu.cn/");
        //响应模型
        CloseableHttpResponse response = null;
        try{
            //有客户端指定get请求
            response = client.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));
            }
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            try{
                //释放资源
                if(client!=null){
                    client.close();
                }
                if (response!=null){
                    response.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * GET--有参测试
     */
    public void doGetTestWayOne(){
        //获得http客户端
        CloseableHttpClient client = HttpClientBuilder.create().build();

        //参数
        StringBuilder params = new StringBuilder();
        try{
            params.append("name=").append(URLEncoder.encode("&","utf-8")).append("&").append("age=24");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }

        //创建Get请求
        HttpGet httpGet = new HttpGet("https://www.cuit.edu.cn/?" + params);
        //响应模型
        CloseableHttpResponse response = null;
        try{
            //配置信息
            RequestConfig config = RequestConfig.custom()
                    //设置连接超时时间
                    .setConnectTimeout(5000)
                    //设置请求超时时间
                    .setConnectionRequestTimeout(5000)
                    //socket读写超时时间
                    .setSocketTimeout(5000)
                    //设置是否允许重定向(默认为true)
                    .setRedirectsEnabled(true)
                    .build();
            //将上面的配置信息配入Get请求中
            httpGet.setConfig(config);

            //由客户端执行Get请求
            response = client.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,"utf-8"));
            }

        } catch (ClientProtocolException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            try {
                if(client!=null){
                    client.close();
                }
                if (response!=null){
                    response.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }

    public void doGetTestWayTwo(){
        CloseableHttpClient client = HttpClientBuilder.create().build();
        URI uri = null;
        try{
            ArrayList<NameValuePair> params = new ArrayList<>();
            params.add(new BasicNameValuePair("name","10"));
            params.add(new BasicNameValuePair("age","18"));
            //这里设置uri信息,并将参数集合放入uri;
            //注: 这里也支持一个键值对一个键值对地往里面方setParameter(String key, String value)
            uri = new URIBuilder().setScheme("http").setHost("www.cuit.edu.cn")
//                    .setPort(12345).setPath("/xw")
                    .setParameters(params).build();
            System.out.println(uri);

        } catch (URISyntaxException e) {
            e.printStackTrace();
        }
        //创建httpGet请求
        HttpGet httpGet = new HttpGet(uri);

        //创建响应模型
        CloseableHttpResponse response = null;
        try{
            RequestConfig config = RequestConfig.custom()
                    .setConnectTimeout(5000)
                    .setConnectionRequestTimeout(5000)
                    .setSocketTimeout(5000)
                    .setRedirectsEnabled(true).build();

            httpGet.setConfig(config);
            response = client.execute(httpGet);

            HttpEntity entity = response.getEntity();
            System.out.println("响应状态码:"+response.getStatusLine());

            System.out.println("响应内容长度:"+entity.getContentLength());
            System.out.println("响应内容:"+EntityUtils.toString(entity,"utf-8"));
        } catch (ClientProtocolException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    //测试
    public static void main(String[] args) {
        //new GetClient().doGetTestOne();
        //new GetClient().doGetTestWayOne();
        new GetClient().doGetTestWayTwo();
    }
}

POST请求

public class PostClient {

    /**
     * POST 无参
     */
    public void doPostTestOne(){
        //获得http客户端
        CloseableHttpClient client = HttpClientBuilder.create().build();
        //创建Post请求
        HttpPost httpPost = new HttpPost("https://www.cuit.edu.cn/index.htm");
        //创建响应模型
        CloseableHttpResponse response = null;
        try{
            response = client.execute(httpPost);
            HttpEntity entity = response.getEntity();
            System.out.println("响应状态码:"+response.getStatusLine());
            System.out.println("响应内容长度:"+entity.getContentLength());
            System.out.println("响应内容:"+ EntityUtils.toString(entity,"utf-8"));
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            try{
                if (client!=null){
                    client.close();
                }
                if (response!=null){
                    response.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }

    /**
     * POST 有参
     */
    public void doPostTestFour(){
        //获的http客户端
        CloseableHttpClient client = HttpClientBuilder.create().build();

        //参数
        StringBuilder params = new StringBuilder();
        try{
            //字符数据最好encoding; 这样一来, 某些特殊字符才嗯那个传过去(如:某人的名字就是"&",不encoding,传不过去)
            params.append("phone=").append(URLEncoder.encode("admin","utf-8"));
            params.append("&");
            params.append("password=admin");

        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }

        //创建post请求
        HttpPost httpPost = new HttpPost("https://www.cuit.edu.cn/?" + params);

        //设置ContentType(注:如果只是传入普通参数的话,ContentType不一定非要用application/json)
        httpPost.setHeader("Content-Type","application/json;charset=utf-8");
        //响应模型
        CloseableHttpResponse response = null;
        try{
            response = client.execute(httpPost);
            HttpEntity entity = response.getEntity();
            System.out.println("状态码:"+response.getStatusLine());
            System.out.println("响应内容长度: "+entity.getContentLength());
            System.out.println("响应内容: "+entity);

        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * POST---有参测试(对象参数)
     */
    public void doPostTestTwo(){
        //获取Http客户端
        CloseableHttpClient client = HttpClientBuilder.create().build();

        //创建Post请求
        HttpPost httpPost = new HttpPost("https://www.cuit.edu.cn/index.htm");
        //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);
        String jsonString = "";
        StringEntity stringEntity = new StringEntity(jsonString, "utf-8");
        httpPost.setEntity(stringEntity);
        httpPost.setHeader("Content-Type", "application/json;charset=utf8");
        CloseableHttpResponse response = null;
        try{
            response = client.execute(httpPost);
            HttpEntity entity = response.getEntity();
            System.out.println("状态码:"+response.getStatusLine());
            System.out.println("响应内容长度:"+entity.getContentLength());
            System.out.println("响应内容:"+EntityUtils.toString(entity,"utf-8"));
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try{
                if (client!=null){
                    client.close();
                }
                if (response!=null){
                    response.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }
    public static void main(String[] args) {
        //new PostClient().doPostTestOne();
        //new PostClient().doPostTestFour();
        new PostClient().doPostTestTwo();
    }
}

上传文件

public class FileClient {
    /**
     * 发送文件
     注:如果想要灵活方便的传输文件的话,
     *    除了引入org.apache.httpcomponents基本的httpclient依赖外
     *    再额外引入org.apache.httpcomponents的httpmime依赖。
     *    追注:即便不引入httpmime依赖,也是能传输文件的,不过功能不够强大。
     */
    public void test4(){

        CloseableHttpClient client = HttpClientBuilder.create().build();
        HttpPost httpPost = new HttpPost("https://www.cuit.edu.cn/file");

        CloseableHttpResponse response = null;
        try{
            MultipartEntityBuilder multipartEntityBuilder = MultipartEntityBuilder.create();
            //第一个文件
            String fileKey = "files";
            File file1 = new File("D:\\图片\\《Valorant》3440x1440带鱼屏游戏壁纸_彼岸图网.jpg");
            /*
            防止服务端收到的文件名乱码. 我们这里可以先将文件名URLEncode, 然后服务端拿到文件后URLDecode
            文件名其实是放在请求头的Content-Disposition中 如其值form-data; name="files"; filename="头像.jpg"
             */
            multipartEntityBuilder.addBinaryBody(fileKey,file1, ContentType.DEFAULT_BINARY, URLEncoder.encode(file1.getName(),"utf-8"));

            //其他参数(注:自定义contentType,设置UTF-8是为了防止服务端拿到的参数出现乱码)
            ContentType contentType = ContentType.create("text/plain", StandardCharsets.UTF_8);
            multipartEntityBuilder.addTextBody("name","等沙利文",contentType);
            multipartEntityBuilder.addTextBody("age","25",contentType);

            HttpEntity httpEntity = multipartEntityBuilder.build();
            httpPost.setEntity(httpEntity);
            response = client.execute(httpPost);
            HttpEntity entity = response.getEntity();
            if (entity!=null){
                System.out.println("状态码:"+response.getStatusLine());
                System.out.println("响应内容长度:"+entity.getContentLength());
                System.out.println("响应内容:"+ EntityUtils.toString(entity,"utf-8"));
            }
            /*
            File file1 = new File("D:\\图片\\XXX.jpg");
            multipartEntityBuilder.addBinaryBody(fileKey,file1);
             */

        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (client!=null){
                    client.close();
                }
                if (response!=null){
                    response.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    public static void main(String[] args) {
        new FileClient().test4();
    }
}

Stream请求

public class StreamClient {
    /**
     * 发送流
     */
    public void test5(){
        CloseableHttpClient client = HttpClientBuilder.create().build();
        HttpPost httpPost = new HttpPost("https://www.cuit.edu.cn/index.htm");
        CloseableHttpResponse response = null;
        try {
            ByteArrayInputStream is = new ByteArrayInputStream("流啊流~".getBytes(StandardCharsets.UTF_8));
            InputStreamEntity ise = new InputStreamEntity(is);
            httpPost.setEntity(ise);

            response = client.execute(httpPost);
            HttpEntity entity = response.getEntity();
            System.out.println("响应状态码:"+response.getStatusLine());
            if (entity!=null){
                System.out.println("响应内容长度:"+entity.getContentLength());
                System.out.println("响应内容:"+ EntityUtils.toString(entity,StandardCharsets.UTF_8));
            }
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            try {
                if (client!=null){
                    client.close();
                }
                if (response!=null){
                    response.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    public static void main(String[] args) {
        new StreamClient().test5();
    }
}

-END-

你可能感兴趣的:(java,后端,apache)