溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

HttpClient、okhttp和RestTemplate的區(qū)別是什么

發(fā)布時(shí)間:2021-06-21 10:43:47 來(lái)源:億速云 閱讀:593 作者:小新 欄目:開(kāi)發(fā)技術(shù)

這篇文章主要介紹HttpClient、okhttp和RestTemplate的區(qū)別是什么,文中介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們一定要看完!

一、HttpClient

1、pom依賴

<!--HttpClient-->
<dependency>
    <groupId>commons-httpclient</groupId>
    <artifactId>commons-httpclient</artifactId>
    <version>3.1</version>
</dependency>

2、HttpClient代碼實(shí)現(xiàn)

public class HttpClientUtil {
    /**
     * httpClient的get請(qǐng)求方式
     * 使用GetMethod來(lái)訪問(wèn)一個(gè)URL對(duì)應(yīng)的網(wǎng)頁(yè)實(shí)現(xiàn)步驟:
     * 1.生成一個(gè)HttpClient對(duì)象并設(shè)置相應(yīng)的參數(shù);
     * 2.生成一個(gè)GetMethod對(duì)象并設(shè)置響應(yīng)的參數(shù);
     * 3.用HttpClient生成的對(duì)象來(lái)執(zhí)行GetMethod生成的Get方法;
     * 4.處理響應(yīng)狀態(tài)碼;
     * 5.若響應(yīng)正常,處理HTTP響應(yīng)內(nèi)容;
     * 6.釋放連接。
     * @param url
     * @param charset
     * @return
     */
    public static String doGet(String url, String charset) {
        //1.生成HttpClient對(duì)象并設(shè)置參數(shù)
        HttpClient httpClient = new HttpClient();
        //設(shè)置Http連接超時(shí)為5秒
        httpClient.getHttpConnectionManager().getParams().setConnectionTimeout(5000);
        //2.生成GetMethod對(duì)象并設(shè)置參數(shù)
        GetMethod getMethod = new GetMethod(url);
        //設(shè)置get請(qǐng)求超時(shí)為5秒
        getMethod.getParams().setParameter(HttpMethodParams.SO_TIMEOUT, 5000);
        //設(shè)置請(qǐng)求重試處理,用的是默認(rèn)的重試處理:請(qǐng)求三次
        getMethod.getParams().setParameter(HttpMethodParams.RETRY_HANDLER, new DefaultHttpMethodRetryHandler());
        String response = "";
        //3.執(zhí)行HTTP GET 請(qǐng)求
        try {
            int statusCode = httpClient.executeMethod(getMethod);
            //4.判斷訪問(wèn)的狀態(tài)碼
            if (statusCode != HttpStatus.SC_OK) {
                System.err.println("請(qǐng)求出錯(cuò):" + getMethod.getStatusLine());
            }
            //5.處理HTTP響應(yīng)內(nèi)容
            //HTTP響應(yīng)頭部信息,這里簡(jiǎn)單打印
            Header[] headers = getMethod.getResponseHeaders();
            for(Header h : headers) {
                System.out.println(h.getName() + "---------------" + h.getValue());
            }
            //讀取HTTP響應(yīng)內(nèi)容,這里簡(jiǎn)單打印網(wǎng)頁(yè)內(nèi)容
            //讀取為字節(jié)數(shù)組
            byte[] responseBody = getMethod.getResponseBody();
            response = new String(responseBody, charset);
            System.out.println("-----------response:" + response);
            //讀取為InputStream,在網(wǎng)頁(yè)內(nèi)容數(shù)據(jù)量大時(shí)候推薦使用
            //InputStream response = getMethod.getResponseBodyAsStream();
        } catch (HttpException e) {
            //發(fā)生致命的異常,可能是協(xié)議不對(duì)或者返回的內(nèi)容有問(wèn)題
            System.out.println("請(qǐng)檢查輸入的URL!");
            e.printStackTrace();
        } catch (IOException e) {
            //發(fā)生網(wǎng)絡(luò)異常
            System.out.println("發(fā)生網(wǎng)絡(luò)異常!");
        } finally {
            //6.釋放連接
            getMethod.releaseConnection();
        }
        return response;
    }
    /**
     * post請(qǐng)求
     * @param url
     * @param json
     * @return
     */
    public static String doPost(String url, JSONObject json){
        HttpClient httpClient = new HttpClient();
        PostMethod postMethod = new PostMethod(url);
        postMethod.addRequestHeader("accept", "*/*");
        postMethod.addRequestHeader("connection", "Keep-Alive");
        //設(shè)置json格式傳送
        postMethod.addRequestHeader("Content-Type", "application/json;charset=GBK");
        //必須設(shè)置下面這個(gè)Header
        postMethod.addRequestHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.81 Safari/537.36");
        //添加請(qǐng)求參數(shù)
        postMethod.addParameter("commentId", json.getString("commentId"));
        String res = "";
        try {
            int code = httpClient.executeMethod(postMethod);
            if (code == 200){
                res = postMethod.getResponseBodyAsString();
                System.out.println(res);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return res;
    }
    public static void main(String[] args) {
        System.out.println(doGet("http://tcc.taobao.com/cc/json/mobile_tel_segment.htm?tel=13026194071", "GBK"));
        System.out.println("-----------分割線------------");
        System.out.println("-----------分割線------------");
        System.out.println("-----------分割線------------");
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("commentId", "13026194071");
        System.out.println(doPost("http://tcc.taobao.com/cc/json/mobile_tel_segment.htm?tel=13026194071", jsonObject));
    }
}

3、建議

代碼復(fù)雜,還得操心資源回收等。代碼很復(fù)雜,冗余代碼多,不建議直接使用。

二、okhttp

1、簡(jiǎn)介

OkHttp是一個(gè)高效的HTTP客戶端,允許所有同一個(gè)主機(jī)地址的請(qǐng)求共享同一個(gè)socket連接;連接池減少請(qǐng)求延時(shí);透明的GZIP壓縮減少響應(yīng)數(shù)據(jù)的大小;緩存響應(yīng)內(nèi)容,避免一些完全重復(fù)的請(qǐng)求

當(dāng)網(wǎng)絡(luò)出現(xiàn)問(wèn)題的時(shí)候OkHttp依然堅(jiān)守自己的職責(zé),它會(huì)自動(dòng)恢復(fù)一般的連接問(wèn)題,如果你的服務(wù)有多個(gè)IP地址,當(dāng)?shù)谝粋€(gè)IP請(qǐng)求失敗時(shí),OkHttp會(huì)交替嘗試你配置的其他IP,OkHttp使用現(xiàn)代TLS技術(shù)(SNI, ALPN)初始化新的連接,當(dāng)握手失敗時(shí)會(huì)回退到TLS 1.0。

2、pom依賴

<dependency>
    <groupId>com.squareup.okhttp3</groupId>
    <artifactId>okhttp</artifactId>
    <version>3.10.0</version>
</dependency>

它的請(qǐng)求/響應(yīng) API 使用構(gòu)造器模式builders來(lái)設(shè)計(jì),它支持阻塞式的同步請(qǐng)求和帶回調(diào)的異步請(qǐng)求。

3、配置文件

@Configuration
public class OkHttpConfig {
    @Bean
    public OkHttpClient okHttpClient() {
        return new OkHttpClient.Builder()
                //.sslSocketFactory(sslSocketFactory(), x509TrustManager())
                .retryOnConnectionFailure(false)
                .connectionPool(pool())
                .connectTimeout(30, TimeUnit.SECONDS)
                .readTimeout(30, TimeUnit.SECONDS)
                .writeTimeout(30,TimeUnit.SECONDS)
                .build();
    }
    @Bean
    public X509TrustManager x509TrustManager() {
        return new X509TrustManager() {
            @Override
            public void checkClientTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {
            }
            @Override
            public void checkServerTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {
            }
            @Override
            public X509Certificate[] getAcceptedIssuers() {
                return new X509Certificate[0];
            }
        };
    }
    @Bean
    public SSLSocketFactory sslSocketFactory() {
        try {
            //信任任何鏈接
            SSLContext sslContext = SSLContext.getInstance("TLS");
            sslContext.init(null, new TrustManager[]{x509TrustManager()}, new SecureRandom());
            return sslContext.getSocketFactory();
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (KeyManagementException e) {
            e.printStackTrace();
        }
        return null;
    }
    /**
     * Create a new connection pool with tuning parameters appropriate for a single-user application.
     * The tuning parameters in this pool are subject to change in future OkHttp releases. Currently
     */
    @Bean
    public ConnectionPool pool() {
        return new ConnectionPool(200, 5, TimeUnit.MINUTES);
    }
}

4、客戶端工具

@Slf4j
public class OkHttpClient {
    private static final MediaType JSON = MediaType.parse("application/json; charset=utf-8");
    private volatile static okhttp3.OkHttpClient client;
    private static final int MAX_IDLE_CONNECTION = Integer
            .parseInt(ConfigManager.get("httpclient.max_idle_connection"));
    private static final long KEEP_ALIVE_DURATION = Long
            .parseLong(ConfigManager.get("httpclient.keep_alive_duration"));
    private static final long CONNECT_TIMEOUT = Long.parseLong(ConfigManager.get("httpclient.connectTimeout"));
    private static final long READ_TIMEOUT = Long.parseLong(ConfigManager.get("httpclient. "));
    /**
     * 單例模式(雙重檢查模式) 獲取類實(shí)例 
     *
     * @return client
     */
    private static okhttp3.OkHttpClient getInstance() {
        if (client == null) {
            synchronized (okhttp3.OkHttpClient.class) {
                if (client == null) {
                    client = new okhttp3.OkHttpClient.Builder()
                            .connectTimeout(CONNECT_TIMEOUT, TimeUnit.SECONDS)
                            .readTimeout(READ_TIMEOUT, TimeUnit.SECONDS)
                            .connectionPool(new ConnectionPool(MAX_IDLE_CONNECTION, KEEP_ALIVE_DURATION,
                                    TimeUnit.MINUTES))
                            .build();
                }
            }
        }
        return client;
    }
    public static String syncPost(String url, String json) throws IOException {
        RequestBody body = RequestBody.create(JSON, json);
        Request request = new Request.Builder()
                .url(url)
                .post(body)
                .build();
        try {
            Response response = OkHttpClient.getInstance().newCall(request).execute();
            if (response.isSuccessful()) {
                String result = response.body().string();
                log.info("syncPost response = {}, responseBody= {}", response, result);
                return result;
            }
            String result = response.body().string();
            log.info("syncPost response = {}, responseBody= {}", response, result);
            throw new IOException("三方接口返回http狀態(tài)碼為" + response.code());
        } catch (Exception e) {
            log.error("syncPost() url:{} have a ecxeption {}", url, e);
            throw new RuntimeException("syncPost() have a ecxeption {}" + e.getMessage());
        }
    }
    public static String syncGet(String url, Map<String, Object> headParamsMap) throws IOException {
        Request request;
        final Request.Builder builder = new Request.Builder().url(url);
        try {
            if (!CollectionUtils.isEmpty(headParamsMap)) {
                final Iterator<Map.Entry<String, Object>> iterator = headParamsMap.entrySet()
                        .iterator();
                while (iterator.hasNext()) {
                    final Map.Entry<String, Object> entry = iterator.next();
                    builder.addHeader(entry.getKey(), (String) entry.getValue());
                }
            }
            request = builder.build();
            Response response = OkHttpClient.getInstance().newCall(request).execute();
            String result = response.body().string();
            log.info("syncGet response = {},responseBody= {}", response, result);
            if (!response.isSuccessful()) {
                throw new IOException("三方接口返回http狀態(tài)碼為" + response.code());
            }
            return result;
        } catch (Exception e) {
            log.error("remote interface url:{} have a ecxeption {}", url, e);
            throw new RuntimeException("三方接口返回異常");
        }
    }
}

三、RestTemplate

1、pom依賴

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

2、get請(qǐng)求(不帶參的即把參數(shù)取消即可)

// 1-getForObject()
User user1 = this.restTemplate.getForObject(uri, User.class);
// 2-getForEntity()
ResponseEntity<User> responseEntity1 = this.restTemplate.getForEntity(uri, User.class);
HttpStatus statusCode = responseEntity1.getStatusCode();
HttpHeaders header = responseEntity1.getHeaders();
User user2 = responseEntity1.getBody();
  
// 3-exchange()
RequestEntity requestEntity = RequestEntity.get(new URI(uri)).build();
ResponseEntity<User> responseEntity2 = this.restTemplate.exchange(requestEntity, User.class);
User user3 = responseEntity2.getBody();

方式一:

Notice notice = restTemplate.getForObject("http://fantj.top/notice/list/{1}/{2}"
                , Notice.class,1,5);

方式二:

Map<String,String> map = new HashMap();
map.put("start","1");
map.put("page","5");
Notice notice = restTemplate.getForObject("http://fantj.top/notice/list/"
        , Notice.class,map);

3、post請(qǐng)求

// 1-postForObject()
User user1 = this.restTemplate.postForObject(uri, user, User.class);
// 2-postForEntity()
ResponseEntity<User> responseEntity1 = this.restTemplate.postForEntity(uri, user, User.class);
// 3-exchange()
RequestEntity<User> requestEntity = RequestEntity.post(new URI(uri)).body(user);
ResponseEntity<User> responseEntity2 = this.restTemplate.exchange(requestEntity, User.class);

方式一:

String url = "http://demo/api/book/";
HttpHeaders headers = new HttpHeaders();
MediaType type = MediaType.parseMediaType("application/json; charset=UTF-8");
headers.setContentType(type);
String requestJson = "{...}";
HttpEntity<String> entity = new HttpEntity<String>(requestJson,headers);
String result = restTemplate.postForObject(url, entity, String.class);
System.out.println(result);

方式二:

@Test
public void rtPostObject(){
    RestTemplate restTemplate = new RestTemplate();
    String url = "http://47.xxx.xxx.96/register/checkEmail";
    HttpHeaders headers = new HttpHeaders();
    headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
    MultiValueMap<String, String> map= new LinkedMultiValueMap<>();
    map.add("email", "844072586@qq.com");
 
    HttpEntity<MultiValueMap<String, String>> request = new HttpEntity<>(map, headers);
    ResponseEntity<String> response = restTemplate.postForEntity( url, request , String.class );
    System.out.println(response.getBody());
}

使用RestTemplate需注意:

使用RestTemplate發(fā)送請(qǐng)求,當(dāng)請(qǐng)求體是String時(shí),應(yīng)這樣配置:

RestTemplate restTemplate = new RestTemplate(factory);
        restTemplate
          .getMessageConverters()
          .set(1, new StringHttpMessageConverter(StandardCharsets.UTF_8));

如果沒(méi)有自定義StringHttpMessageConverter,默認(rèn)的StringHttpMessageConverter使用的字符集是ISO_8859_1,當(dāng)請(qǐng)求體包含中文時(shí),會(huì)亂碼。

以上是“HttpClient、okhttp和RestTemplate的區(qū)別是什么”這篇文章的所有內(nèi)容,感謝各位的閱讀!希望分享的內(nèi)容對(duì)大家有幫助,更多相關(guān)知識(shí),歡迎關(guān)注億速云行業(yè)資訊頻道!

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI