java实现调用Http请求常用的几种方式

人生之路坎坎坷坷,跌跌撞撞在所难免。但是,不论跌了多少次,你都必须坚强勇敢地站起来。任何时候,无论你面临着生命的何等困惑抑或经受着多少挫折,无论道路多艰难,希望变得如何渺茫,请你不要绝望,再试一次,坚持到底,成功终将属于勇不言败的你。

导读:本篇文章讲解 java实现调用Http请求常用的几种方式,希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com,来源:原文

参考链接: https://blog.csdn.net/riemann_/article/details/90539829.
参考链接: 使用HttpURlConnection 发送POST请求上传文件(带参数).

使用这些http客户端时注意tcp链接数的问题

参考链接: 高并发下对接第三方请求时http请求的问题及处理方式.

通过Java.net.HttpURLConnection实现

import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

public class MyHttpUtil {

    private static final int TIME_OUT = 5 * 1000;             //超时时间
    private static final String GET = "GET";                  //GET请求
    private static final String POST = "POST";                //GET请求
    private static final String CHARSET = "UTF-8";            //编码格式
    private static final String PREFIX = "--";                //前缀
    private static final String LINE_END = "\r\n";            //换行

    /**
     * 对post参数进行编码处理
     */
    private static StringBuilder getStrParams(Map<String, String> strParams, String BOUNDARY) {
        StringBuilder strSb = new StringBuilder();
        for (Map.Entry<String, String> entry : strParams.entrySet()) {
            strSb.append(PREFIX)
                    .append(BOUNDARY)
                    .append(LINE_END)
                    .append("Content-Disposition: form-data; name=\"" + entry.getKey() + "\"" + LINE_END)
                    .append("Content-Type: text/plain; charset=" + CHARSET + LINE_END)
                    .append("Content-Transfer-Encoding: 8bit" + LINE_END)
                    .append(LINE_END)// 参数头设置完以后需要两个换行,然后才是参数内容
                    .append(entry.getValue())
                    .append(LINE_END);
        }
        return strSb;
    }


