HttpURLConnection Demo

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(); }}

相关文章