Java进行Http请求的三种方式总结归纳(JDK/HttpClient/OkHttp3)

需求使然,需要后端使用Java访问特定的第三方接口来进行请求,而这些接口则需要使用Http协议访问。所以归纳了一下目前Java主流的Http访问的三种方式。

第一种:JDK提供  使用java.net.HttpURLConnection

先上代码

/**
 * 第一种:java.net
 */
public class HttpConnect {
    public static String post(String urlStr, String data){
        try {
            URL url = new URL(urlStr);
            HttpURLConnection connection = (HttpURLConnection) url.openConnection();
            connection.setRequestMethod("POST");
            connection.setRequestProperty("Content-Type", "application/json; charset=utf-8");
            connection.setDoOutput(true);
            connection.setDoInput(true);
            connection.setUseCaches(false);
            DataOutputStream dataOutputStream = new DataOutputStream(connection.getOutputStream());
            JSONObject jsonObject = JSON.parseObject(data);
            dataOutputStream.writeBytes(jsonObject.toJSONString());
            dataOutputStream.flush();
            dataOutputStream.close();
            BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
            StringBuilder result = new StringBuilder();
            String line;
            while((line = reader.readLine()) != null){
                result.append(line);
            }
            reader.close();
            connection.disconnect();
            return result.toString();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    public static String get(String strUrl){
        try {
            // 传入参数
//            String realUrl = strUrl;
            URL url = new URL(strUrl);
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            // 在连接之前设置各种属性

            // Content-Type实体头用于向接收方指示实体的介质类型,指定HEAD方法送到接收方的实体介质类型,或GET方法发送的请求介质类型
            conn.setRequestProperty("Content-Type", "application/json; charset=utf-8");
            // 设置打开与此URLConnection引用的资源的通信链接时使用的指定超时值(以毫秒为单位)
            conn.setConnectTimeout(10000);
            // 将读取超时设置为指定的超时时间,以毫秒为单位。
            // conn.setReadTimeout(60000);
            conn.setRequestMethod("GET");
            conn.setUseCaches(false);

            // 建立连接
            conn.connect();
            // 获取响应
            BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream()));
            String line;
            StringBuilder result = new StringBuilder();
            while ((line = reader.readLine()) != null) {
                result.append(line);
            }
            reader.close();
            conn.disconnect();
            return result.toString();
        } catch (IOException e) {
            e.printStackTrace();
        }

        return null;
    }

}

使用URL对象打开连接,也就是HttpURLConnection对象,然后设置各种属性。

建立连接后,喜闻乐见的要获取各种流,通过流来获取Http协议传来的各种Data。

繁琐且麻烦

第二种:HttpClient 是Apache的开源Http请求包

/**
 * apache HttpClient
 */
public class HttpClientTest {

