HttpClient学习
1. 导入需要的pom文件
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.12</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastJson</artifactId>
<version>1.2.7</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.16</version>
</dependency>
<!--如果需要灵活的传输文件,引入此依赖后会更加方便-->
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpmime</artifactId>
<version>4.5.5</version>
</dependency>
</dependencies>
2.GET请求的测试
2.1 测试代码
package com.wcc;
import org.apache.http.HttpEntity;
import org.apache.http.NameValuePair;
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.utils.URIBuilder;
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 org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
//@SpringBootTest
public class HttpGetTest {
@Test
// get的无参方式
public void getTest001(){
// 创建httpClient客户端(可以理解为在这里创建一个浏览器,来发送请求,但是并不同于浏览器)
CloseableHttpClient httpClient = HttpClientBuilder.create().build();
// 创建get请求
HttpGet httpGet = new HttpGet("http://localhost:20000/getTest01");
// 声明响应模型
CloseableHttpResponse httpResponse = null;
try {
// 客户端发送get请求
httpResponse = httpClient.execute(httpGet);
// 从响应模型中获得具体的实体
HttpEntity entity = httpResponse.getEntity();
System.out.println("响应状态为"+httpResponse.getStatusLine());
if (entity!=null){
System.out.println("响应的内容长度为"+entity.getContentLength());
System.out.println("响应内容为"+ EntityUtils.toString(entity));
}
} catch (IOException e) {
e.printStackTrace();
}
}
@Test
// get的有参方式
public void getTest002(){
//构建httpClient对象
CloseableHttpClient httpClient = HttpClientBuilder.create().build();
// 构建参数
StringBuffer sb =new StringBuffer();
// 字符数据最好encoding以下;这样一来,某些特殊字符才能传过去(如:某人的名字就是“&”,不encoding的话,传不过去)
// sb.append("name="+ URLEncoder.encode("&","utf-8"));
sb.append("name=xiaoliu");
sb.append("&");
sb.append("age=18");
String url = "http://localhost:20000/getTest02?" + sb;
System.out.println("请求的地址为"+url);
HttpGet httpGet = new HttpGet(url);
// 配置信息
RequestConfig requestConfig = RequestConfig.custom()
.setConnectionRequestTimeout(5000) // 设置请求超时时间
.setConnectTimeout(5000) // 设置连接超时时间
.setSocketTimeout(5000) // socket读写超时时间
.setRedirectsEnabled(true)
.build();
// 将上面的配置信息,运用到这个get请求中
httpGet.setConfig(requestConfig);
// 声明响应模型
CloseableHttpResponse httpResponse = null;
try {
// 执行此get请求
httpResponse = httpClient.execute(httpGet);
// 获取响应实体
HttpEntity entity = httpResponse.getEntity();
System.out.println("请求的响应状态为"+httpResponse.getStatusLine());
if (entity != null){
System.out.println("响应的实体长度为"+entity.getContentLength());
System.out.println("响应的内容为"+EntityUtils.toString(entity));
}
} catch (IOException e) {
e.printStackTrace();
}
}
@Test
// get的有参方式二
public void getTest003(){
// 构建httpClient对象
CloseableHttpClient httpClient = HttpClientBuilder.create().build();
// 参数URL
URI uri = null;
// 将参数放入键值对namevaluepair中,再放入集合中
List<NameValuePair> params = new ArrayList<>();
params.add(new BasicNameValuePair("name","wang"));
params.add(new BasicNameValuePair("age","18"));
// 设置uri信息,并将参数集合放入uri;
// 注:这里也支持一个键值对一个键值对地往里面放setParameter(String key, String value)
try {
uri = new URIBuilder().setScheme("http").setHost("localhost").setPort(20000)
.setPath("getTest02").setParameters(params).build();
HttpGet httpGet = new HttpGet(uri);
// 设置配置信息
RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(5000)
.setConnectTimeout(5000).setConnectionRequestTimeout(5000).build();
// 将此配置信息,运用到此请求中
httpGet.setConfig(requestConfig);
try {
// 执行此请求 返回响应对象
CloseableHttpResponse httpResponse = httpClient.execute(httpGet);
// 获取响应实体
HttpEntity entity = httpResponse.getEntity();
System.out.println("响应状态为"+httpResponse.getStatusLine());
if ( entity != null){
System.out.println("响应内容的长度为:"+entity.getContentLength());
System.out.println("响应内容为:"+EntityUtils.toString(entity));
}
} catch (IOException e) {
e.printStackTrace();
}
} catch (URISyntaxException e) {
e.printStackTrace();
}
}
}
2.2 对应的控制层代码
@RestController
public class HttpClentGetTest {
@RequestMapping(value = "getTest01",method = RequestMethod.GET)
public String doGetTest01(){
return "123";
}
@RequestMapping(value = "getTest02",method = RequestMethod.GET)
public String doGetTest02(String name,int age){
return name +"已经"+age+"岁了";
}
}
3.POST请求
3.1 测试代码
package com.wcc;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.sun.org.apache.bcel.internal.generic.NEW;
import com.wcc.pojo.User;
import org.apache.http.HttpEntity;
import org.apache.http.NameValuePair;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.entity.StringEntity;
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 org.junit.jupiter.api.Test;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
public class HttpPostTest {
@Test
// 无参的post请求
public void postTest01(){
// 构建httpClient客户端
CloseableHttpClient httpClient = HttpClientBuilder.create().build();
// 创建httppost请求
HttpPost httpPost = new HttpPost("http://localhost:20000/postTest001");
try {
// 执行此请求
CloseableHttpResponse httpResponse = httpClient.execute(httpPost);
// 获取响应实体
HttpEntity entity = httpResponse.getEntity();
System.out.println("响应的状态为:"+httpResponse.getStatusLine());
if (entity != null){
System.out.println("响应的内容长度:"+entity.getContentLength());
System.out.println("响应的内容为"+ EntityUtils.toString(entity));
}
} catch (IOException e) {
e.printStackTrace();
}
}
@Test
// 有参的post请求方式
public void postTest002(){
// 获取httpClient对象
CloseableHttpClient httpClient = HttpClientBuilder.create().build();
// 构建参数
StringBuffer params = new StringBuffer();
params.append("name=xiaoliu").append("&").append("doing=昨晚腰疼");
HttpPost httpPost = new HttpPost("http://localhost:20000/postTest002?" + params);
try {
// 设置ContentType(注:如果只是传普通参数的话,ContentType不一定非要用application/json)
httpPost.setHeader("Content-Type","application/json;charset=utf-8");
// 执行httpPost请求
CloseableHttpResponse httpResponse = httpClient.execute(httpPost);
// 获取实体
HttpEntity entity = httpResponse.getEntity();
System.out.println("响应状态为"+httpResponse.getStatusLine());
if ( entity!=null ){
System.out.println("响应内容长度为"+entity.getContentLength());
System.out.println("响应的内容为"+EntityUtils.toString(entity));
}
} catch (IOException e) {
e.printStackTrace();
}
}
@Test
// 有参的post请求 构建参数的第二种方式
public void postTest003(){
// 获取客户端
CloseableHttpClient httpClient = HttpClientBuilder.create().build();
// 构建参数
List<NameValuePair> params = new ArrayList<>();
params.add(new BasicNameValuePair("name","小王"));
params.add(new BasicNameValuePair("doing","xuexi"));
try {
// 构建URI
URI uri = new URIBuilder().setScheme("http").setHost("localhost").setPort(20000).setPath("postTest002")
.setParameters(params).build();
// 构建post请求
HttpPost httpPost = new HttpPost(uri);
// 发送请求
CloseableHttpResponse httpResponse = httpClient.execute(httpPost);
System.out.println("响应状态为:"+httpResponse.getStatusLine());
HttpEntity entity = httpResponse.getEntity();
if ( entity!= null){
System.out.println("响应内容长度为:"+entity.getContentLength());
System.out.println("我告诉你一个秘密:"+EntityUtils.toString(entity));
}
} catch (URISyntaxException | IOException e) {
e.printStackTrace();
}
}
// post请求参数为一个对象时
@Test
public void testPost004(){
// 构建httpClient对象
CloseableHttpClient httpClient = HttpClientBuilder.create().build();
// 构建参数
User user = new User().setId(1).setName("小刘").setAge(18);
String jsonString = JSON.toJSONString(user);
StringEntity stringEntity = new StringEntity(jsonString, "utf-8");
// 构建post请求
HttpPost httpPost = new HttpPost("http://localhost:20000/postTest003");
httpPost.setEntity(stringEntity);
httpPost.setHeader("Content-Type","application/json;charset=utf-8");
try {
// 执行post请求
CloseableHttpResponse httpResponse = httpClient.execute(httpPost);
HttpEntity entity = httpResponse.getEntity();
System.out.println("详情:"+EntityUtils.toString(entity));
} catch (IOException e) {
e.printStackTrace();
}
}
// 普通参数和对象参数
@Test
public void postTest005(){
CloseableHttpClient httpClient = HttpClientBuilder.create().build();
List<NameValuePair> params = new ArrayList<>();
params.add(new BasicNameValuePair("name","xiaoliu"));
try {
URI uri = new URIBuilder().setScheme("http").setHost("localhost").setPort(20000).
setPath("postTest004").setParameters(params).build();
User user = new User().setName("xiaoliu");
HttpPost httpPost = new HttpPost(uri);
httpPost.setEntity(new StringEntity(JSON.toJSONString(user),"utf-8"));
// 如果请求参数为对象。必须设置这个json传参
httpPost.setHeader("Content-Type","application/json;charset=utf-8");
CloseableHttpResponse httpResponse = httpClient.execute(httpPost);
System.out.println("响应状态为:"+httpResponse.getStatusLine());
HttpEntity entity = httpResponse.getEntity();
if ( entity!=null ){
// 防止乱码,解决方式
System.out.println("响应内容为"+EntityUtils.toString(entity, StandardCharsets.UTF_8));
}
} catch (URISyntaxException e) {
e.printStackTrace();
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
3.2 对应的控制层代码
@RestController
public class HttpClientPostTest {
@PostMapping(value = "postTest001")
public String postTest001(){
return "无参的post请求";
}
@PostMapping(value = "postTest002")
public String postTest002(String name,String doing){
return name+doing;
}
@PostMapping(value = "postTest003")
public String postTest003(@RequestBody User user){
if (user.getName().equalsIgnoreCase("xiaoliu")){
return "lovely";
}
return "笨";
}
@PostMapping(value = "postTest004")
public String postTest004(String name,@RequestBody User user){
if (name.equalsIgnoreCase(user.getName())){
return "benbenbenben";
}
return "congming";
}
}
3.3 对应的实体类
@Data
@AllArgsConstructor
@NoArgsConstructor
@Accessors(chain = true)
public class User {
private int id;
private String name;
private int age;
}
4.Http上传文件
4.1 测试代码
public class FileTest {
// 上传文件对应的测试
@Test
public void fileTest() throws IOException {
CloseableHttpClient httpClient = HttpClientBuilder.create().build();
HttpPost httpPost = new HttpPost("http://localhost:20000/file");
MultipartEntityBuilder multipartEntityBuilder = MultipartEntityBuilder.create();
// 第一个文件
String fileKey = "files";
File file1 = new File("D:\\360Downloads\\111.jpg");
multipartEntityBuilder.addBinaryBody(fileKey,file1);
// 第二个文件(多个文件的话,使用同一个key就行,后端用数组或者集合接受即可)
File file2 = new File("D:\\360Downloads\\timg.png");
// 防止服务端收到的文件名乱码。 我们这里可以先将文件名URLEncode,然后服务端拿到文件名时在URLDecode。就能避免乱码问题。
// 文件名其实是放在请求头的Content-Disposition里面进行传输的,如其值为form-data; name="files"; filename=timg.png"
multipartEntityBuilder.addBinaryBody(fileKey,file2, ContentType.DEFAULT_BINARY, URLEncoder.encode(file2.getName(),"utf-8"));
// 其他参数
multipartEntityBuilder.addTextBody("name","xiaowang",ContentType.DEFAULT_TEXT);
multipartEntityBuilder.addTextBody("age","18",ContentType.DEFAULT_TEXT);
HttpEntity httpEntity = multipartEntityBuilder.build();
httpPost.setEntity(httpEntity);
// 执行
CloseableHttpResponse httpResponse = httpClient.execute(httpPost);
System.out.println("响应的状态为:"+httpResponse.getStatusLine());
HttpEntity entity = httpResponse.getEntity();
if ( entity!=null ){
System.out.println("响应内容为:"+ EntityUtils.toString(entity));
}
}
}
4.2 controller层代码
@RestController
public class FileController {
@PostMapping(value = "file")
public String fileTest001(@RequestParam("name")String name,
@RequestParam("age") int age,
@RequestParam("files")MultipartFile[] multipartFiles) throws IOException {
if (multipartFiles.length>0){
for (MultipartFile multipartFile : multipartFiles) {
InputStream inputStream = multipartFile.getInputStream();
IOUtils.copy(inputStream,new FileOutputStream(new File(multipartFile.getOriginalFilename())));
return "success";
}
}
return "nonononon";
}
}
5.Http发送流的测试
5.1 测试代码
public class StreamTest {
// 发送流测试
@Test
public void streamTest() throws IOException {
CloseableHttpClient httpClient = HttpClientBuilder.create().build();
HttpPost httpPost = new HttpPost("http://localhost:20000/stream?name=xiowangshuo");
InputStream inputStream = new ByteArrayInputStream("nihaoya,xiaoliu".getBytes());
InputStreamEntity streamEntity = new InputStreamEntity(inputStream);
httpPost.setEntity(streamEntity);
CloseableHttpResponse httpResponse = httpClient.execute(httpPost);
HttpEntity entity = httpResponse.getEntity();
if ( entity!=null ){
System.out.println("响应内容为:"+ EntityUtils.toString(entity));
}
}
}
5.2controller层代码
@RestController
public class StreamController {
@PostMapping(value = "stream")
public String streamTest(@RequestParam("name") String name, InputStream inputStream) throws IOException {
StringBuffer sb = new StringBuffer();
sb.append("name的值为").append(name);
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
String line;
while ( (line=reader.readLine())!= null){
sb.append(line);
}
return sb.toString();
}
}
6.Https测试
package com.wcc;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;
import javax.net.ssl.X509TrustManager;
import java.io.IOException;
import java.io.InputStream;
import java.security.*;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.util.Arrays;
public class HttpsTest {
/**
* 根据是否是https请求,获取HttpClient客户端
* 提示: 此工具类的封装、相关客户端、服务端证书的生成,可参考这篇博客:
* <linked>https://blog.csdn.net/justry_deng/article/details/91569132</linked>
* @param isHttps 是否是HTTPS请求
* @return HttpClient实例
* @date 2019/9/18 17:57
*/
private CloseableHttpClient getHttpClient(boolean isHttps) {
CloseableHttpClient httpClient;
if (isHttps) {
SSLConnectionSocketFactory sslSocketFactory;
try {
/// 如果不作证书校验的话
sslSocketFactory = getSocketFactory(false, null, null);
/// 如果需要证书检验的话
// 证书
//InputStream ca = this.getClass().getClassLoader().getResourceAsStream("client/ds.crt");
// 证书的别名,即:key。 注:cAalias只需要保证唯一即可,不过推荐使用生成keystore时使用的别名。
// String cAalias = System.currentTimeMillis() + "" + new SecureRandom().nextInt(1000);
//sslSocketFactory = getSocketFactory(true, ca, cAalias);
} catch (Exception e) {
throw new RuntimeException(e);
}
httpClient = HttpClientBuilder.create().setSSLSocketFactory(sslSocketFactory).build();
return httpClient;
}
httpClient = HttpClientBuilder.create().build();
return httpClient;
}
/**
* HTTPS辅助方法, 为HTTPS请求 创建SSLSocketFactory实例、TrustManager实例
*
* @param needVerifyCa
* 是否需要检验CA证书(即:是否需要检验服务器的身份)
* @param caInputStream
* CA证书。(若不需要检验证书,那么此处传null即可)
* @param cAalias
* 别名。(若不需要检验证书,那么此处传null即可)
* 注意:别名应该是唯一的, 别名不要和其他的别名一样,否者会覆盖之前的相同别名的证书信息。别名即key-value中的key。
*
* @return SSLConnectionSocketFactory实例
* @throws NoSuchAlgorithmException
* 异常信息
* @throws CertificateException
* 异常信息
* @throws KeyStoreException
* 异常信息
* @throws IOException
* 异常信息
* @throws KeyManagementException
* 异常信息
* @date 2019/6/11 19:52
*/
private static SSLConnectionSocketFactory getSocketFactory(boolean needVerifyCa, InputStream caInputStream, String cAalias)
throws CertificateException, NoSuchAlgorithmException, KeyStoreException,
IOException, KeyManagementException {
X509TrustManager x509TrustManager;
// https请求,需要校验证书
if (needVerifyCa) {
KeyStore keyStore = getKeyStore(caInputStream, cAalias);
TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
trustManagerFactory.init(keyStore);
TrustManager[] trustManagers = trustManagerFactory.getTrustManagers();
if (trustManagers.length != 1 || !(trustManagers[0] instanceof X509TrustManager)) {
throw new IllegalStateException("Unexpected default trust managers:" + Arrays.toString(trustManagers));
}
x509TrustManager = (X509TrustManager) trustManagers[0];
// 这里传TLS或SSL其实都可以的
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, new TrustManager[]{x509TrustManager}, new SecureRandom());
return new SSLConnectionSocketFactory(sslContext);
}
// https请求,不作证书校验
x509TrustManager = new X509TrustManager() {
@Override
public void checkClientTrusted(X509Certificate[] arg0, String arg1) {
}
@Override
public void checkServerTrusted(X509Certificate[] arg0, String arg1) {
// 不验证
}
@Override
public X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[0];
}
};
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, new TrustManager[]{x509TrustManager}, new SecureRandom());
return new SSLConnectionSocketFactory(sslContext);
}
/**
* 获取(密钥及证书)仓库
* 注:该仓库用于存放 密钥以及证书
*
* @param caInputStream
* CA证书(此证书应由要访问的服务端提供)
* @param cAalias
* 别名
* 注意:别名应该是唯一的, 别名不要和其他的别名一样,否者会覆盖之前的相同别名的证书信息。别名即key-value中的key。
* @return 密钥、证书 仓库
* @throws KeyStoreException 异常信息
* @throws CertificateException 异常信息
* @throws IOException 异常信息
* @throws NoSuchAlgorithmException 异常信息
* @date 2019/6/11 18:48
*/
private static KeyStore getKeyStore(InputStream caInputStream, String cAalias)
throws KeyStoreException, CertificateException, IOException, NoSuchAlgorithmException {
// 证书工厂
CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
// 秘钥仓库
KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
keyStore.load(null);
keyStore.setCertificateEntry(cAalias, certificateFactory.generateCertificate(caInputStream));
return keyStore;
}
}
Http封装好的工具类 github地址:https://github.com/Arronlong/httpclientutil
版权声明:本文为weixin_45785893原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。