浅谈HttpClient、okhttp和RestTemplate的区别

一、HttpClient1、pom依赖

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

2、HttpClient代码实现

public class HttpClientUtil {    /**     * httpClient的get请求方式     * 使用GetMethod来访问一个URL对应的网页实现步骤:     * 1.生成一个HttpClient对象并设置相应的参数;     * 2.生成一个GetMethod对象并设置响应的参数;     * 3.用HttpClient生成的对象来执行GetMethod生成的Get方法;     * 4.处理响应状态码;     * 5.若响应正常,处理HTTP响应内容;     * 6.释放连接。     * @param url     * @param charset     * @return     */    public static String doGet(String url, String charset) {        //1.生成HttpClient对象并设置参数        HttpClient httpClient = new HttpClient();        //设置Http连接超时为5秒        httpClient.getHttpConnectionManager().getParams().setConnectionTimeout(5000);        //2.生成GetMethod对象并设置参数        GetMethod getMethod = new GetMethod(url);        //设置get请求超时为5秒        getMethod.getParams().setParameter(HttpMethodParams.SO_TIMEOUT, 5000);        //设置请求重试处理,用的是默认的重试处理:请求三次        getMethod.getParams().setParameter(HttpMethodParams.RETRY_HANDLER, new DefaultHttpMethodRetryHandler());        String response = "";        //3.执行HTTP GET 请求        try {            int statusCode = httpClient.executeMethod(getMethod);            //4.判断访问的状态码            if (statusCode != HttpStatus.SC_OK) {                System.err.println("请求出错:" + getMethod.getStatusLine());            }            //5.处理HTTP响应内容            //HTTP响应头部信息,这里简单打印            Header[] headers = getMethod.getResponseHeaders();            for(Header h : headers) {                System.out.println(h.getName() + "---------------" + h.getValue());            }            //读取HTTP响应内容,这里简单打印网页内容            //读取为字节数组            byte[] responseBody = getMethod.getResponseBody();            response = new String(responseBody, charset);            System.out.println("-----------response:" + response);            //读取为InputStream,在网页内容数据量大时候推荐使用            //InputStream response = getMethod.getResponseBodyAsStream();        } catch (HttpException e) {            //发生致命的异常,可能是协议不对或者返回的内容有问题            System.out.println("请检查输入的URL!");            e.printStackTrace();        } catch (IOException e) {            //发生网络异常            System.out.println("发生网络异常!");        } finally {            //6.释放连接            getMethod.releaseConnection();        }        return response;    }    /**     * post请求     * @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");        //设置json格式传送        postMethod.addRequestHeader("Content-Type", "application/json;charset=GBK");        //必须设置下面这个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");        //添加请求参数        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、建议

代码复杂,还得操心资源回收等。代码很复杂,冗余代码多,不建议直接使用。

二、okhttp1、简介

OkHttp是一个高效的HTTP客户端,允许所有同一个主机地址的请求共享同一个socket连接;连接池减少请求延时;透明的GZIP压缩减少响应数据的大小;缓存响应内容,避免一些完全重复的请求

当网络出现问题的时候OkHttp依然坚守自己的职责,它会自动恢复一般的连接问题,如果你的服务有多个IP地址,当第一个IP请求失败时,OkHttp会交替尝试你配置的其他IP,OkHttp使用现代TLS技术(SNI, ALPN)初始化新的连接,当握手失败时会回退到TLS 1.0。

2、pom依赖

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

它的请求/响应 API 使用构造器模式builders来设计,它支持阻塞式的同步请求和带回调的异步请求。

3、配置文件

@Configurationpublic 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、客户端工具

@Slf4jpublic 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. "));    /**     * 单例模式(双重检查模式) 获取类实例      *     * @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状态码为" + 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状态码为" + response.code());            }            return result;        } catch (Exception e) {            log.error("remote interface url:{} have a ecxeption {}", url, e);            throw new RuntimeException("三方接口返回异常");        }    }}

三、RestTemplate1、pom依赖

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

2、get请求(不带参的即把参数取消即可)

// 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请求

// 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);

方式二:

@Testpublic 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发送请求,当请求体是String时,应这样配置:

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

如果没有自定义StringHttpMessageConverter,默认的StringHttpMessageConverter使用的字符集是ISO_8859_1,当请求体包含中文时,会乱码。

以上为个人经验,希望能给大家一个参考,也希望大家多多支持。

心中有愿望一定要去闯,努力实现最初的梦想,

浅谈HttpClient、okhttp和RestTemplate的区别

相关文章:

你感兴趣的文章:

标签云: