美文网首页
HttpClient系列-Post使用基础知识(三)

HttpClient系列-Post使用基础知识(三)

作者: 油腻的Java | 来源:发表于2019-06-24 17:45 被阅读0次

    简述

    本文学习如何简单的使用POST,如何上传文件等等场景

    基础POST

    首先,让我们来看一个简单的例子,并使用HttpClient发送POST请求。

    我们将使用两个参数 - “username”和“password” 进行POST :

    @Test
    public void test() 
      throws ClientProtocolException, IOException {
        CloseableHttpClient client = HttpClients.createDefault();
    
        List<NameValuePair> params = new ArrayList<NameValuePair>();
        params.add(new BasicNameValuePair("username", "John"));
        params.add(new BasicNameValuePair("password", "pass"));
        httpPost.setEntity(new UrlEncodedFormEntity(params));
     
        HttpPost httpPost = new HttpPost("http://localhost:8080");
    
        CloseableHttpResponse response = client.execute(httpPost);
        assertThat(response.getStatusLine().getStatusCode(), equalTo(200));
        client.close();
    }
    

    请注意我们如何使用List<NameValuePair>在POST请求中包含参数。

    使用授权进行POST

    接下来,让我们看看如何使用HttpClient对身份验证凭据进行POST 。

    在以下示例中 - 我们通过添加Authorization在Header向使用基本身份验证保护的URL发送POST请求:

    @Test
    public void test()
      throws ClientProtocolException, IOException, AuthenticationException {
        CloseableHttpClient client = HttpClients.createDefault();
    
        HttpPost httpPost = new HttpPost("http://localhost:8080");
    
    
       httpPost.setEntity(new StringEntity("test post"));
        UsernamePasswordCredentials creds
          = new UsernamePasswordCredentials("John", "pass");
        httpPost.addHeader(new BasicScheme().authenticate(creds, httpPost, null));
     
        CloseableHttpResponse response = client.execute(httpPost);
        assertThat(response.getStatusLine().getStatusCode(), equalTo(200));
        client.close();
    }
    

    使用JSON POST

    现在 - 让我们看看如何使用HttpClient向JSON主体发送POST请求。

    在以下示例中 - 我们将一些Person(id,name)作为JSON发送:

    @Test
    public void test() 
      throws ClientProtocolException, IOException {
        CloseableHttpClient client = HttpClients.createDefault();
    
        HttpPost httpPost = new HttpPost("http://localhost:8080");
    
        String json = "{"id":1,"name":"John"}";
        StringEntity entity = new StringEntity(json);
        httpPost.setEntity(entity);
        httpPost.setHeader("Accept", "application/json");
        httpPost.setHeader("Content-type", "application/json");
     
        CloseableHttpResponse response = client.execute(httpPost);
        assertThat(response.getStatusLine().getStatusCode(), equalTo(200));
        client.close();
    }
    

    注意我们如何使用StringEntity来设置请求的主体。

    我们还将ContentType标头设置为application / json ,以便为服务器提供有关我们发送的内容表示的必要信息。

    使用HttpClient Form进行 POST

    接下来,让我们使用HttpClient Fluent API进行POST 。

    我们将发送一个带有两个参数“ username ”和“ password ” 的请求:

    @Test
    public void test() 
      throws ClientProtocolException, IOException {
        HttpResponse response = Request.Post("http://localhost:8080").bodyForm(
          Form.form().add("username", "John").add("password", "pass").build())
          .execute().returnResponse();
     
        assertThat(response.getStatusLine().getStatusCode(), equalTo(200));
    }
    

    POST多参数请求

    现在,让我们发一个多参数请求。

    我们将使用MultipartEntityBuilder发布文件,useranme和password:

    @Test
    public void whenSendMultipartRequestUsingHttpClient_thenCorrect() 
      throws ClientProtocolException, IOException {
        CloseableHttpClient client = HttpClients.createDefault();
    
        HttpPost httpPost = new HttpPost("http://localhost:8080");
    
        MultipartEntityBuilder builder = MultipartEntityBuilder.create();
        builder.addTextBody("username", "John");
        builder.addTextBody("password", "pass");
        builder.addBinaryBody("file", new File("test.txt"), ContentType.APPLICATION_OCTET_STREAM, "file.ext");
     
        HttpEntity multipart = builder.build();
        httpPost.setEntity(multipart);
     
        CloseableHttpResponse response = client.execute(httpPost);
        assertThat(response.getStatusLine().getStatusCode(), equalTo(200));
        client.close();
    }
    
    

    使用HttpClient上传文件

    接下来,让我们看看如何使用HttpClient上传文件。

    我们将使用MultipartEntityBuilder上传“ test.txt ”文件:

    @Test
    public void test() throws ClientProtocolException, IOException {
        CloseableHttpClient client = HttpClients.createDefault();
    
        HttpPost httpPost = new HttpPost("http://localhost:8080");
    
        MultipartEntityBuilder builder = MultipartEntityBuilder.create();
        builder.addBinaryBody("file", new File("test.txt"), ContentType.APPLICATION_OCTET_STREAM, "file.ext");
        HttpEntity multipart = builder.build();
        httpPost.setEntity(multipart);
     
        CloseableHttpResponse response = client.execute(httpPost);
        assertThat(response.getStatusLine().getStatusCode(), equalTo(200));
        client.close();
    }
    

    获取文件上传 进度

    最后 - 让我们看看如何使用HttpClient获取文件上传的进度。

    在下面的示例中,我们将扩展HttpEntityWrapper以获得对上载过程的可见性。

    首先 - 这是上传方法:

    @Test
    public void test()
      throws ClientProtocolException, IOException {
        CloseableHttpClient client = HttpClients.createDefault();
    
        HttpPost httpPost = new HttpPost("http://localhost:8080");
    
        MultipartEntityBuilder builder = MultipartEntityBuilder.create();
        builder.addBinaryBody("file", new File("test.txt"), ContentType.APPLICATION_OCTET_STREAM, "file.ext");
        HttpEntity multipart = builder.build();
     
        ProgressEntityWrapper.ProgressListener pListener = 
          percentage -> assertFalse(Float.compare(percentage, 100) > 0);
        httpPost.setEntity(new ProgressEntityWrapper(multipart, pListener));
     
        CloseableHttpResponse response = client.execute(httpPost);
        assertThat(response.getStatusLine().getStatusCode(), equalTo(200));
        client.close();
    }
    

    我们还将添加接口ProgressListener,使我们能够观察上传进度:

    public static interface ProgressListener {
        void progress(float percentage);
    }
    

    这是我们的扩展版HttpEntityWrapper的ProgressEntityWrapper

    public class ProgressEntityWrapper extends HttpEntityWrapper {
        private ProgressListener listener;
     
        public ProgressEntityWrapper(HttpEntity entity, ProgressListener listener) {
            super(entity);
            this.listener = listener;
        }
     
        @Override
        public void writeTo(OutputStream outstream) throws IOException {
            super.writeTo(new CountingOutputStream(outstream, listener, getContentLength()));
        }
    }
    

    而FilterOutputStream的扩展版CountingOutputStream

    public static class CountingOutputStream extends FilterOutputStream {
        private ProgressListener listener;
        private long transferred;
        private long totalBytes;
     
        public CountingOutputStream(
          OutputStream out, ProgressListener listener, long totalBytes) {
            super(out);
            this.listener = listener;
            transferred = 0;
            this.totalBytes = totalBytes;
        }
     
        @Override
        public void write(byte[] b, int off, int len) throws IOException {
            out.write(b, off, len);
            transferred += len;
            listener.progress(getCurrentProgress());
        }
     
        @Override
        public void write(int b) throws IOException {
            out.write(b);
            transferred++;
            listener.progress(getCurrentProgress());
        }
     
        private float getCurrentProgress() {
            return ((float) transferred / totalBytes) * 100;
        }
    }
    

    注意:

    • 将FilterOutputStream扩展为CountingOutputStream时 -我们重写write()方法来计算写入(传输)的字节数
    • 将HttpEntityWrapper扩展为ProgressEntityWrapper时 -我们重写writeTo()方法以使用我们的CountingOutputStream

    小结

    HttpClient的基础知识到本文就已经介绍结束,希望对你有所收获。

    相关文章

      网友评论

          本文标题:HttpClient系列-Post使用基础知识(三)

          本文链接:https://www.haomeiwen.com/subject/jjgoqctx.html