    public static String upload(String url, Map<String, String> strParams, File file) {
        String boundary = UUID.randomUUID().toString(); // 文件边界
        String filename = file.getName();
        StringBuffer result = new StringBuffer();
        HttpURLConnection connection = null;
        try {
            URL url1 = new URL(url);
            connection = (HttpURLConnection) url1.openConnection();
            connection.setRequestMethod(POST);
            connection.setDoOutput(true);
            connection.setDoInput(true);
            connection.setUseCaches(false);
            connection.setConnectTimeout(TIME_OUT);
            connection.setReadTimeout(TIME_OUT);
            connection.setRequestProperty("accept", "*/*");
            connection.setRequestProperty("connection", "Keep-Alive");
            connection.setRequestProperty("Charset", CHARSET);
            connection.setRequestProperty("Content-Type", "multipart/form-data" + ";boundary=" + boundary);
            connection.connect();
            try (DataOutputStream dos = new DataOutputStream(connection.getOutputStream());
                 InputStream is = new FileInputStream(file)) {
                dos.writeBytes(getStrParams(strParams, boundary).toString());
                dos.flush();
                StringBuilder fileSb = new StringBuilder();
                fileSb.append(PREFIX)
                        .append(boundary)
                        .append(LINE_END)
                        .append("Content-Disposition: form-data; name=\"file\"; filename=\""
                                + filename + "\"" + LINE_END)
                        .append("Content-Transfer-Encoding: 8bit" + LINE_END)
                        .append(LINE_END);
                dos.writeBytes(fileSb.toString());
                dos.flush();
                byte[] buffer = new byte[1024];
                int len = 0;
                while ((len = is.read(buffer)) != -1) {
                    dos.write(buffer, 0, len);
                }
                //请求结束标志
                dos.writeBytes(LINE_END + PREFIX + boundary + PREFIX + LINE_END);
                dos.flush();
            }
            try (BufferedReader reader = new BufferedReader(
                    new InputStreamReader(connection.getInputStream(), CHARSET))) {
                String line;
                while ((line = reader.readLine()) != null) {
                    result.append(line);
                }
                System.out.println(result.toString());
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            connection.disconnect();
        }
        return result.toString();
    }


    public static String post(String url, String content) {
        StringBuffer result = new StringBuffer();
        HttpURLConnection connection = null;
        try {
            URL url1 = new URL(url);
            connection = (HttpURLConnection) url1.openConnection();
            //设置请求方式
            connection.setRequestMethod(POST);
            //DoOutput设置是否向httpUrlConnection输出,DoInput设置是否从httpUrlConnection读入,此外发送post请求必须设置这两个
            connection.setDoOutput(true);
            connection.setDoInput(true);
            // 设置是否允许缓存值
            connection.setUseCaches(false);
            //设置连接超时时间
            connection.setConnectTimeout(TIME_OUT);
            //设置读取超时时间
            connection.setReadTimeout(TIME_OUT);
            //设置通用的请求属性
            connection.setRequestProperty("accept", "*/*");
            connection.setRequestProperty("connection", "Keep-Alive");
            connection.setRequestProperty("Content-Type", "application/json;charset=utf-8");
            connection.connect();
            try (OutputStreamWriter out = new OutputStreamWriter(connection.getOutputStream(), CHARSET)) {
                out.append(content);
                out.flush();
            }
            try (BufferedReader reader = new BufferedReader(
                    new InputStreamReader(connection.getInputStream(), CHARSET))) {
                String line;
                while ((line = reader.readLine()) != null) {
                    result.append(line);
                }
                System.out.println(result.toString());
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            connection.disconnect();
        }
        return result.toString();
    }


    public static String get(String url) {
        StringBuffer stringBuffer = new StringBuffer();
        HttpURLConnection connection = null;
        try {
            URL url1 = new URL(url);
            connection = (HttpURLConnection) url1.openConnection();
            //设置请求方式
            connection.setRequestMethod(GET);
            //设置连接超时时间
            connection.setReadTimeout(TIME_OUT);
            //开始连接
            connection.connect();
            try (BufferedReader bufferedReader = new BufferedReader(
                    new InputStreamReader(connection.getInputStream(), CHARSET))) {
                String line;
                while ((line = bufferedReader.readLine()) != null) {
                    stringBuffer.append(line);
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            connection.disconnect();
        }
        System.out.println("GET请求返回值:" + stringBuffer.toString());
        return stringBuffer.toString();
    }

}

总结:
如果使用了HttpUrlConnection进行http请求
1.最好在finally中加disconnet(),以防异常时候http连接未被关闭,造成tcp连接堆积
2.并且要设置连接和读取超时时间,否则程序会一直卡在获取流这一步
3.记得关闭IO流资源

HttpClient

参考链接: HttpClient用法–这一篇全了解.

链接: 实现HttpClient重试

HttpClient是Apache Jakarta Common下的子项目,用来提供高效的、最新的、功能丰富的支持HTTP协议的客户端编程工具包,并且它支持HTTP协议最新的版本和建议。HttpClient已经应用在很多的项目中,比如Apache Jakarta上很著名的另外两个开源项目Cactus和HTMLUnit都使用了HttpClient。
在这里插入图片描述
HttpClient相比传统JDK自带的URLConnection,增加了易用性和灵活性,它不仅使客户端发送Http请求变得容易,而且也方便开发人员测试接口(基于Http协议的),提高了开发的效率,也方便提高代码的健壮性。

org.apache.commons.httpclient.HttpClient与org.apache.http.client.HttpClient的区别

Commons的HttpClient项目现在是生命的尽头,不再被开发, 已被Apache HttpComponents项目HttpClient和HttpCore 模组取代,提供更好的性能和更大的灵活性。

基本使用方法

<!-- 导入依赖包 -->
<dependency>
    <groupId>org.apache.httpcomponents</groupId>
    <artifactId>httpclient</artifactId>
    <version>4.5.13</version>
</dependency>
<dependency>
    <groupId>org.apache.httpcomponents</groupId>
    <artifactId>httpmime</artifactId>
    <version>4.5.13</version>
</dependency>

使用 HttpClient 发送请求主要分为一下几步骤:
创建 CloseableHttpClient 对象或 CloseableHttpAsyncClient 对象
创建 Http 请求对象
调用 execute 方法执行请求,如果是异步请求在执行之前需调用 start 方法
释放连接或放回线程池

参考链接: HttpClient详细使用示例.

ClosableHttpClient 同步请求

import com.alibaba.fastjson.JSON;
import com.zm.entity.User;
import org.apache.http.HttpEntity;
import org.apache.http.NameValuePair;
import org.apache.http.ParseException;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;

import java.io.File;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URLEncoder;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class HttpClientUtil {


    public static void get(String url) {
        // 创建 Http 请求对象
        HttpGet httpGet = new HttpGet(url);
        RequestConfig requestConfig = RequestConfig.custom()
                .setConnectionRequestTimeout(3000)//使用连接池来管理连接,从连接池获取连接的超时时间
                .setSocketTimeout(5000)//请求超时,数据传输过程中数据包之间间隔的最大时间
                .setConnectTimeout(5000)//连接超时,连接建立时间,三次握手完成时间
                .build();
        httpGet.setConfig(requestConfig);
        try (// 获得Http客户端(创建 CloseableHttpClient 对象或 CloseableHttpAsyncClient 对象)
             CloseableHttpClient httpClient = HttpClientBuilder.create().build();
             // 调用 execute 方法执行请求,如果是异步请求在执行之前需调用 start 方法
             CloseableHttpResponse response = httpClient.execute(httpGet)) {
            // 从响应模型中获取响应实体
            HttpEntity responseEntity = response.getEntity();
            System.out.println("响应状态为:" + response.getStatusLine());
            if (responseEntity != null) {
                System.out.println("响应内容为:" + EntityUtils.toString(responseEntity, StandardCharsets.UTF_8));
            }
        } catch (ClientProtocolException e) {
            e.printStackTrace();
        } catch (ParseException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * get请求 参数转码
     *
     * @return
     * @throws UnsupportedEncodingException
     */
    public static String getParams(Map<String, String> params){
        StringBuilder strSb = new StringBuilder();
        boolean index = false;
        for (Map.Entry<String, String> entry : params.entrySet()) {
            if (index) {
                strSb.append("&");
            }
            strSb.append(entry.getKey())
                    .append("=")
                    .append(encode(entry.getValue()));
            index = true;
        }
        return strSb.toString();
    }

    public static void get(String url, Map<String, String> params) {
        // 方式一:直接拼接URL
        String param = getParams(params);
        // 创建 Http 请求对象
        HttpGet httpGet = new HttpGet(url + "?" + param);

        // 方式二:使用URI获得HttpGet
//        URI uri = null;
//        try {
//            // 将参数放入键值对类NameValuePair中,再放入集合中
//            List<NameValuePair> param = new ArrayList<>();
//            for (Map.Entry<String, String> entry : params.entrySet()) {
//                param.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));
//            }
//            // 设置uri信息,并将参数集合放入uri;
//            uri = new URIBuilder().setScheme("http").setHost("localhost")
//                    .setPort(8080).setPath("/Exception")
//                    .setParameters(param).build();
//
//        } catch (URISyntaxException e) {
//            e.printStackTrace();
//        }
//        // 创建Get请求
//        HttpGet httpGet = new HttpGet(uri);
        
        RequestConfig requestConfig = RequestConfig.custom()
                .setConnectionRequestTimeout(3000)//使用连接池来管理连接,从连接池获取连接的超时时间
                .setSocketTimeout(5000)//请求超时,数据传输过程中数据包之间间隔的最大时间
                .setConnectTimeout(5000)//连接超时,连接建立时间,三次握手完成时间
                .build();
        httpGet.setConfig(requestConfig);
        try (// 获得Http客户端(创建 CloseableHttpClient 对象或 CloseableHttpAsyncClient 对象)
             CloseableHttpClient httpClient = HttpClientBuilder.create().build();
             // 调用 execute 方法执行请求,如果是异步请求在执行之前需调用 start 方法
             CloseableHttpResponse response = httpClient.execute(httpGet)) {
            // 从响应模型中获取响应实体
            HttpEntity responseEntity = response.getEntity();
            System.out.println("响应状态为:" + response.getStatusLine());
            if (responseEntity != null) {
                System.out.println("响应内容为:" + EntityUtils.toString(responseEntity, StandardCharsets.UTF_8));
            }
        } catch (ClientProtocolException e) {
            e.printStackTrace();
        } catch (ParseException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static void post(String url, String params) {
        // 创建Post请求
        HttpPost httpPost = new HttpPost(url);
        // post请求是将参数放在请求体里面传过去的;这里将entity放入post请求体中
        httpPost.setEntity(new StringEntity(params, StandardCharsets.UTF_8));
        httpPost.setHeader("Content-Type", "application/json;charset=utf8");
        try (CloseableHttpClient httpClient = HttpClientBuilder.create().build();
             CloseableHttpResponse response = httpClient.execute(httpPost)) {
            HttpEntity responseEntity = response.getEntity();
            System.out.println("响应状态为:" + response.getStatusLine());
            if (responseEntity != null) {
                System.out.println("响应内容为:" + EntityUtils.toString(responseEntity, StandardCharsets.UTF_8));
            }
        } catch (ClientProtocolException e) {
            e.printStackTrace();
        } catch (ParseException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static String encode(String str) {
        String encode = null;
        try {
            encode = URLEncoder.encode(str, "UTF-8");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return encode;
    }
    
    public static void upload(String url, Map<String, String> params, File file) {
        HttpPost httpPost = new HttpPost(url);
        MultipartEntityBuilder multipartEntityBuilder = MultipartEntityBuilder.create();
        String filesKey = "file";
        // (多个文件的话,使用同一个key就行,后端用数组或集合进行接收即可)
        // 文件名其实是放在请求头的Content-Disposition里面进行传输的,如其值为form-data; name="files"; filename="头像.jpg"
        multipartEntityBuilder.addBinaryBody(filesKey, file, ContentType.DEFAULT_BINARY, encode(file.getName()));
        // 其它参数(注:自定义contentType,设置UTF-8是为了防止服务端拿到的参数出现乱码)
        ContentType contentType = ContentType.create("text/plain", Charset.forName("UTF-8"));
        for (Map.Entry<String, String> entry : params.entrySet()) {
            multipartEntityBuilder.addTextBody(entry.getKey(), entry.getValue(), contentType);
        }
        HttpEntity httpEntity = multipartEntityBuilder.build();
        httpPost.setEntity(httpEntity);
        try (CloseableHttpClient httpClient = HttpClientBuilder.create().build();
             CloseableHttpResponse response = httpClient.execute(httpPost)) {
            HttpEntity responseEntity = response.getEntity();
            System.out.println("HTTPS响应状态为:" + response.getStatusLine());
            if (responseEntity != null) {
                String responseStr = EntityUtils.toString(responseEntity, StandardCharsets.UTF_8);
                System.out.println("HTTPS响应内容为:" + responseStr);
            }
        } catch (ParseException | IOException e) {
            e.printStackTrace();
        }
    }
    

}

CloseableHttpAsynClient 异步请求(了解)

链接: 异步请求CloseableHttpAsyncClient的使用.

OkHttp

参考链接: java使用OkHttp.
参考链接: Okhttp4 RequestBody.create()过时 解决办法.

使用 OkHttp 发送请求主要分为一下几步骤:
创建 OkHttpClient 对象
创建 Request 对象
将 Request 对象封装为 Call
通过 Call 来执行同步或异步请求,调用 execute 方法同步执行,调用 enqueue 方法异步执行

<!--导入依赖 排除android部分 -->
<dependency>
    <groupId>com.squareup.okhttp3</groupId>
    <artifactId>okhttp</artifactId>
    <version>4.9.1</version>
    <exclusions>
        <exclusion>
            <groupId>com.google.android</groupId>
            <artifactId>android</artifactId>
        </exclusion>
    </exclusions>
</dependency>
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import okhttp3.*;
import java.io.File;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.*;
import java.util.concurrent.TimeUnit;

public class OkHttpUtil {
    
    private static volatile OkHttpClient client;

    private static final String DEFAULT_MEDIA_TYPE = "application/json;charset=utf-8";

    private static final int CONNECT_TIMEOUT = 5;

    private static final int READ_TIMEOUT = 7;
    
    /**
     * 单例模式  获取类实例
     *
     * @return client
     */
    private static OkHttpClient getInstance() {
        if (client == null) {
            synchronized (OkHttpClient.class) {
                if (client == null) {
                    client = new OkHttpClient.Builder()
                            .connectTimeout(CONNECT_TIMEOUT, TimeUnit.SECONDS)// 设置连接超时时间
                            .readTimeout(READ_TIMEOUT, TimeUnit.SECONDS)// 设置读取超时时间
                            .build();
                }
            }
        }
        return client;
    }

    public static String get(String url) {
        try {
            Request request = new Request.Builder().url(url).build();
            Response response = getInstance().newCall(request).execute();
            return handleHttpResponse(response);
        } catch (Exception ex) {
            return StringUtils.EMPTY;
        }
    }

    public static String encode(String str) {
        String encode = null;
        try {
            encode = URLEncoder.encode(str, "UTF-8");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return encode;
    }

    /**
     * get请求 参数转码
     *
     * @return
     * @throws UnsupportedEncodingException
     */
    public static String getParams(Map<String, String> params) {
        StringBuilder strSb = new StringBuilder();
        boolean index = false;
        for (Map.Entry<String, String> entry : params.entrySet()) {
            if (index) {
                strSb.append("&");
            }
            strSb.append(entry.getKey())
                    .append("=")
                    .append(encode(entry.getValue()));
            index = true;
        }
        return strSb.toString();
    }


    public static String get(String url, Map<String, String> params) {
        try {
            url = url + "?" + getParams(params);
            System.out.println(url);
            Request request = new Request.Builder().url(url).build();
            Response response = getInstance().newCall(request).execute();
            return handleHttpResponse(response);
        } catch (Exception ex) {
            return StringUtils.EMPTY;
        }
    }


    public static String post(String url, String postBody) {
        try {
            MediaType mediaType = MediaType.Companion.parse(DEFAULT_MEDIA_TYPE);
            RequestBody stringBody = RequestBody.Companion.create(postBody, mediaType);
            Request request = new Request.Builder()
                    .url(url)
                    .post(stringBody)
                    .build();
            Response response = getInstance().newCall(request).execute();
            return handleHttpResponse(response);
        } catch (Exception ex) {
            return StringUtils.EMPTY;
        }
    }

    public static String upload(String url, Map<String, String> params, File file) throws IOException {
        MultipartBody.Builder builder = new MultipartBody.Builder();
        String fileName = file.getName();
        MediaType mediaType = MediaType.Companion.parse("multipart/form-data");
        RequestBody fileBody = RequestBody.Companion.create(file, mediaType);
        for (Map.Entry<String, String> entry : params.entrySet()) {
            builder.addFormDataPart(entry.getKey(), entry.getValue());  // 上传参数
        }
        RequestBody requestBody = builder
                .setType(MultipartBody.FORM)
                .addFormDataPart("file", fileName, fileBody)
                .build();
        Request request = new Request.Builder()
                .url(url)
                .post(requestBody)
                .build();
        Response response = getInstance().newCall(request).execute();
        return handleHttpResponse(response);
    }


    public static void main(String[] args) throws IOException {
        HashMap<String, String> map = new HashMap<>();
        map.put("name","小明");
        System.out.println(upload("http://127.0.0.1:8080/upload", map,new File("C:\\Users\\a\\Pictures\\1.jpg")));

    }
    

    private static String handleHttpResponse(Response response) throws IOException {
        if (response.body() == null) {
            throw new IOException("exception in OkHttpUtil,response body is null");
        }
        if (!response.isSuccessful()) {
           throw new RuntimeException("OkHttpUtil request failed");
        }
        return response.body().string();
    }
    
}

文件和参数接收


import com.zm.entity.User;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;

@RestController
public class TestController {

    @PostMapping("/upload")
    @ApiOperation(value = "上传文件")
    public String upload(@RequestParam("file") MultipartFile file, User user) {
        System.out.println(user);
        String fileName = file.getOriginalFilename();// 文件名
        String filePath = "F:\\img\\";// 保存图片的地址
        File dest = new File(filePath + fileName);
        try {
            file.transferTo(dest);
            return "上传成功";
        } catch (IOException e) {
            e.printStackTrace();
        }
        return "上传失败!";
    }

}

RestTemplate

链接: RestTemplate与ClosableHttpClient.

Spring WebClient下封装了专门用于restful请求的RestTempate实际上内部就采用了ClosableHttpClient,对于有连接池的Client来说,最好使用单例模式,同时根据调用量配置合适的连接池大小以及配置各种超时时间等

待续。。。。。

https://www.jianshu.com/p/c852cbcf3d68

首先,明确两点:
1.http连接池不是万能的,过多的长连接会占用服务器资源,导致其他服务受阻
2.http连接池只适用于请求是经常访问同一主机(或同一个接口)的情况下
3.并发数不高的情况下资源利用率低下

那么,当你的业务符合上面3点,那么你可以考虑使用http连接池来提高服务器性能
使用http连接池的优点:
1.复用http连接,省去了tcp的3次握手和4次挥手的时间,极大降低请求响应的时间
2.自动管理tcp连接,不用人为地释放/创建连接

Forest

SpringBoot整合Forest实现调用第三方接口

https://zhengqing.blog.csdn.net/article/details/108258130

轻量级 HTTP 客户端

https://www.oschina.net/p/forest?hmsr=aladdin1e1

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/133947.html

(0)
飞熊的头像飞熊bm

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!