HttpClient 用法详细介绍
一、简介
超文本传输协议(HTTP)可能是当今Internet上使用的最重要的协议。Web服务,具有网络功能的设备以及网络计算的增长继续将HTTP协议的作用扩展到用户驱动的Web浏览器之外,同时增加了需要HTTP支持的应用程序的数量。尽管java.net 软件包提供了用于通过HTTP访问资源的基本功能,但它并未提供许多应用程序所需的全部灵活性或功能。Jakarta Commons HttpClient 组件试图通过提供高效,最新且功能丰富的程序包来实现此空白,以实现最新HTTP标准和建议的客户端。
Commons HttpClient项目现已停产,并且不再开发。它已被其HttpClient和HttpCore模块中的Apache HttpComponents项目取代。
二、项目搭建
tips:本项目案例是基于SpringBoot+SpringDataJPA环境搭建的
2.1 导入依赖:
<dependencies>
<!-- web场景 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- jpa场景 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<!-- mysql驱动 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.18</version>
</dependency>
<!-- 单元测试 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!-- HttpClient的依赖(httpmime依赖包含了httpclient以及httpcore) -->
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpmime</artifactId>
</dependency>
<!-- 早期引入如下两个依赖 -->
<!-- <dependency> <groupId>org.apache.httpcomponents</groupId> <artifactId>httpcore</artifactId> </dependency> <dependency> <groupId>org.apache.httpcomponents</groupId> <artifactId>httpclient</artifactId> </dependency> -->
<!-- 文件上传下载 -->
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.3.3</version>
</dependency>
</dependencies>
2.2 application.properties:
server.port=8080
# 数据源配置
spring.datasource.username=root
spring.datasource.password=admin
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/test?serverTimezone=GMT%2b8
# jpa配置
spring.jpa.show-sql=true
spring.jpa.database=mysql
2.3 实体类:
@Entity
@Table(name = "user")
public class User implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
@Column
private String username;
@Column
private Date birthday;
@Column
private String pic;
// 省略get/set....
}
2.4 dao:
public interface UserDao extends JpaRepository<User,Integer> {
}
2.5 controller:
@RestController
@RequestMapping("/user")
public class UserController {
@Autowired
private UserDao userDao;
/** * 添加用户 * @param user * @return * @throws Exception */
@PostMapping
public Map save(@RequestBody User user) throws Exception {
user.setBirthday(new Date());
userDao.save(user);
Map returnMap = new HashMap<>();
returnMap.put("message", "添加成功");
return returnMap;
}
/** * 删除用户 * @param id * @return */
@DeleteMapping("/{id}")
public Map delete(@PathVariable Integer id) {
userDao.deleteById(id);
Map returnMap = new HashMap<>();
returnMap.put("message", "删除成功");
return returnMap;
}
/** * 修改用户 * @param id * @param user * @return */
@PutMapping("/{id}")
public Map update(@PathVariable Integer id, @RequestBody User user) {
user.setId(id);
userDao.save(user);
Map returnMap = new HashMap<>();
returnMap.put("message", "修改成功");
return returnMap;
}
/** * 根据id查询用户 * @param id * @return */
@GetMapping("/{id}")
public User findById(@PathVariable Integer id) {
return userDao.findById(id).get();
}
/** * 查询全部用户 * @return */
@GetMapping
public List<User> findAll() {
return userDao.findAll();
}
/** * 上传头像 * * @param pic * @param username * @return * @throws Exception */
@PostMapping("/upload")
// 如果上传了多个文件使用:List<MultipartFile> pic
public Map upload(MultipartFile pic, String username) throws Exception {
pic.transferTo(new File("D:\\", UUID.randomUUID().toString() + ".png"));
Map returnMap = new HashMap<>();
returnMap.put("message", "上传成功");
returnMap.put("data", username);
return returnMap;
}
}
2.6 启动类:
@SpringBootApplication
public class HttpclientApplication {
public static void main(String[] args) {
SpringApplication.run(HttpclientApplication.class, args);
}
}
数据库脚本如下:
CREATE TABLE `user` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`username` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
`birthday` datetime(0) NULL DEFAULT NULL,
`pic` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
本人已亲测,controller所有接口均可用。大家可以跟我一样,先把环境搭建好
三、HttpClient快速入门
3.1 Get 请求
3.1.1 普通Get请求
@Test
public void test1() throws Exception{
// 获取HttpClient实例
CloseableHttpClient httpClient = HttpClients.createDefault();
// 创建一个HttpGet请求
HttpGet httpGet = new HttpGet("http://localhost:8080/user");
// 发送请求,获取响应结果
CloseableHttpResponse response = httpClient.execute(httpGet);
// 获取响应实体
HttpEntity responseEntity = response.getEntity();
System.out.println("响应状态: " + response.getStatusLine());
if (responseEntity != null) {
System.out.println("响应内容长度为:" + responseEntity.getContentLength());
System.out.println("响应内容为:" + EntityUtils.toString(responseEntity));
}
}
3.1.2 Get请求带参数
请求代码:
@Test
public void test2() throws Exception {// 获取HttpClient实例
CloseableHttpClient httpClient = HttpClients.createDefault();
// 请求参数
StringBuilder params = new StringBuilder();
params.append("?");
// 字符数据最好encoding一下;这样一来,某些特殊字符才能传过去(如:username就是"&",不encoding的话,解析时,会认为要拼接下一个参数username就为空)
params.append("username=" + URLEncoder.encode("admin", "UTF8"));
HttpGet httpGet = new HttpGet("http://localhost:8080/user/testGet" + params);
// 发送请求,获取响应结果
CloseableHttpResponse response = httpClient.execute(httpGet);
// 获取响应实体
HttpEntity responseEntity = response.getEntity();
System.out.println("响应状态: " + response.getStatusLine());
if (responseEntity != null) {
System.out.println("响应内容长度为:" + responseEntity.getContentLength());
System.out.println("响应内容为:" + EntityUtils.toString(responseEntity));
}
}
新增接口:
@GetMapping(“/testGet”)
public Map testGet(String username) throws Exception{Map returnMap = new HashMap<>();
returnMap.put("message", "请求成功");
returnMap.put("data", username);
return returnMap;
}
3.1.3 GET请求使用URI方式
使用URIBuilder()来构建一个uri对象用于传递参数使用。
URIBuilder()中有如下方法
setParameters(List<NameValuePair> params)
:用于构建多个键值对,使用List,单个NameValuePair用于封装一个键值对setParameter(String key,String val)
:自己手动添加键值对// GET请求(使用URI获取HttpGet)
@Test
public void test3() throws Exception {// 获取HttpClient实例
CloseableHttpClient httpClient = HttpClients.createDefault();
// 将参数放入键值对类NameValuePair中,再放入集合中
List<NameValuePair> params = new ArrayList<>();
params.add(new BasicNameValuePair("username", "admin"));
// 设置uri信息,并将参数集合放入uri;
// 注:这里也支持一个键值对一个键值对地往里面放setParameter(String key, String value)
URI uri = new URIBuilder().setScheme("http").setHost("localhost")
.setPort(8080).setPath("/user/testGet")
.setParameters(params).build();
HttpGet httpGet = new HttpGet(uri);
print(httpClient, httpGet);
}
3.1.4 抽取打印方法
/** * 抽取打印方法 * * @param httpClient * @param http * @throws Exception */
private void print(CloseableHttpClient httpClient, HttpRequestBase http) throws Exception {
// 发送请求,获取响应结果
CloseableHttpResponse response = httpClient.execute(http);
// 获取响应实体
HttpEntity responseEntity = response.getEntity();
System.out.println("响应状态: " + response.getStatusLine());
if (responseEntity != null) {
System.out.println("响应内容长度为:" + responseEntity.getContentLength());
// 设置响应内容的编码(默认为UTF8)
System.out.println("响应内容为:" + EntityUtils.toString(responseEntity, "UTF8"));
}
response.close();
httpClient.close();
}
3.2 Post请求
3.2.1 普通Post请求
请求代码:
@Test
public void test4() throws Exception {// 获取HttpClient实例
CloseableHttpClient httpClient = HttpClients.createDefault();
HttpPost httpPost = new HttpPost("http://localhost:8080/user/testPost");
print(httpClient, httpPost);
}
请求接口:
@PostMapping(“/testPost”)
public Map testPost() throws Exception {Map returnMap = new HashMap<>();
returnMap.put("message", "普通方式post请求成功");
return returnMap;
}
3.2.2 Post请求带参数
请求代码:
@Test
public void test5() throws Exception {// 获取HttpClient实例
CloseableHttpClient httpClient = HttpClients.createDefault();
HttpPost httpPost = new HttpPost("http://localhost:8080/user/testPost?username=admin");
print(httpClient, httpPost);
}
新增接口
@PostMapping(“/testPost2”)
public Map testPost2(String username) throws Exception {Map returnMap = new HashMap<>();
returnMap.put("message", "普通方式post请求成功");
returnMap.put("data", username);
return returnMap;
}
3.2.3 Post请求提交对象
@Test
public void test6() throws Exception {
// 获取HttpClient实例
CloseableHttpClient httpClient = HttpClients.createDefault();
User user=new User();
user.setUsername("王五");
// json转换工具
ObjectMapper om = new ObjectMapper();
StringEntity entity = new StringEntity(om.writeValueAsString(user), "utf-8");
HttpPost httpPost = new HttpPost("http://localhost:8080/user");
// post请求是将参数放在请求体里面传过去的;这里将entity放入post请求体中
httpPost.setEntity(entity);
// 设置请求头
httpPost.setHeader("Content-Type", "application/json;charset=utf8");
httpClient.execute(httpPost);
print(httpClient, httpPost);
}
3.2.4 Post请求对象+参数
请求代码:
@Test
public void test7() throws Exception {// 获取HttpClient实例
CloseableHttpClient httpClient = HttpClients.createDefault();
User user=new User();
user.setUsername("赵六");
// json转换工具
ObjectMapper om = new ObjectMapper();
StringEntity entity = new StringEntity(om.writeValueAsString(user), "utf-8");
// 构建uri
URI uri = new URIBuilder().setScheme("http").setHost("localhost")
.setPort(8080).setPath("/user/testPost")
.setParameter("flag", "测试post请求带参哦!") //使用setParameter设置单个参数
.build();
HttpPost httpPost = new HttpPost(uri);
// post请求是将参数放在请求体里面传过去的;这里将entity放入post请求体中
httpPost.setEntity(entity);
// 设置请求头
httpPost.setHeader("Content-Type", "application/json;charset=utf8");
httpClient.execute(httpPost);
print(httpClient, httpPost);
}
新增接口:
@PostMapping(“/testPost3”)
public Map testPost3(@RequestBody User user, String flag) throws Exception {user.setBirthday(new Date());
userDao.save(user);
Map returnMap = new HashMap<>();
returnMap.put("message", "请求testPost3成功");
returnMap.put("data", flag);
return returnMap;
}
3.3 Put请求
@Test
public void test8() throws Exception {
// 获取HttpClient实例
CloseableHttpClient httpClient = HttpClients.createDefault();
User user=new User();
user.setUsername("管理员");
ObjectMapper om=new ObjectMapper();
String userStr = om.writeValueAsString(user);
// 构建实体
StringEntity entity = new StringEntity(userStr, StandardCharsets.UTF_8);
HttpPut httpPut = new HttpPut("http://localhost:8080/user/12");
// 设置请求头
httpPut.setHeader("Content-Type", "application/json;charset=utf8");
httpPut.setEntity(entity);
httpClient.execute(httpPut);
print(httpClient,httpPut);
}
3.4 Delete请求
@Test
public void test9() throws Exception {
// 获取HttpClient实例
CloseableHttpClient httpClient = HttpClients.createDefault();
HttpDelete httpDelete = new HttpDelete("http://localhost:8080/user/12");
httpClient.execute(httpDelete);
print(httpClient,httpDelete);
}
四、特殊类型请求
4.1 模拟表单提交
4.1.1 请求代码:
@Test
public void test10() throws Exception {// 获取HttpClient实例
CloseableHttpClient httpClient = HttpClients.createDefault();
HttpPost httpPost = new HttpPost("http://localhost:8080/user/testForm");
// 设置请求头
httpPost.setHeader("Content-Type", "application/x-www-form-urlencoded");
List<BasicNameValuePair> params = new ArrayList<>();
params.add(new BasicNameValuePair("id","100"));
params.add(new BasicNameValuePair("username","张三"));
// 这里不要传递birthday,后台需要定义converter,做类型转换(String->Date),你们有兴趣自己去玩,也不难
// params.add(new BasicNameValuePair(“birthday”,new SimpleDateFormat(“yyyy-MM-dd”).format(new Date())));
params.add(new BasicNameValuePair("pic","https://www.baidu.com/favicon.ico"));
// 构建一个虚拟表单,并设置参数
UrlEncodedFormEntity entity = new UrlEncodedFormEntity(params,StandardCharsets.UTF_8);
// 设置请求实体
httpPost.setEntity(entity);
// 发送请求
httpClient.execute(httpPost);
print(httpClient, httpPost);
}
4.1.2 新增接口:
/* 测试表单传输 @param user @return @throws Exception /
@PostMapping(“/testForm”)
public Map testPost3(User user) throws Exception {Map returnMap = new HashMap<>();
returnMap.put("message", "请求testForm成功");
returnMap.put("data", user);
return returnMap;
}
4.2 上传文件
注:
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpmime</artifactId>
</dependency>
@Test
public void test11() throws Exception {
// 获取HttpClient实例
CloseableHttpClient httpClient = HttpClients.createDefault();
MultipartEntityBuilder multipartEntityBuilder = MultipartEntityBuilder.create();
// 可以添加多个图片(name保持一致就行,后台使用List<MultipartFile> pic接收)
// multipartEntityBuilder.addBinaryBody("pic",new File("D:\\10.png"));
multipartEntityBuilder.addBinaryBody("pic",new File("D:\\11.png"));
// 携带文本参数
multipartEntityBuilder.addTextBody("username","管理员", ContentType.create("text/plain",StandardCharsets.UTF_8));
// 装换为HttpEntity
HttpEntity entity = multipartEntityBuilder.build();
HttpPost httpPost = new HttpPost("http://localhost:8080/user/upload");
httpPost.setEntity(entity);
print(httpClient,httpPost);
}
4.3 传递数据流
4.3.1 请求代码:
// 发送数据流
@Test
public void test12() throws Exception {// 获取HttpClient实例
CloseableHttpClient httpClient = HttpClients.createDefault();
InputStream is = new ByteArrayInputStream("admin".getBytes());
// 构建数据流实体
InputStreamEntity entity = new InputStreamEntity(is);
HttpPost httpPost = new HttpPost("http://localhost:8080/user/testStream");
httpPost.setEntity(entity);
// 发送请求
httpClient.execute(httpPost);
print(httpClient,httpPost);
}
4.3.2 新增接口:
/* 测试数据流传输 @param is @return @throws Exception */
@PostMapping(value = “/testStream”)
public Map testStream(InputStream is) throws Exception {// 接受前端传递的数据
String str = new BufferedReader(new InputStreamReader(is)).readLine();
Map returnMap = new HashMap<>();
returnMap.put("message", "testStream");
returnMap.put("data", str);
return returnMap;
}
还没有评论,来说两句吧...