本篇文章主要介绍使用HttpClient和OKHttp两种方式进行HTTP请求。
1. Http请求概述
请求方法
主要使用HTTP GET
或 POST
方式发送请求,GET方式下请求参数需要包含在请求的URL中,POST方式下请求参数需要包含在请求的Body中。
HTTP请求中,常见的Content-Type类型:
1、application/x-www-form-urlencoded
最常见的 POST 提交数据的方式,表单默认的提交数据的格式,如果不设置 enctype 属性,默认为application/x-www-form-urlencoded 方式提交数据。提交的表单数据会转换为键值对并按照 key1=val1&key2=val2 的方式进行编码,key 和 val 都进行了 URL 转码。
2、application/json
JSON数据格式,现在越来越多的人把它作为请求头,用来告诉服务端消息主体是序列化后的 JSON 字符串,其中一个好处就是JSON 格式支持比键值对复杂得多的结构化数据
3、multipart/form-data
需要在表单中进行文件上传时,就需要使用该格式。它会将表单的数据处理为一条消息,以标签为单元,用分隔符(就是boundary的作用)分开。
4、application/octet-stream
二进制流数据(如常见的文件下载)
2. HttpClient
HttpClient使用介绍
使用HttpClient发送请求主要分为以下几步骤:
- 创建 CloseableHttpClient对象或CloseableHttpAsyncClient对象,前者同步,后者为异步
- 创建Http请求对象
- 调用execute方法执行请求,如果是异步请求在执行之前需调用start方法
Get请求:
String url = "xxxxx";
//1.创建client、response对象
CloseableHttpClient client = HttpClientBuilder.create().build();
CloseableHttpResponse response = null;
//2.构造请求:使用HttpGet表示该连接为GET请求,HttpClient调用execute方法发送GET请求
HttpGet httpGet = new HttpGet(url);
//3.执行请求并接收返回数据
response = client.execute(httpGet);
Post请求:
String url = "xxxxx";
//1.创建client和response对象
CloseableHttpClient client = HttpClientBuilder.create().build();
CloseableHttpResponse response = null;
//2.构造请求:使用HttpPost表示该连接为POST请求,HttpClient调用execute方法发送POST请求
HttpGet httpPost= new HttpPost(url);
//设置请求头,请求体,配置
httpPost.setHeader("Content-Type", "application/json;charset=utf8");
httpPost.setHeader("Access-Token", accessToken);
httpPost.setConfig(requestConfig);
httpPost.setEntity(new StringEntity(JSONObject.toJSONString(userVO), "UTF-8"));
//3.执行请求并接收返回数据
response = client.execute(httpPost);
通过POST上传文件:(Content-Type = multipart/form-data)
String url = "xxxxx";
String fileUrl = "xxxxx";
//1.创建client、response对象、httpPost请求对象
CloseableHttpClient client = HttpClientBuilder.create().build();
CloseableHttpResponse response = null;
HttpPost httpPost = new HttpPost(url);
//获取文件(文件在本地)
FileBody fileBody = new FileBody(new File(fileUrl));
//将文件fileUrl下载到本地localUrl(文件在远端)
String localUrl = "xxxxx";
FileUtil.download(fileUrl, localUrl);
//新建MultipartEntityBuilder对象,通过addPart上传文件,addTextBody上传文本数据
MultipartEntityBuilder entityBuilder = MultipartEntityBuilder.create()
entityBuilder.addPart("image_file",fileBody);
entityBuilder.addTextBody("Content-Type","multipart/form-data");
entityBuilder.addTextBody("advertiser_id", "0");
entityBuilder.addTextBody("image_signature", "xxx");
HttpEntity entity = entityBuilder.build();
//放入httpEntity
httpPost.setEntity(entity);
//3.执行请求并接收返回数据
response = client.execute(httpPost);
从远端下载文件到本地(服务器),写在FileUtil类下
//fileUrl:下载文件的url,filepath:保存在本地的地址
public static Boolean download(String fileUrl, String filepath) {
Boolean ret = false;
try {
HttpClient client = HttpClients.custom().build();
HttpGet httpget = new HttpGet(fileUrl);
HttpResponse response = client.execute(httpget);
HttpEntity entity = response.getEntity();
InputStream is = entity.getContent();
File file = new File(filepath);
file.getParentFile().mkdirs();
FileOutputStream fileout = new FileOutputStream(file);
int cache = true;
byte[] buffer = new byte[10240];
boolean var12 = false;
int byteread = 0;
while((ch = is.read(buffer)) != -1) {
fileout.write(buffer, 0, byteread );
}
is.close();
fileout.flush();
fileout.close();
ret = true;
} catch (Exception var13) {
logger.error("error : ", var13);
ret = false;
var13.printStackTrace();
}
return ret;
}
3. OKHttp
OkHttp使用介绍
1、高效的HTTP客户端,它能允许同一ip和端口的请求重用一个socket,这种方式能大大降低网络连接的时间,和每次请求都建立socket,再断开socket的方式相比,降低了服务器服务器的压力,透明的GZIP压缩减少响应数据的大小;缓存响应内容。
2、okhttp 对http和https都有良好的支持。 3、okhttp 对大数据量的网络请求支持非常好。使用OkHttp发送请求主要分为以下几步骤:
- 创建OkHttpClient对象
- 创建Request对象
- 将Request 对象封装为Call
- 通过Call 来执行同步或异步请求,调用execute方法同步执行,调用enqueue方法异步执行
Get请求:
//创建client连接对象:
OkHttpClient client = new OkHttpClient().newBuilder().build();
//Get请求
public void testGet() throws IOException {
String url = "xxxxx";
//创建Request对象
Request request = new Request.Builder()
.url(url)
.get() //默认为GET请求,可以不写
.build();
//将Request对象封装为Call
final Call call = client.newCall(request);
//调用execute方法
Response response = call.execute();
System.out.println(response.body().string());
}
Post请求
//Post请求
public void testPost() throws IOException {
String api = "/api/user";
String url = String.format("%s%s", BASE_URL, api);
//请求参数json,放入requestBody中
JSONObject json = new JSONObject();
json.put("name", "hetiantian");
RequestBody requestBody = RequestBody.create(MediaType.parse("application/json; charset=utf-8"),String.valueOf(json));
//1.2.3.
Request request = new Request.Builder()
.url(url)
.post(requestBody) //post请求
.addHeader("Content-Type", "application/json")
.addHeader("Access-Token", ACCESS_TOKEN)
.build();
try{
Response response = client.newCall(request).execute();
String res = response.body().string(); //获取到response中的内容并存到DTO
log.info(res);
RetDTO retDTO= JSON.parseObject(res,RetDTO.class);
return retDTO;
}catch(IOException e){
e.printStackTrace();
}retrun null;
}
上传文件
public void testUpload() throws IOException {
String api = "/api/files/1";
String url = String.format("%s%s", BASE_URL, api);
RequestBody requestBody = new MultipartBody.Builder()
.setType(MultipartBody.FORM)
.addFormDataPart("file", "docker_practice.pdf",
RequestBody.create(MediaType.parse("multipart/form-data"),
new File("C:/Users/practice.pdf")))
.build();
//步骤1.2.3.
Request request = new Request.Builder()
.url(url)
.post(requestBody)
.build();
final Call call = client.newCall(request);
Response response = call.execute();
System.out.println(response.body().string());
}
小结
OkHttp使用build模式创建对象来的更简洁一些,并且使用.post/.get/.delete/.put方法表示请求类型,不需要像HttpClient创建HttpGet、HttpPost等这些方法来创建请求类型
依赖包上,如果HttpClient需要发送异步请求、实现文件上传,需要额外的引入异步请求依赖
HttpClient超时设置:
在HttpClient4.3+版本以上,超时设置通过RequestConfig
进行设置
private CloseableHttpClient httpClient = HttpClientBuilder.create().build();
private RequestConfig requestConfig = RequestConfig.custom()
.setSocketTimeout(60 * 1000)
.setConnectTimeout(60 * 1000).build();
String api = "/api/files/1";
String url = String.format("%s%s", BASE_URL, api);
HttpGet httpGet = new HttpGet(url);
httpGet.setConfig(requestConfig); //设置超时时间
超时时间是设置在请求类型HttpGet上,而不是HttpClient上
OkHttp超时设置:
直接在OkHttp上进行设置
private OkHttpClient client = new OkHttpClient.Builder()
.connectTimeout(60, TimeUnit.SECONDS)//设置连接超时时间
.readTimeout(60, TimeUnit.SECONDS)//设置读取超时时间
.build();
小结:
如果client是单例模式,HttpClient在设置超时方面来的更灵活,针对不同请求类型设置不同的超时时间,OkHttp一旦设置了超时时间,所有请求类型的超时时间也就确定