|
@@ -0,0 +1,463 @@
|
|
|
|
|
+package com.zswl.dataservice.utils.net;
|
|
|
|
|
+
|
|
|
|
|
+import lombok.SneakyThrows;
|
|
|
|
|
+
|
|
|
|
|
+import javax.net.ssl.*;
|
|
|
|
|
+import java.io.*;
|
|
|
|
|
+import java.net.*;
|
|
|
|
|
+import java.security.SecureRandom;
|
|
|
|
|
+import java.security.cert.CertificateException;
|
|
|
|
|
+import java.security.cert.X509Certificate;
|
|
|
|
|
+import java.util.HashMap;
|
|
|
|
|
+import java.util.List;
|
|
|
|
|
+import java.util.Map;
|
|
|
|
|
+
|
|
|
|
|
+/**
|
|
|
|
|
+ *
|
|
|
|
|
+ * Http client
|
|
|
|
|
+ *
|
|
|
|
|
+ * @作者:练书锋 @日期:2013年10月22日
|
|
|
|
|
+ *
|
|
|
|
|
+ */
|
|
|
|
|
+public class HttpClient {
|
|
|
|
|
+
|
|
|
|
|
+ static {
|
|
|
|
|
+ init();
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ @SneakyThrows
|
|
|
|
|
+ private static void init(){
|
|
|
|
|
+ SSLContext sslcontext = SSLContext.getInstance("SSL", "SunJSSE");//第一个参数为协议,第二个参数为提供者(可以缺省)
|
|
|
|
|
+ TrustManager[] tm = {new X509TrustManager(){
|
|
|
|
|
+
|
|
|
|
|
+ @Override
|
|
|
|
|
+ public void checkClientTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {
|
|
|
|
|
+
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ @Override
|
|
|
|
|
+ public void checkServerTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {
|
|
|
|
|
+
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ @Override
|
|
|
|
|
+ public X509Certificate[] getAcceptedIssuers() {
|
|
|
|
|
+ return new X509Certificate[0];
|
|
|
|
|
+ }
|
|
|
|
|
+ }};
|
|
|
|
|
+ sslcontext.init(null, tm, new SecureRandom());
|
|
|
|
|
+ HostnameVerifier ignoreHostnameVerifier = new HostnameVerifier() {
|
|
|
|
|
+ public boolean verify(String s, SSLSession sslsession) {
|
|
|
|
|
+ System.out.println("WARNING: Hostname is not matched for cert.");
|
|
|
|
|
+ return true;
|
|
|
|
|
+ }
|
|
|
|
|
+ };
|
|
|
|
|
+ HttpsURLConnection.setDefaultHostnameVerifier(ignoreHostnameVerifier);
|
|
|
|
|
+ HttpsURLConnection.setDefaultSSLSocketFactory(sslcontext.getSocketFactory());
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private static final String CHARSET = "charset";
|
|
|
|
|
+
|
|
|
|
|
+ // 连接超时时间
|
|
|
|
|
+ private int connectTimeout = 60000;
|
|
|
|
|
+ // 读取超时时间
|
|
|
|
|
+ private int readTimeout = 60000;
|
|
|
|
|
+ // cookies
|
|
|
|
|
+ private Map<String, String> cookies = new HashMap<String, String>();
|
|
|
|
|
+ // 设置是否自动跳转
|
|
|
|
|
+ private boolean followRedirects = true;
|
|
|
|
|
+
|
|
|
|
|
+ // 监听输出管道
|
|
|
|
|
+ private OutputStream listenOutputStream;
|
|
|
|
|
+
|
|
|
|
|
+ // 代理IP
|
|
|
|
|
+ private String proxyHost;
|
|
|
|
|
+ // 代理端口
|
|
|
|
|
+ private int porxyPort;
|
|
|
|
|
+
|
|
|
|
|
+ public OutputStream getListenOutputStream() {
|
|
|
|
|
+ return listenOutputStream;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ public HttpClient setListenOutputStream(OutputStream listenOutputStream) {
|
|
|
|
|
+ this.listenOutputStream = listenOutputStream;
|
|
|
|
|
+ return this;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ public boolean isFollowRedirects() {
|
|
|
|
|
+ return followRedirects;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ public HttpClient setFollowRedirects(boolean followRedirects) {
|
|
|
|
|
+ this.followRedirects = followRedirects;
|
|
|
|
|
+ return this;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ public Map<String, String> getCookies() {
|
|
|
|
|
+ return cookies;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ public HttpClient setCookies(Map<String, String> cookies) {
|
|
|
|
|
+ this.cookies = cookies;
|
|
|
|
|
+ return this;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ public int getConnectTimeout() {
|
|
|
|
|
+ return connectTimeout;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ public HttpClient setConnectTimeout(int connectTimeout) {
|
|
|
|
|
+ this.connectTimeout = connectTimeout;
|
|
|
|
|
+ return this;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ public int getReadTimeout() {
|
|
|
|
|
+ return readTimeout;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ public void setReadTimeout(int readTimeout) {
|
|
|
|
|
+ this.readTimeout = readTimeout;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ public String getProxyHost() {
|
|
|
|
|
+ return proxyHost;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ public HttpClient setProxyHost(String proxyHost) {
|
|
|
|
|
+ this.proxyHost = proxyHost;
|
|
|
|
|
+ return this;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ public int getPorxyPort() {
|
|
|
|
|
+ return porxyPort;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ public HttpClient setPorxyPort(int porxyPort) {
|
|
|
|
|
+ this.porxyPort = porxyPort;
|
|
|
|
|
+ return this;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 默认的构造方法
|
|
|
|
|
+ */
|
|
|
|
|
+ public HttpClient() {
|
|
|
|
|
+
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 请重写该方法用于显示下载进度
|
|
|
|
|
+ *
|
|
|
|
|
+ * @param currentPoint
|
|
|
|
|
+ * @param totalPoint
|
|
|
|
|
+ */
|
|
|
|
|
+ public void showProgress(long currentPoint, long totalPoint) {
|
|
|
|
|
+
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 使用get方式请求
|
|
|
|
|
+ *
|
|
|
|
|
+ * @param url
|
|
|
|
|
+ * @return
|
|
|
|
|
+ * @throws IOException
|
|
|
|
|
+ */
|
|
|
|
|
+ public byte[] get(final String url) throws IOException {
|
|
|
|
|
+ return ReadDocuments(url, false, null).getData();
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 使用POST请求
|
|
|
|
|
+ *
|
|
|
|
|
+ * @param url
|
|
|
|
|
+ * @param bin
|
|
|
|
|
+ * @return
|
|
|
|
|
+ * @throws IOException
|
|
|
|
|
+ */
|
|
|
|
|
+ public byte[] post(final String url, final byte[] bin) throws IOException {
|
|
|
|
|
+ return ReadDocuments(url, true, bin).getData();
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 请求网络访问
|
|
|
|
|
+ *
|
|
|
|
|
+ * @param url
|
|
|
|
|
+ * @return
|
|
|
|
|
+ * @throws IOException
|
|
|
|
|
+ */
|
|
|
|
|
+ public ResultBean ReadDocuments(String url) throws IOException {
|
|
|
|
|
+ return ReadDocuments(url, false, null);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ *
|
|
|
|
|
+ * @param url
|
|
|
|
|
+ * @param isPost
|
|
|
|
|
+ * @param
|
|
|
|
|
+ * @return
|
|
|
|
|
+ * @throws IOException
|
|
|
|
|
+ */
|
|
|
|
|
+ public ResultBean ReadDocuments(String url, boolean isPost, byte[] postData) throws IOException {
|
|
|
|
|
+ return ReadDocuments(new URL(url), isPost, postData, null, null);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * HTTP访问网络
|
|
|
|
|
+ *
|
|
|
|
|
+ * @param url
|
|
|
|
|
+ * @param isPost
|
|
|
|
|
+ * @param postData
|
|
|
|
|
+ * @param requestHead
|
|
|
|
|
+ * @return
|
|
|
|
|
+ * @throws IOException
|
|
|
|
|
+ */
|
|
|
|
|
+ public ResultBean ReadDocuments(String url, boolean isPost, byte[] postData, Map<String, String> requestHead)
|
|
|
|
|
+ throws IOException {
|
|
|
|
|
+ return ReadDocuments(new URL(url), isPost, postData, requestHead, null);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+ public ResultBean ReadDocuments(final URL url, final boolean isPost, final byte[] postData,
|
|
|
|
|
+ Map<String, String> requestHead, Boolean onlyHead) throws IOException {
|
|
|
|
|
+ HttpURLConnection httpURLConnection = connect(url, isPost, requestHead);
|
|
|
|
|
+ if (httpURLConnection == null) {
|
|
|
|
|
+ return null;
|
|
|
|
|
+ }
|
|
|
|
|
+ // 写出参数
|
|
|
|
|
+ if (isPost && postData != null) {
|
|
|
|
|
+ OutputStream outputStream = httpURLConnection.getOutputStream();
|
|
|
|
|
+ outputStream.write(postData);
|
|
|
|
|
+ outputStream.flush();
|
|
|
|
|
+ outputStream.close();
|
|
|
|
|
+ }
|
|
|
|
|
+ // 设置响应与返回的响应头信息
|
|
|
|
|
+ ResultBean resultBean = readInputStream(httpURLConnection, onlyHead);
|
|
|
|
|
+ // 设置服务器需要设置的cookies
|
|
|
|
|
+ readAndSetCookies(httpURLConnection);
|
|
|
|
|
+ return resultBean;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 创建连接管道
|
|
|
|
|
+ *
|
|
|
|
|
+ * @param url
|
|
|
|
|
+ * @param isPost
|
|
|
|
|
+ * @param requestHead
|
|
|
|
|
+ * @return 返回写入的数据管道
|
|
|
|
|
+ * @throws IOException
|
|
|
|
|
+ */
|
|
|
|
|
+ protected HttpURLConnection connect(final URL url, final Boolean isPost, Map<String, String> requestHead)
|
|
|
|
|
+ throws IOException {
|
|
|
|
|
+ URLConnection uRLConnection = null;
|
|
|
|
|
+ if (this.proxyHost == null) {
|
|
|
|
|
+ uRLConnection = url.openConnection();
|
|
|
|
|
+ } else {
|
|
|
|
|
+ Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(this.proxyHost, this.porxyPort));
|
|
|
|
|
+ uRLConnection = url.openConnection(proxy);
|
|
|
|
|
+ }
|
|
|
|
|
+ HttpURLConnection httpURLConnection = (HttpURLConnection) uRLConnection;
|
|
|
|
|
+ // 设置是否自动重定向
|
|
|
|
|
+ httpURLConnection.setInstanceFollowRedirects(isFollowRedirects());
|
|
|
|
|
+ // 设置访问模式
|
|
|
|
|
+ httpURLConnection.setRequestMethod(isPost != null && isPost ? "POST" : "GET");
|
|
|
|
|
+ // 设置是否从httpUrlConnection读入,默认情况下是true;
|
|
|
|
|
+ httpURLConnection.setDoInput(true);
|
|
|
|
|
+ // http正文内,因此需要设为true, 默认情况下是false;
|
|
|
|
|
+ httpURLConnection.setDoOutput(true);
|
|
|
|
|
+ // Post 请求不能使用缓存
|
|
|
|
|
+ httpURLConnection.setUseCaches(false);
|
|
|
|
|
+ // 请求头
|
|
|
|
|
+ if (requestHead == null) {
|
|
|
|
|
+ requestHead = new HashMap<String, String>();
|
|
|
|
|
+ }
|
|
|
|
|
+ // 设置请求类型编码
|
|
|
|
|
+ if (requestHead.get("Content-type") == null) {
|
|
|
|
|
+ httpURLConnection.setRequestProperty("Content-type", "application/x-www-form-urlencoded");
|
|
|
|
|
+ }
|
|
|
|
|
+ // 设置浏览器的版本
|
|
|
|
|
+ if (requestHead.get("User-Agent") == null) {
|
|
|
|
|
+ httpURLConnection.setRequestProperty("User-Agent", "Mozilla/5.0");
|
|
|
|
|
+ }
|
|
|
|
|
+ // 设置默认的Referer
|
|
|
|
|
+ if (requestHead.get("Referer") == null) {
|
|
|
|
|
+ httpURLConnection.setRequestProperty("Referer", url.toExternalForm());
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ for (String key : requestHead.keySet()) {
|
|
|
|
|
+ httpURLConnection.setRequestProperty(key, requestHead.get(key));
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 加载cookies
|
|
|
|
|
+ if (this.cookies != null && this.cookies.size() > 0)
|
|
|
|
|
+ httpURLConnection.setRequestProperty("Cookie", getInnerCookies());
|
|
|
|
|
+
|
|
|
|
|
+ httpURLConnection.setConnectTimeout(connectTimeout);
|
|
|
|
|
+ httpURLConnection.setReadTimeout(readTimeout);
|
|
|
|
|
+ // 开始连接连接
|
|
|
|
|
+ httpURLConnection.connect();
|
|
|
|
|
+ // 返回该创建连接后的对象
|
|
|
|
|
+ return httpURLConnection;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 取响应的结果
|
|
|
|
|
+ *
|
|
|
|
|
+ * @param httpURLConnection
|
|
|
|
|
+ * @return
|
|
|
|
|
+ * @throws IOException
|
|
|
|
|
+ */
|
|
|
|
|
+ protected ResultBean readInputStream(HttpURLConnection httpURLConnection, Boolean onlyHead) throws IOException {
|
|
|
|
|
+ // 读取响应的数据
|
|
|
|
|
+ InputStream inputStream = null;
|
|
|
|
|
+ try {
|
|
|
|
|
+ inputStream = httpURLConnection.getInputStream();
|
|
|
|
|
+ } catch (Exception e) {
|
|
|
|
|
+ inputStream = httpURLConnection.getErrorStream();
|
|
|
|
|
+ }
|
|
|
|
|
+ long totalByte = -1;
|
|
|
|
|
+ if (httpURLConnection.getHeaderField("Content-Length") != null) {
|
|
|
|
|
+ totalByte = Long.parseLong(httpURLConnection.getHeaderField("Content-Length"));
|
|
|
|
|
+ }
|
|
|
|
|
+ ResultBean resultBean = new ResultBean();
|
|
|
|
|
+ // 判断是否读取内容
|
|
|
|
|
+ if (onlyHead == null || onlyHead == false) {
|
|
|
|
|
+ byte[] resultBin = null;
|
|
|
|
|
+ if (inputStream != null) {
|
|
|
|
|
+ // 读取内容部分
|
|
|
|
|
+ resultBin = inputStreamToBytes(inputStream, totalByte);
|
|
|
|
|
+ inputStream.close();
|
|
|
|
|
+ }
|
|
|
|
|
+ resultBean.setData(resultBin);
|
|
|
|
|
+ }
|
|
|
|
|
+ // 设置响应的头信息
|
|
|
|
|
+ resultBean.setResponseHead(httpURLConnection.getHeaderFields());
|
|
|
|
|
+ // 设置响应状态code
|
|
|
|
|
+ resultBean.setStat(httpURLConnection.getResponseCode());
|
|
|
|
|
+ return resultBean;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 设置当前网络访问后的cookies
|
|
|
|
|
+ *
|
|
|
|
|
+ * @param httpURLConnection
|
|
|
|
|
+ */
|
|
|
|
|
+ protected void readAndSetCookies(HttpURLConnection httpURLConnection) {
|
|
|
|
|
+ setInnerCookies(httpURLConnection.getHeaderFields().get("Set-Cookie"));
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private void setInnerCookies(List<String> cookiesStr) {
|
|
|
|
|
+ if (cookiesStr != null)
|
|
|
|
|
+ for (int i = 0; i < cookiesStr.size(); i++) {
|
|
|
|
|
+ String tempStr = cookiesStr.get(i);
|
|
|
|
|
+ tempStr = tempStr.replaceAll(";", "=");
|
|
|
|
|
+ String[] mapping = tempStr.split("=");
|
|
|
|
|
+ if (mapping.length > 1) {
|
|
|
|
|
+ String key = mapping[0];
|
|
|
|
|
+ String value = mapping[1];
|
|
|
|
|
+ this.cookies.put(key, value);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ public String getInnerCookies() {
|
|
|
|
|
+ String result = "";
|
|
|
|
|
+ for (String key : this.cookies.keySet()) {
|
|
|
|
|
+ result += key + "=" + this.cookies.get(key) + "; ";
|
|
|
|
|
+ }
|
|
|
|
|
+ return result.trim();
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ *
|
|
|
|
|
+ * @param inputStream
|
|
|
|
|
+ * @return
|
|
|
|
|
+ */
|
|
|
|
|
+ private byte[] inputStreamToBytes(InputStream inputStream, long totalByte) throws IOException {
|
|
|
|
|
+ byte[] container = new byte[102400];
|
|
|
|
|
+ ByteArrayOutputStream arrayOutputStream = new ByteArrayOutputStream();
|
|
|
|
|
+ int b = -1;
|
|
|
|
|
+ while ((b = inputStream.read(container)) != -1) {
|
|
|
|
|
+ if (listenOutputStream != null) {
|
|
|
|
|
+ try {
|
|
|
|
|
+ listenOutputStream.write(container, 0, b);
|
|
|
|
|
+ } catch (Exception e) {
|
|
|
|
|
+ e.printStackTrace();
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ arrayOutputStream.write(container, 0, b);
|
|
|
|
|
+ showProgress(arrayOutputStream.size(), totalByte);
|
|
|
|
|
+ }
|
|
|
|
|
+ arrayOutputStream.flush();
|
|
|
|
|
+ byte[] data = arrayOutputStream.toByteArray();
|
|
|
|
|
+ arrayOutputStream.close();
|
|
|
|
|
+ return data;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 返回结果集
|
|
|
|
|
+ *
|
|
|
|
|
+ * @author admin
|
|
|
|
|
+ *
|
|
|
|
|
+ */
|
|
|
|
|
+ public class ResultBean implements Serializable {
|
|
|
|
|
+ /**
|
|
|
|
|
+ *
|
|
|
|
|
+ */
|
|
|
|
|
+ private static final long serialVersionUID = 2933585102741021542L;
|
|
|
|
|
+
|
|
|
|
|
+ public ResultBean() {
|
|
|
|
|
+
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private byte[] data;
|
|
|
|
|
+
|
|
|
|
|
+ private Map<String, List<String>> responseHead;
|
|
|
|
|
+
|
|
|
|
|
+ private int stat = 0;
|
|
|
|
|
+
|
|
|
|
|
+ public int getStat() {
|
|
|
|
|
+ return stat;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ public void setStat(int stat) {
|
|
|
|
|
+ this.stat = stat;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ public byte[] getData() {
|
|
|
|
|
+ return data;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ public void setData(byte[] data) {
|
|
|
|
|
+ this.data = data;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ public Map<String, List<String>> getResponseHead() {
|
|
|
|
|
+ return responseHead;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ public void setResponseHead(Map<String, List<String>> responseHead) {
|
|
|
|
|
+ this.responseHead = responseHead;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 取出字符编码,没有则返回null
|
|
|
|
|
+ *
|
|
|
|
|
+ * @return
|
|
|
|
|
+ */
|
|
|
|
|
+ public String getCharset() {
|
|
|
|
|
+ String charset = null;
|
|
|
|
|
+ // 取出文字编码
|
|
|
|
|
+ List<String> contentTypes = this.getResponseHead().get("Content-Type");
|
|
|
|
|
+ if (contentTypes != null) {
|
|
|
|
|
+ for (String contentType : contentTypes) {
|
|
|
|
|
+ int at = contentType.indexOf(CHARSET + "=");
|
|
|
|
|
+ if (at > -1) {
|
|
|
|
|
+ String right = contentType.substring(at + CHARSET.length() + 1, contentType.length());
|
|
|
|
|
+ charset = right.trim();
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ return charset;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+}
|