我们在项目开发的过程中经常会使用到网络请求,比如对接某个第三方的接口,大部分的接口一般都是通过 HTTP 来请求,这就需要来构造一个 HTTP 协议,本篇文章就具体来讲讲如何通过HttpClient发送不同body类型的请求
HTTP协议
我们在使用一个web浏览器访问一个网址的时候,浏览器会向服务端建立起用一个通道,并通过这个通道来获取访问的内容并将内容呈现到浏览器上
那么这里就涉及到客户端该怎么样构造一个请求的数据格式来给到服务端,服务端又需要构造一个怎么样的数据格式响应给客户端,它们如果要顺利的完成这种数据交互就需要有一种统一的规约,这种规约我们就称之为协议
其实这种规约在现实生活中也是随处可见的,比如你要跟一个不懂中文的外国人交流,那么首先你得会说英文才能跟他交流,而 "说英文" 就是你跟外国人的一种规约;再比如你后端在写接口的时候需要提供一个接口文档供前端查看,前端按照接口文档里定义好的接口来进行开发,这种 "接口" 就是你后端跟前端的一种规约
HTTP协议就是这种规约的一种,是 TCP/IP 协议族内部的一个子集,属于应用层,当然除了HTTP之外,还有FTP,RTMP,SNMP等
HTTP协议的报文格式一共包含两部分---报文首部和报文主体,请求和响应对应不同的报文
这些报文内容我们可以直接通过浏览器查看
下图是请求报文
报文中的第一行数据我们也称为请求行,主要描述请求的方式及请求的路径,其他就是主要描述请求数据、编码格式、ip地址、浏览器版本等,这些东西我们也可以通过 HttpServletRequest 来获取
如果是 POST 请求会将 POST 提交的数据放到报文主体里
下图是响应报文
报文的第一行是响应行,主要描述响应状态和协议版本,其他的主要就是描述响应数据、响应时间等
如果服务端响应了一些数据,也会将这些数据放到报文主体里
不同的请求类型如何传送数据
我们如果要向第三方接口发送网络请求,上面的HTTP协议中的报文首部不需要过多的关注,在请求的过程中我们主要是要将数据发送给第三方,因此我们只要关注报文主体就行了,那么这里就要讲下最为重要的两种请求类型--POST和GET
GET传送数据
对于 GET 请求来讲,我们是直接通过 URL 后面拼接参数来传送数据,那么这是一种 QueryString 方式,这种方式虽然比较的简单,但是也要注意中文乱码问题
下面的请求方式就展示了通过 GET 请求来传送数据
POST传送数据
如果是POST请求来传送数据的话,那么这里传送数据的方式就得分几种类型了,我们称为body类型,body类型最为常用的有 form-data ,x-www-from-urlencoded ,application/json,application/xml 等
如何用Java发送HTTP请求
Java 发送网络请求最常用的就是通过 HttpClient 来发送,HttpClient 封装了通用的请求协议,让我们只关注传送数据本身
这里我用 HttpClient 4.3.2版本来具体讲下如何进行发送不同body类型的请求
我们首先需要导入对应的 jar 包
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.3.2</version>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpmime</artifactId>
<version>4.3.2</version>
</dependency>
发送GET请求
HttpClient 对于GET和POST分别提供了Java类---HttpGet和HttpPost,我们如果需要发送GET请求的话就需要使用到HttpGet
public static void main(String[] args) throws IOException {
CloseableHttpClient httpclient = HttpClients.createDefault();
// 构造一个GET请求
HttpGet httpget = new HttpGet("http://localhost:8080/service/send?name=张三&age=12");
// 如果需要设置头信息
httpget.setHeader("singn","abcdefg");
// 执行GET请求
CloseableHttpResponse response = httpclient.execute(httpget);
// 解析响应参数
String responseStr = EntityUtils.toString(response.getEntity());
}
发送POST请求
form-data(表单) 传送数据
HttpClient 提供了 MultipartEntityBuilder 类,也可以称为实体对象,我们可以通过不同的类型数据构造实体对象
public static void main(String[] args) throws IOException {
// 构建POST请求
HttpPost httpPost = new HttpPost("http://localhost:8080/service/send");
// 如果是表单的形式 , 构建一个MultipartEntityBuilder实体
MultipartEntityBuilder multipartEntityBuilder = MultipartEntityBuilder.create();
// 添加参数,如果是纯文本的话
multipartEntityBuilder.addTextBody("name","zhangsan");
// 添加参数,如果是上传文件
multipartEntityBuilder.addBinaryBody("file",new File("fileurl"));
httpPost.setEntity(multipartEntityBuilder.build());
// 执行POST请求
CloseableHttpResponse response = httpclient.execute(httpPost);
}
x-www-form-urlencoded 传送数据
这种方式跟form-data方式差不多也是通过键值对的方式传送,唯一不同的就是form-data可以上传文件
HttpClient 也提供了 UrlEncodedFormEntity ,我们可以通过这个实体来构造POST请求
public static void main(String[] args) throws IOException {
// 构建POST请求
HttpPost httpPost = new HttpPost("http://localhost:8080/service/send");
List<NameValuePair> formparams = new ArrayList<NameValuePair>();
formparams.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));
// 构建UrlEncode表单实体
UrlEncodedFormEntity entity = new UrlEncodedFormEntity(formparams, Consts.UTF_8);
httppost.setEntity(entity);
// 执行POST请求
CloseableHttpResponse response = httpclient.execute(httpPost);
}
application/json 传送数据
public static void main(String[] args) throws IOException {
// 构建POST请求
HttpPost httpPost = new HttpPost("http://localhost:8080/service/send");
// 如果是JSON字符串 , 构建一个String实体
String paramJson = "{\"name\":\"zhangsan\",\"age\":\"12\"}";
StringEntity jsonEntity = new StringEntity(paramJson,ContentType.create("application/json","utf-8"));
httppost.setEntity(jsonEntity);
// 执行POST请求
CloseableHttpResponse response = httpclient.execute(httpPost);
}