HttpUtils
package com.seliote.stockanalyzer.util;
import com.seliote.stockanalyzer.exc.http.HttpException;
import org.springframework.util.Assert;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.nio.charset.Charset;
import java.util.List;
import java.util.Map;
import java.util.zip.GZIPInputStream;
/**
* HTTP 相关工具类
*
* @author LiYangDi
* @since 2020/2/22
*/
public class HttpUtils {
// HTTP GET 方法常量
private static final String HTTP_GET = "GET";
// 连接超时
private static final int CONNECT_TIMEOUT = 5000;
// 读取超时
private static final int READ_TIMEOUT = 5000;
// HTTP ACCEPT 常量
private static final String ACCEPT_KEY = "Accept";
// Accept 信息
private static final String ACCEPT_VALUE = "text/html,application/xhtml+xml,application/xml;q=0.9," +
"image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9";
// HTTP ACCEPT_ENCODING 常量
private static final String ACCEPT_ENCODING_KEY = "Accept-Encoding";
// ACCEPT_ENCODING 信息
private static final String ACCEPT_ENCODING_VALUE = "gzip, deflate, br";
// HTTP ACCEPT_LANGUAGE 常量
private static final String ACCEPT_LANGUAGE_KEY = "Accept-Language";
// ACCEPT_LANGUAGE 信息
private static final String ACCEPT_LANGUAGE_VALUE = "zh-CN,zh;q=0.9,en;q=0.8";
// HTTP CONNECTION 常量
private static final String CONNECTION_KEY = "Connection";
// CONNECTION 信息
private static final String CONNECTION_VALUE = "keep-alive";
// HTTP USER-AGENT 常量
private static final String USER_AGENT_KEY = "User-Agent";
// USER-AGENT 信息
private static final String USER_AGENT_VALUE = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) " +
"AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.116 Safari/537.36";
// 响应中的 content-encoding 键
private static final String RESP_CONTENT_ENCODING_KEY = "content-encoding";
/**
* HTTP GET 方法请求 URL 编码后的响应 byte[]
*
* @param url 需要请求的 URL,GET 参数加在链接后
* @return 请求接口后返回数据的 byte[]
* @throws HttpException URL 编码、HTTP 请求中产生异常
*/
public static byte[] getByBytes(String url) throws HttpException {
HttpURLConnection httpURLConnection = null;
try {
// encode URL 并创建连接
httpURLConnection = (HttpURLConnection) ((new URL(url)).openConnection());
httpURLConnection.setRequestMethod(HTTP_GET);
// 配置超时与请求头
setProperties(httpURLConnection);
// 设置写入与输出
httpURLConnection.setDoOutput(true);
// 开始请求
httpURLConnection.connect();
// 处理响应
if (HttpURLConnection.HTTP_OK == httpURLConnection.getResponseCode()) {
return readResp(httpURLConnection);
} else {
throw new HttpException("HTTP response code exception:" + httpURLConnection.getResponseCode());
}
} catch (MalformedURLException exc) {
throw new HttpException("MalformedURLException: " + url + ", " + exc.getMessage(), exc);
} catch (IOException exc) {
throw new HttpException("IOException, URL: " + url + ", " + exc.getMessage(), exc);
} finally {
if (null != httpURLConnection) {
httpURLConnection.disconnect();
}
}
}
/**
* HTTP GET 方法请求 URL 编码后的响应 String
*
* @param url 需要请求的 URL,GET 参数加在链接后
* @param charset URL 编码以及解析响应时所用的字符集
* @return 请求接口后返回数据的 String
* @throws HttpException URL 编码、HTTP 请求中产生异常
*/
public static String getByString(String url, Charset charset) throws HttpException {
return new String(getByBytes(url), charset);
}
/**
* 设置 HttpURLConnection 超时与请求头参数
*
* @param httpURLConnection 需要设置的 HttpURLConnection 对象
*/
private static void setProperties(HttpURLConnection httpURLConnection) {
// 超时相关
httpURLConnection.setConnectTimeout(CONNECT_TIMEOUT);
httpURLConnection.setReadTimeout(READ_TIMEOUT);
// 请求头相关
httpURLConnection.setRequestProperty(ACCEPT_KEY, ACCEPT_VALUE);
httpURLConnection.setRequestProperty(ACCEPT_ENCODING_KEY, ACCEPT_ENCODING_VALUE);
httpURLConnection.setRequestProperty(ACCEPT_LANGUAGE_KEY, ACCEPT_LANGUAGE_VALUE);
httpURLConnection.setRequestProperty(CONNECTION_KEY, CONNECTION_VALUE);
httpURLConnection.setRequestProperty(USER_AGENT_KEY, USER_AGENT_VALUE);
}
/**
* 读取 HTTP 响应
*
* @param httpURLConnection 读取响应的 HttpURLConnection 对象
* @return 读取的 byte[]
* @throws IOException 读取响应时发生异常
*/
private static byte[] readResp(HttpURLConnection httpURLConnection) throws IOException {
// 响应头,用来检测是否有压缩
Map<String, List<String>> respHeader = httpURLConnection.getHeaderFields();
String compressMethod = null;
// 循环 Map 以获得大小写无关的比较
for (Map.Entry<String, List<String>> entry : respHeader.entrySet()) {
if (null != entry.getKey() && entry.getKey().equalsIgnoreCase(RESP_CONTENT_ENCODING_KEY)) {
Assert.isTrue(null != entry.getValue() && 1 == entry.getValue().size(),
"HTTP response header 'content-encoding' value is empty or more than one");
compressMethod = entry.getValue().get(0);
break;
}
}
return uncompressInputStream(compressMethod, httpURLConnection.getInputStream());
}
/**
* 解压 InputStream
*
* @param compressMethod 压缩方法
* @param inputStream 需要读取的 InputStream
* @return 解压缩后的 byte[]
* @throws IOException 读取时发生异常
*/
private static byte[] uncompressInputStream(String compressMethod, InputStream inputStream) throws IOException {
if (null == compressMethod) {
return IOUtils.readInputStream(inputStream);
} else if ("gzip".equalsIgnoreCase(compressMethod)) {
GZIPInputStream gzipInputStream = new GZIPInputStream(inputStream);
return IOUtils.readInputStream(gzipInputStream);
} else {
throw new IOException("Response had unknown 'content-encoding': " + compressMethod);
}
}
}
IOUtils
package com.seliote.stockanalyzer.util;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
/**
* IO 相关工具类
*
* @author LiYangDi
* @since 2020/2/23
*/
public class IOUtils {
/**
* 读取 InputStream 中的所有 byte[] 数据,内存中保存,不适合大量数据
*
* @param inputStream 输入的流
* @return 流中的 byte[] 数据
*/
public static byte[] readInputStream(InputStream inputStream) throws IOException {
// 缓存
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
int readLength;
byte[] readBuffer = new byte[1024];
// 读取数据
while ((readLength = inputStream.read(readBuffer)) != -1) {
byteArrayOutputStream.write(readBuffer, 0, readLength);
}
return byteArrayOutputStream.toByteArray();
}
}
原文地址:https://www.cnblogs.com/seliote/p/12353146.html
时间: 2024-10-28 13:54:03