    public static String get(String urlStr){
        // 创建HttpClient对象
        CloseableHttpClient client = HttpClients.createDefault();
        RequestConfig config = RequestConfig.custom()
                .setConnectTimeout(30000)  // 各种参数设置,这里是请求超时时间
                .build();
        HttpGet get = new HttpGet(urlStr);
        get.setConfig(config);
        String result = "";
        try {
            CloseableHttpResponse response = client.execute(get);
            if (response.getStatusLine().getStatusCode() == 200){
                result = EntityUtils.toString(response.getEntity());
                return result;
            }
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            try {
                client.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return null;
    }

    public static String post(String urlStr, String jsonStr){
        CloseableHttpClient client = HttpClients.createDefault();
        HttpPost post = new HttpPost(urlStr);
        RequestConfig requestConfig = RequestConfig.custom()
                .setConnectTimeout(30*1000)
                .build();
        post.setConfig(requestConfig);
        post.setHeader("Content-Type","application/json");
        post.setEntity(new StringEntity(jsonStr, ContentType.create("application/json", "utf-8")));
        String result = "";
        try {
            CloseableHttpResponse response = client.execute(post);
            if (response.getStatusLine().getStatusCode() == 200){
                result = EntityUtils.toString(response.getEntity());
                return result;
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

}

 

百度上是这么写的:

(1)实现了所有 HTTP 的方法(GET,POST,PUT,HEAD 等)

(2)支持自动转向

(3)支持 HTTPS 协议

(4)支持代理服务器等

封装了JDK繁琐的流操作,而且配置使用Builder方式,让代码更清晰好看。对请求返回Code封装了对象,可以通过Code判断请求状态。POST请求可以传入Json字符串,也可以传入List对象,比起JDK的流要便利很多。(疯狂DISS JDK 哈哈)

第三种:OkHttp3  #本人最喜欢的

2019-09-05 更新,重新更改代码结构,并增加新的方法,以便复制即可使用

/**
 * OkHttp
 */
public static String get(String url) throws IOException {
        OkHttpClient okHttpClient = new OkHttpClient.Builder()
                .readTimeout(30L, TimeUnit.SECONDS)
                .build();
        final Request request = new Request.Builder()
                .url(url)
                .get()
                .build();
        final Call call = okHttpClient.newCall(request);
        ResponseBody body = call.execute().body();
        return formatResponse(body);
    }

    public static String post(String url, String requestBody) throws IOException {
        MediaType media = MediaType.parse("application/json;charset=utf-8");
        return post(url, requestBody, media);
    }

    /**
     * 上传文件
     */
    public static String post(String url, File file) throws IOException {
        OkHttpClient okHttpClient = new OkHttpClient.Builder()
                .readTimeout(30L, TimeUnit.SECONDS)
                .build();
        MediaType media = MediaType.parse("multipart/form-data");
        RequestBody requestBody = RequestBody.create(file, media);
        MultipartBody multipartBody = new MultipartBody.Builder()
                // 设置type为"multipart/form-data"
                .setType(MultipartBody.FORM)
                .addFormDataPart("file", file.getName(), requestBody)
                .build();
        Request request = new Request.Builder()
                .url(url)
                .post(multipartBody)
                .build();
        Call call = okHttpClient.newCall(request);
        ResponseBody body = call.execute().body();
        return formatResponse(body);
    }

    private static String post(String url, String requestBody, MediaType media) throws RuntimeException, IOException {
        OkHttpClient okHttpClient = new OkHttpClient.Builder()
                .readTimeout(30L, TimeUnit.SECONDS)
                .build();
        Request request = new Request.Builder()
                .url(url)
                .post(RequestBody.create(requestBody, media))
                .build();

        Call call = okHttpClient.newCall(request);
        ResponseBody body = call.execute().body();
        return formatResponse(body);
    }

    private static String formatResponse(ResponseBody body) throws IOException {
        final StringBuilder stringBuilder = new StringBuilder();
        // 同步请求
        if (body != null){
            stringBuilder.append(body.string());
        }
        return stringBuilder.toString();
    }

同样的,已经封装了任何流的操作,使用Builder创建连接对象。更方便地,可以根据需求决定使用同步请求还是异步请求。异步请求时,OkHttp会要求构造回调函数,这种清晰直观的设计让人不管观看还是使用,都很舒服。

使用POST请求时,也有封装的RequestBody,进行参数设置。

事实上,OkHttp的优点主要是:(官网的说明)

  • 支持HTTP/2,允许所有同一个主机地址的请求共享同一个socket连接

  • 连接池减少请求延时(如果Http2 不可用)

  • 透明的GZIP压缩减少响应数据的大小

  • 缓存响应内容,避免一些完全重复的请求

 

OkHttp最精髓的部分是他的拦截器。在创建HttpClient对象时,可以加上

.addInterceptor(new Interceptor()/* 该类的实现类*/)

就可以拦截这个请求,并做一些不为人知的事。嘿嘿~

只需要实现

public abstract Response intercept(Chain chain) throws IOException;

这个方法,就可以了,更多具体使用方法,可以参考官方API文档,这里不多作赘述。

附上链接

就是这样,附上本文参考资料。

  • JDK参考
  • HttpURLConnection参考
  • OkHttp参考

 

 

 

你可能感兴趣的:(Java进行Http请求的三种方式总结归纳(JDK/HttpClient/OkHttp3))