• 浅析几种Java Http请求库的使用:HttpURLConnection、RestTemplate、OKhttp、Feign/OpenFeign


      转载于:https://www.modb.pro/db/69232

      java常见的http请求库有HttpURLConnection、httpclient、RestTemplate、OKhttp,更高层次封装的 feign、retrofit

    一、HttpURLConnection

    HttpURLConnection 是 JDK 自带的标准库;

    【优点】:不需要引入额外的依赖

    【缺点】:缺乏连接池管理、域名机械控制等特性支持,在java9才支持 HTTP/2

    public class HttpUrlConnectionDemo {
        public static void main(String[] args) throws Exception {
            String urlString = "https://httpbin.org/post";
            String bodyString = "password=e10adc3949ba59abbe56e057f20f883e&username=test3";
     
            URL url = new URL(urlString);
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            conn.setRequestMethod("POST");
            conn.setDoOutput(true);
     
            OutputStream os = conn.getOutputStream();
            os.write(bodyString.getBytes("utf-8"));
            os.flush();
            os.close();
     
            if (conn.getResponseCode() == HttpURLConnection.HTTP_OK) {
                InputStream is = conn.getInputStream();
                BufferedReader reader = new BufferedReader(new InputStreamReader(is));
                StringBuilder sb = new StringBuilder();
                String line;
                while ((line = reader.readLine()) != null) {
                    sb.append(line);
                }
                System.out.println("rsp:" + sb.toString());
            } else {
                System.out.println("rsp code:" + conn.getResponseCode());
            }
        }
    }

    二、OkHttp

    【优点】:OkHttp 接口设计友好,支持 HTTP/2,并且在弱网和无网环境下有自动检测和恢复机制,因此,是当前 Android APP 开发中使用最广泛的 HTTP clilent lib 之一。

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

    1、导入依赖

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

    2、简单使用

    import okhttp3.*;
    import org.apache.http.util.CharsetUtils;
    import java.util.HashMap;
    import java.util.Map;
    
    public class OkHttpDemo {
        OkHttpClient client = new OkHttpClient();
     
        private String sendPostForm(String url, final Map&lt;String, String&gt; params) throws Exception {
            FormBody.Builder builder = new FormBody.Builder(CharsetUtils.get("UTF-8"));
            if (params != null) {
                for (Map.Entry&lt;String, String&gt; entry: params.entrySet()) {
                    builder.add(entry.getKey(), entry.getValue());
                }
            }
            RequestBody requestBody = builder.build();
            Request request = new Request.Builder().url(url).post(requestBody).build();
            return client.newCall(request).execute().body().string();
     
        }
     
        private String sendGet(String url) throws Exception {
            Request request = new Request.Builder().url(url).build();
            return  client.newCall(request).execute().body().string();
        }
     
        public static void main(String[] args) throws Exception {
            OkHttpDemo okHttpDemo = new OkHttpDemo();
            String url = "https://httpbin.org/post";
            params = new HashMap();
            params.put("foo", "bar中文");
            // Post请求
            String rsp = okHttpDemo.sendPostForm(url, params);
            System.out.println("http post rsp:" + rsp);
             // Get请求
            url = "https://httpbin.org/get";
            System.out.println("http get rsp:" + okHttpDemo.sendGet(url));
        }
    }

    3、项目应用

    (1)配置文件

    import okhttp3.ConnectionPool;
    import okhttp3.OkHttpClient;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    
    import javax.net.ssl.SSLContext;
    import javax.net.ssl.SSLSocketFactory;
    import javax.net.ssl.TrustManager;
    import javax.net.ssl.X509TrustManager;
    import java.security.KeyManagementException;
    import java.security.NoSuchAlgorithmException;
    import java.security.SecureRandom;
    import java.security.cert.CertificateException;
    import java.security.cert.X509Certificate;
    import java.util.concurrent.TimeUnit;
    
    @Configuration
    public class OkHttpConfiguration {
    
        @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);
        }
    }

    (2)utils 工具类

    import okhttp3.*;
    import org.apache.commons.lang3.exception.ExceptionUtils;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    
    import java.io.File;
    import java.util.Iterator;
    import java.util.Map;
    
    public class OkHttpUtil{
        private static final Logger logger = LoggerFactory.getLogger(OkHttpUtil.class);
        
        private static OkHttpClient  okHttpClient;
    
        @Autowired
        public OkHttpUtil(OkHttpClient  okHttpClient) {
            OkHttpUtil.okHttpClient= okHttpClient;
        } 
        
        /**
         * get
         * @param url     请求的url
         * @param queries 请求的参数,在浏览器?后面的数据,没有可以传null
         * @return
         */
        public static  String get(String url, Map<String, String> queries) {
            String responseBody = "";
            StringBuffer sb = new StringBuffer(url);
            if (queries != null && queries.keySet().size() > 0) {
                boolean firstFlag = true;
                Iterator iterator = queries.entrySet().iterator();
                while (iterator.hasNext()) {
                    Map.Entry entry = (Map.Entry<String, String>) iterator.next();
                    if (firstFlag) {
                        sb.append("?" + entry.getKey() + "=" + entry.getValue());
                        firstFlag = false;
                    } else {
                        sb.append("&" + entry.getKey() + "=" + entry.getValue());
                    }
                }
            }
            Request request = new Request.Builder()
                    .url(sb.toString())
                    .build();
            Response response = null;
            try { 
                response = okHttpClient.newCall(request).execute();
                int status = response.code();
                if (response.isSuccessful()) {
                    return response.body().string();
                }
            } catch (Exception e) {
                logger.error("okhttp3 put error >> ex = {}", ExceptionUtils.getStackTrace(e));
            } finally {
                if (response != null) {
                    response.close();
                }
            }
            return responseBody;
        }
    
        /**
         * post
         *
         * @param url    请求的url
         * @param params post form 提交的参数
         * @return
         */
        public static String post(String url, Map<String, String> params) {
            String responseBody = "";
            FormBody.Builder builder = new FormBody.Builder();
            //添加参数
            if (params != null && params.keySet().size() > 0) {
                for (String key : params.keySet()) {
                    builder.add(key, params.get(key));
                }
            }
            Request request = new Request.Builder()
                    .url(url)
                    .post(builder.build())
                    .build();
            Response response = null;
            try { 
                response = okHttpClient.newCall(request).execute();
                int status = response.code();
                if (response.isSuccessful()) {
                    return response.body().string();
                }
            } catch (Exception e) {
                logger.error("okhttp3 post error >> ex = {}", ExceptionUtils.getStackTrace(e));
            } finally {
                if (response != null) {
                    response.close();
                }
            }
            return responseBody;
        }
    
        /**
         * get
         * @param url     请求的url
         * @param queries 请求的参数,在浏览器?后面的数据,没有可以传null
         * @return
         */
        public static String getForHeader(String url, Map<String, String> queries) {
            String responseBody = "";
            StringBuffer sb = new StringBuffer(url);
            if (queries != null && queries.keySet().size() > 0) {
                boolean firstFlag = true;
                Iterator iterator = queries.entrySet().iterator();
                while (iterator.hasNext()) {
                    Map.Entry entry = (Map.Entry<String, String>) iterator.next();
                    if (firstFlag) {
                        sb.append("?" + entry.getKey() + "=" + entry.getValue());
                        firstFlag = false;
                    } else {
                        sb.append("&" + entry.getKey() + "=" + entry.getValue());
                    }
                }
            }
            Request request = new Request.Builder()
                    .addHeader("key", "value")
                    .url(sb.toString())
                    .build();
            Response response = null;
            try { 
                response = okHttpClient.newCall(request).execute();
                int status = response.code();
                if (response.isSuccessful()) {
                    return response.body().string();
                }
            } catch (Exception e) {
                logger.error("okhttp3 put error >> ex = {}", ExceptionUtils.getStackTrace(e));
            } finally {
                if (response != null) {
                    response.close();
                }
            }
            return responseBody;
        }
    
        /**
         * Post请求发送JSON数据....{"name":"zhangsan","pwd":"123456"}
         * 参数一:请求Url
         * 参数二:请求的JSON
         * 参数三:请求回调
         */
        public static String postJsonParams(String url, String jsonParams) {
            String responseBody = "";
            RequestBody requestBody = RequestBody.create(MediaType.parse("application/json; charset=utf-8"), jsonParams);
            Request request = new Request.Builder()
                    .url(url)
                    .post(requestBody)
                    .build();
            Response response = null;
            try { 
                response = okHttpClient.newCall(request).execute();
                int status = response.code();
                if (response.isSuccessful()) {
                    return response.body().string();
                }
            } catch (Exception e) {
                logger.error("okhttp3 post error >> ex = {}", ExceptionUtils.getStackTrace(e));
            } finally {
                if (response != null) {
                    response.close();
                }
            }
            return responseBody;
        }
    
        /**
         * Post请求发送xml数据....
         * 参数一:请求Url
         * 参数二:请求的xmlString
         * 参数三:请求回调
         */
        public static String postXmlParams(String url, String xml) {
            String responseBody = "";
            RequestBody requestBody = RequestBody.create(MediaType.parse("application/xml; charset=utf-8"), xml);
            Request request = new Request.Builder()
                    .url(url)
                    .post(requestBody)
                    .build();
            Response response = null;
            try { 
                response = okHttpClient.newCall(request).execute();
                int status = response.code();
                if (response.isSuccessful()) {
                    return response.body().string();
                }
            } catch (Exception e) {
                logger.error("okhttp3 post error >> ex = {}", ExceptionUtils.getStackTrace(e));
            } finally {
                if (response != null) {
                    response.close();
                }
            }
            return responseBody;
        }
    }

    三、RestTemplate

    RestTemplate: 是 Spring 提供的用于访问Rest服务的客户端, RestTemplate 提供了多种便捷访问远程Http服务的方法,能够大大提高客户端的编写效率。

    1、导入依赖

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

    2、关于注入RestTemplate对象

      RestTemplate 在源码中是没有@Bean注入的,因此,我们不能直接使用如下方式直接注入

    @Autowired
    private RestTemplate restTemplate;

    【解决方案】

    (1)方式一:如果要使用,可以编写配置文件自己注入

    @Configuration
    public class ApiConfig {
        @Bean
        public RestTemplate restTemplate(ClientHttpRequestFactory factory) {
            return new RestTemplate(factory);
        }
    
        @Bean
        public ClientHttpRequestFactory simpleClientHttpRequestFactory() {
            //默认的是JDK提供http连接,需要的话可以//通过setRequestFactory方法替换为例如Apache HttpComponents、Netty或//OkHttp等其它HTTP library。
            SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory();
            factory.setReadTimeout(5000);//单位为ms
            factory.setConnectTimeout(5000);//单位为ms
            return factory;
        }
    }

    (2)也可以通过自己新建对象直接使用

    RestTemplate restTemplate = new RestTemplate();

    3、如何使用

    (1)Get 请求

    // 方式一
    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);

    (2)Post 请求

    // 方式一
    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);
    
    // 方式二
    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());

    四、Feign/OpenFeign

      可以看这篇:Spring Cloud OpenFeign详解  ——  https://blog.csdn.net/taiyangdao/article/details/81359394

  • 相关阅读:
    第七周作业
    人月神话之没有银弹
    第六周作业
    第五周作业
    第四周作业
    第三周作业
    人月神话之沟通
    第二周作业
    第一周作业
    第八周作业
  • 原文地址:https://www.cnblogs.com/goloving/p/15035647.html
Copyright © 2020-2023  润新知