HTTP 클 라 이언 트 연결, HttpClient 를 선택 하 시 겠 습 니까? OkHttp 를 선택 하 시 겠 습 니까?

12189 단어 자바
앞 에 쓰다
왜 이 글 을 썼 는 지 는 친구 와 의 대화 HTTP客户端连接,选择HttpClient还是OkHttp?_第1张图片 에서 비롯 되 었 기 때문에 사용, 성능, 시간 초과 설정 에 대해 비교 합 니 다.
쓰다
HttpClient 와 OkHttp 는 일반적으로 다른 서 비 스 를 호출 하 는 데 사 용 됩 니 다. 일반 서비스 에 노출 된 인 터 페 이 스 는 http 이 고 http 에서 자주 사용 하 는 요청 유형 은 GET, PUT, POST 와 DELETE 이기 때문에 이러한 요청 유형의 호출 을 소개 합 니 다.
HttpClient 사용 안내
HttpClient 를 사용 하여 요청 을 보 내 는 것 은 주로 몇 단계 로 나 눌 수 있 습 니 다.
  • CloseableHttpClient 대상 또는 CloseableHttpAsyncClient 대상 을 만 들 고 전자 동기 화, 후 자 는 비동기
  • Http 요청 대상 생 성
  • execute 방법 으로 요청 을 수행 합 니 다. 비동기 요청 이 실행 되 기 전에 start 방법
  • 을 호출 해 야 합 니 다.
    연결 만 들 기:
    CloseableHttpClient httpClient = HttpClientBuilder.create().build();

    동기 화 연결
    GET 요청:
    @Test
    public void testGet() throws IOException {
        String api = "/api/files/1";
        String url = String.format("%s%s", BASE_URL, api);
        HttpGet httpGet = new HttpGet(url);
        CloseableHttpResponse response = httpClient.execute(httpGet);
        System.out.println(EntityUtils.toString(response.getEntity()));
    }

    HttpGet 을 사용 하여 이 연결 을 GET 요청 으로 표시 하고 HttpClient 에서 execute 방법 으로 GET 요청 을 보 냅 니 다.
    PUT 요청:
    @Test
    public void testPut() throws IOException {
        String api = "/api/user";
        String url = String.format("%s%s", BASE_URL, api);
        HttpPut httpPut = new HttpPut(url);
        UserVO userVO = UserVO.builder().name("h2t").id(16L).build();
        httpPut.setHeader("Content-Type", "application/json;charset=utf8");
        httpPut.setEntity(new StringEntity(JSONObject.toJSONString(userVO), "UTF-8"));
        CloseableHttpResponse response = httpClient.execute(httpPut);
        System.out.println(EntityUtils.toString(response.getEntity()));
    }

    POST 요청:
  • 대상 추가
    @Test
    public void testPost() throws IOException {
        String api = "/api/user";
        String url = String.format("%s%s", BASE_URL, api);
        HttpPost httpPost = new HttpPost(url);
        UserVO userVO = UserVO.builder().name("h2t2").build();
        httpPost.setHeader("Content-Type", "application/json;charset=utf8");
        httpPost.setEntity(new StringEntity(JSONObject.toJSONString(userVO), "UTF-8"));
        CloseableHttpResponse response = httpClient.execute(httpPost);
        System.out.println(EntityUtils.toString(response.getEntity()));
    }
    이 요청 은 생 성 대상 의 요청 입 니 다. json 문자열
  • 을 입력 해 야 합 니 다.
  • 파일 업로드
    @Test
    public void testUpload1() throws IOException {
        String api = "/api/files/1";
        String url = String.format("%s%s", BASE_URL, api);
        HttpPost httpPost = new HttpPost(url);
        File file = new File("C:/Users/hetiantian/Desktop/  /docker_practice.pdf");
        FileBody fileBody = new FileBody(file);
        MultipartEntityBuilder builder = MultipartEntityBuilder.create();
        builder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
        builder.addPart("file", fileBody);  //addPart    
        HttpEntity entity = builder.build();
        httpPost.setEntity(entity);
        CloseableHttpResponse response = httpClient.execute(httpPost);
        System.out.println(EntityUtils.toString(response.getEntity()));
    }
    addPart 를 통 해 파일 업로드
  • DELETE 요청:
    @Test
    public void testDelete() throws IOException {
        String api = "/api/user/12";
        String url = String.format("%s%s", BASE_URL, api);
        HttpDelete httpDelete = new HttpDelete(url);
        CloseableHttpResponse response = httpClient.execute(httpDelete);
        System.out.println(EntityUtils.toString(response.getEntity()));
    }

    요청 한 취소:
    @Test
    public void testCancel() throws IOException {
        String api = "/api/files/1";
        String url = String.format("%s%s", BASE_URL, api);
        HttpGet httpGet = new HttpGet(url);
        httpGet.setConfig(requestConfig);  //      
        //       
    
        long begin = System.currentTimeMillis();
        CloseableHttpResponse response = httpClient.execute(httpGet);
        while (true) {
            if (System.currentTimeMillis() - begin > 1000) {
              httpGet.abort();
              System.out.println("task canceled");
              break;
          }
        }
    
        System.out.println(EntityUtils.toString(response.getEntity()));
    }

    abort 방법 으로 요청 실행 취소 결과:
    task canceled
    cost 8098 msc
    Disconnected from the target VM, address: '127.0.0.1:60549', transport: 'socket'
    
    java.net.SocketException: socket closed...【  】

    OkHttp 사용
    OkHttp 를 사용 하여 요청 을 보 내 는 것 은 주로 몇 단계 로 나 뉜 다.
  • OkHttpClient 대상 만 들 기
  • 요청 대상 생 성
  • 요청 대상 을 Call
  • 로 봉인
  • 콜 을 통 해 동기 화 또는 비동기 요청 을 실행 하고 execute 방법 으로 동기 화 를 실행 하 며 enqueue 방법 으로 비동기 화 를 실행 합 니 다
  • 연결 만 들 기:
    private OkHttpClient client = new OkHttpClient();

    GET 요청:
    @Test
    public void testGet() throws IOException {
        String api = "/api/files/1";
        String url = String.format("%s%s", BASE_URL, api);
        Request request = new Request.Builder()
                .url(url)
                .get() 
                .build();
        final Call call = client.newCall(request);
        Response response = call.execute();
        System.out.println(response.body().string());
    }

    PUT 요청:
    @Test
    public void testPut() throws IOException {
        String api = "/api/user";
        String url = String.format("%s%s", BASE_URL, api);
        //    
        UserVO userVO = UserVO.builder().name("h2t").id(11L).build();
        RequestBody requestBody = RequestBody.create(MediaType.parse("application/json; charset=utf-8"),
        JSONObject.toJSONString(userVO));
        Request request = new Request.Builder()
                .url(url)
                .put(requestBody)
                .build();
        final Call call = client.newCall(request);
        Response response = call.execute();
        System.out.println(response.body().string());
    }

    POST 요청:
  • 대상 추가
    @Test
    public void testPost() throws IOException {
        String api = "/api/user";
        String url = String.format("%s%s", BASE_URL, api);
        //    
        JSONObject json = new JSONObject();
        json.put("name", "hetiantian");
        RequestBody requestBody = RequestBody.create(MediaType.parse("application/json; charset=utf-8"),     String.valueOf(json));
        Request request = new Request.Builder()
                .url(url)
                .post(requestBody) //post  
               .build();
        final Call call = client.newCall(request);
        Response response = call.execute();
        System.out.println(response.body().string());
    }
  • 파일 업로드
    @Test
    public void testUpload() throws IOException {
        String api = "/api/files/1";
        String url = String.format("%s%s", BASE_URL, api);
        RequestBody requestBody = new MultipartBody.Builder()
                .setType(MultipartBody.FORM)
                .addFormDataPart("file", "docker_practice.pdf",
                        RequestBody.create(MediaType.parse("multipart/form-data"),
                                new File("C:/Users/hetiantian/Desktop/  /docker_practice.pdf")))
                .build();
        Request request = new Request.Builder()
                .url(url)
                .post(requestBody)  //   GET  ,    
                .build();
        final Call call = client.newCall(request);
        Response response = call.execute();
        System.out.println(response.body().string());
    }
    addFormDataPart 방법 으로 폼 을 모 의 해서 파일 업로드
  • DELETE 요청:
    @Test
    public void testDelete() throws IOException {
      String url = String.format("%s%s", BASE_URL, api);
      //    
      Request request = new Request.Builder()
              .url(url)
              .delete()
              .build();
      final Call call = client.newCall(request);
      Response response = call.execute();
      System.out.println(response.body().string());
    }

    요청 한 취소:
    @Test
    public void testCancelSysnc() throws IOException {
        String api = "/api/files/1";
        String url = String.format("%s%s", BASE_URL, api);
        Request request = new Request.Builder()
                .url(url)
                .get()  
                .build();
        final Call call = client.newCall(request);
        Response response = call.execute();
        long start = System.currentTimeMillis();
        //       
        while (true) {
             //1             
            if (System.currentTimeMillis() - start > 1000) {
                call.cancel();
                System.out.println("task canceled");
                break;
            }
        }
    
        System.out.println(response.body().string());
    }

    cancel 방법 으로 테스트 결 과 를 취소 합 니 다:
    task canceled
    cost 9110 msc
    
    java.net.SocketException: socket closed...【  】

    작은 매듭
  • OkHttp 는 build 모드 로 대상 을 좀 더 간결 하 게 만 들 고. post /. delete /. pt /. get 방법 으로 요청 형식 을 표시 합 니 다. HttpClient 처럼 HttpGet, HttpPost 등 방법 으로 요청 형식 을 만 들 필요 가 없습니다
  • 의존 패키지 에서 HttpClient 가 비동기 요청 을 보 내 고 파일 업 로드 를 실현 하려 면 비동기 요청 의존
     
     
         org.apache.httpcomponents
         httpmime
         4.5.3
     
     
     
         org.apache.httpcomponents
         httpasyncclient
         4.5.3
     
  • 을 추가 로 도입 해 야 합 니 다.
  • 요청 의 취소, HttpClient 는 abort 방법, OkHttp 는 cancel 방법 을 사용 합 니 다. 모두 간단 합 니 다. 비동기 client 를 사용 하면 이상 을 던 질 때 요청 을 취소 하 는 방법 을 호출 하면 됩 니 다
  • 시간 초과 설정
    HttpClient 시간 초과 설정: HttpClient 4.3 + 버 전 이상 에서 시간 초과 설정 은 RequestConfig 를 통 해 설정 합 니 다.
    private CloseableHttpClient httpClient = HttpClientBuilder.create().build();
    private RequestConfig requestConfig =  RequestConfig.custom()
            .setSocketTimeout(60 * 1000)
            .setConnectTimeout(60 * 1000).build();
    String api = "/api/files/1";
    String url = String.format("%s%s", BASE_URL, api);
    HttpGet httpGet = new HttpGet(url);
    httpGet.setConfig(requestConfig);  //      

    시간 초 과 는 HttpClient 대신 요청 형식 HttpGet 에 설 정 됩 니 다.
    OkHttp 시간 초과 설정: OkHttp 에서 직접 설정
    private OkHttpClient client = new OkHttpClient.Builder()
            .connectTimeout(60, TimeUnit.SECONDS)//        
            .readTimeout(60, TimeUnit.SECONDS)//        
            .build();

    소결: client 가 단일 모드 라면 HttpClient 는 시간 초과 설정 을 더욱 유연 하 게 할 수 있 습 니 다. 요청 유형 에 따라 시간 초과 설정 을 할 수 있 습 니 다. OkHttp 는 시간 초과 설정 을 하면 모든 요청 유형의 시간 초과 도 확 정 됩 니 다.
    HttpClient 와 OkHttp 성능 비교
    테스트 환경:
  • CPU 6 핵
  • 메모리 8G
  • windows10

  • 모든 테스트 용례 는 다섯 번 테스트 하여 우연성 을 배제한다
    client 연결 은 단일 예: HTTP客户端连接,选择HttpClient还是OkHttp?_第2张图片 단일 예 모드 에서 HttpClient 의 응답 속도 가 더 빨 라 야 합 니 다. 단 위 는 밀리초 이 고 성능 차이 가 크 지 않 습 니 다. 단일 예 모드 에서 OkHttp 의 성능 이 더 좋 습 니 다. HttpClient 가 연결 을 만 드 는 데 시간 이 걸 립 니 다. 대부분의 경우 이 자원 들 이 단일 예 모드 로 작성 되 기 때문에 그림 1 의 테스트 결 과 는 더욱 참고 가치 가 있 습 니 다.
    총결산
    OkHttp 와 HttpClient 는 성능 과 사용 에 있어 서 우열 을 가리 지 않 고 실제 업무 선택 에 따라 마지막 으로 첨부 할 수 있 습 니 다. 예제 코드 fork 와 star * 는 오랫동안 대외 수출 글 을 하지 않 았 습 니 다 HTTP客户端连接,选择HttpClient还是OkHttp?_第3张图片

    좋은 웹페이지 즐겨찾기