HttpClient系列-Post使用基礎知識(三)

簡述

本文學習如何簡單的使用POST,如何上傳文件等等場景json

基礎POST

首先,讓咱們來看一個簡單的例子,並使用HttpClient發送POST請求。bash

咱們將使用兩個參數 - 「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在POST請求中包含參數。app

使用受權進行POST

接下來,讓咱們看看如何使用HttpClient對身份驗證憑據進行POST 。ide

在如下示例中 - 咱們經過添加Authorization在Header向使用基自己份驗證保護的URL發送POST請求: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發送:ui

@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來設置請求的主體。this

咱們還將ContentType標頭設置爲application / json ,以便爲服務器提供有關咱們發送的內容表示的必要信息。spa

使用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的基礎知識到本文就已經介紹結束,但願對你有所收穫。

相關文章
相關標籤/搜索