HttpClient简介
HTTP 协议可能是现在 Internet 上使用得最多、最重要的协议了,越来越多的 Java 应用程序需要直接通过 HTTP 协议来访问网络资源。虽然在 JDK 的 java.net 包中已经提供了访问 HTTP 协议的基本功能,但是对于大部分应用程序来说,JDK 库本身提供的功能还不够丰富和灵活。HttpClient 是 Apache Jakarta Common 下的子项目,用来提供高效的、最新的、功能丰富的支持 HTTP 协议的客户端编程工具包,并且它支持 HTTP 协议最新的版本和建议。HttpClient 已经应用在很多的项目中,比如 Apache Jakarta 上很著名的另外两个开源项目 Cactus 和 HTMLUnit 都使用了 HttpClient。更多信息请关注http://hc.apache.org/
HttpClient 功能介绍
以下列出的是 HttpClient 提供的主要的功能,要知道更多详细的功能可以参见 HttpClient 的主页。
-
实现了所有 HTTP 的方法(GET,POST,PUT,HEAD 等)
-
支持自动转向
-
支持 HTTPS 协议
-
支持代理服务器等
为什么使用此封装类?
不少的朋友使用了org.apache.http.client.methods.HttpGet和org.apache.http.client.methods.HttpPost这两个封装类进行抓取网页数据,伪造提交。当然本封装类也是基于这两个类进行再次封装的。使用过这两个类的朋友应该发现一些问题就是,每写一个伪造请求都需要实例一个对象。然而还无法很好的管理线程池的问题。导致几个请求一起触发的时候就会出现一直无响应,直到出现timeout。还要单独管理线程池的溢出和每一个请求的超时。所以这就是本类封装的缘故。当然这个封装类封装是傻瓜式的。只是解决了部分繁琐的代码,简便了一些重复的操作。同时自动管理了线程池的问题以及HTTPS证书问题。封装后最大的效果就是抽象,简便重复操作。使用此类完整的获取一个HTML页面内容只需要两行代码即可:
HttpClient client = new HttpClient("http://www.sohu.com/picture/209151068?_f=index_news_25"); System.out.println(client.request());
基于org.apache.httpcomponents -4.5.1 版本的HttpClient 做封装
项目中引用的话记得在maven中添加对应的pom:
<dependency> <groupId>org.apache.httpcomponents</groupId> <artifactId>httpclient</artifactId> <version>4.5.1</version> </dependency>
1、新建扩展类 “StringUtil”
public static class StringUtil { /** * 判断字符串是否为空 * * @param value * @return */ public static boolean isEmpty(String value) { return value == null || "".equals(value.trim()); } /** * 判断字符串是否不为空 * * @param str * @return */ public static boolean isNotEmpty(String str) { return !isEmpty(str); } /** * 判断是否是数字 * * @param sourceString * @return */ public static boolean isNumber(String sourceString) { if (isEmpty(sourceString)) return false; char[] sourceChar = sourceString.toCharArray(); for (int i = 0; i < sourceChar.length; i++) if ((sourceChar[i] < '0') || (sourceChar[i] > '9')) return false; return true; } }
2、新建扩展hashMap “CommonMap”
import java.util.HashMap; /** * 扩展hashMap * Created by Administrator on 2015/6/8. */ public class CommonMap<K,V> extends HashMap<K,V>{ public CommonMap(){} public CommonMap(K key, V value){ this.put(key,value); } public CommonMap<K,V> add(K key,V value){ this.put(key,value); return this; } public CommonMap<K,V> delete(K key){ this.remove(key); return this; } }
3、新建SSL类“MySSLProtocolSocketFactory”
import java.io.IOException; import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.Socket; import java.net.SocketAddress; import java.net.UnknownHostException; import java.security.KeyManagementException; import java.security.NoSuchAlgorithmException; import java.security.cert.CertificateException; import java.security.cert.X509Certificate; import javax.net.SocketFactory; import javax.net.ssl.SSLContext; import javax.net.ssl.TrustManager; import javax.net.ssl.X509TrustManager; import org.apache.commons.httpclient.ConnectTimeoutException; import org.apache.commons.httpclient.params.HttpConnectionParams; import org.apache.commons.httpclient.protocol.ProtocolSocketFactory; /** * author by zhangwei * * created at 2010-7-26 上午09:29:33 */ public class MySSLProtocolSocketFactory implements ProtocolSocketFactory { private SSLContext sslcontext = null; private SSLContext createSSLContext() { SSLContext sslcontext=null; try { sslcontext = SSLContext.getInstance("SSL"); sslcontext.init(null, new TrustManager[]{new TrustAnyTrustManager()}, new java.security.SecureRandom()); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } catch (KeyManagementException e) { e.printStackTrace(); } return sslcontext; } private SSLContext getSSLContext() { if (this.sslcontext == null) { this.sslcontext = createSSLContext(); } return this.sslcontext; } public Socket createSocket(Socket socket, String host, int port, boolean autoClose) throws IOException, UnknownHostException { return getSSLContext().getSocketFactory().createSocket( socket, host, port, autoClose ); } public Socket createSocket(String host, int port) throws IOException, UnknownHostException { return getSSLContext().getSocketFactory().createSocket( host, port ); } public Socket createSocket(String host, int port, InetAddress clientHost, int clientPort) throws IOException, UnknownHostException { return getSSLContext().getSocketFactory().createSocket(host, port, clientHost, clientPort); } public Socket createSocket(String host, int port, InetAddress localAddress, int localPort, HttpConnectionParams params) throws IOException, UnknownHostException, ConnectTimeoutException { if (params == null) { throw new IllegalArgumentException("Parameters may not be null"); } int timeout = params.getConnectionTimeout(); SocketFactory socketfactory = getSSLContext().getSocketFactory(); if (timeout == 0) { return socketfactory.createSocket(host, port, localAddress, localPort); } else { Socket socket = socketfactory.createSocket(); SocketAddress localaddr = new InetSocketAddress(localAddress, localPort); SocketAddress remoteaddr = new InetSocketAddress(host, port); socket.bind(localaddr); socket.connect(remoteaddr, timeout); return socket; } } //自定义私有类 private static class TrustAnyTrustManager implements X509TrustManager { public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException { } public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException { } public X509Certificate[] getAcceptedIssuers() { return new X509Certificate[]{}; } } }
4、新建HttpClient 请求核心封装类 “HttpClient ”
import CommonMap; import MySSLProtocolSocketFactory; import org.apache.commons.httpclient.protocol.Protocol; import org.apache.http.*; import org.apache.http.auth.AuthScope; import org.apache.http.auth.UsernamePasswordCredentials; import org.apache.http.client.AuthCache; import org.apache.http.client.CredentialsProvider; import org.apache.http.client.config.RequestConfig; import org.apache.http.client.entity.UrlEncodedFormEntity; import org.apache.http.client.methods.CloseableHttpResponse; import org.apache.http.client.methods.HttpGet; import org.apache.http.client.methods.HttpPost; import org.apache.http.client.protocol.HttpClientContext; import org.apache.http.client.utils.HttpClientUtils; import org.apache.http.config.Registry; import org.apache.http.config.RegistryBuilder; import org.apache.http.conn.socket.ConnectionSocketFactory; import org.apache.http.conn.socket.PlainConnectionSocketFactory; import org.apache.http.conn.ssl.SSLConnectionSocketFactory; import org.apache.http.entity.StringEntity; import org.apache.http.impl.auth.BasicScheme; import org.apache.http.impl.client.BasicAuthCache; import org.apache.http.impl.client.BasicCredentialsProvider; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClients; import org.apache.http.impl.conn.PoolingHttpClientConnectionManager; import org.apache.http.message.BasicNameValuePair; import org.apache.http.util.EntityUtils; import javax.net.ssl.SSLContext; import javax.net.ssl.TrustManager; import javax.net.ssl.X509TrustManager; import java.io.*; import java.security.KeyManagementException; import java.security.NoSuchAlgorithmException; import java.security.cert.CertificateException; import java.util.*; import java.util.regex.Matcher; import java.util.regex.Pattern; /** * Created by zhangwei on 2017/9/5. * httpClient */ public class HttpClient { /** * 请求类型 get/post */ public String METHOD_NAME = "GET"; /** * 请求的地址 url */ private String URL = ""; /** * HttpHost 代理对象 */ private HttpHost httpHost = null; /** * HTTP身份认证 用户凭证 */ private CredentialsProvider credsProvider = null; /** * clinet上下文对象 * 用来应用程序经常需要通过一些逻辑相关的请求-响应交换来保持状态信息。 * 为了使应用程序能够维持一个过程状态, * HttpClient允许HTTP请求在一个特定的执行上下文中来执行--称为HTTP上下文 */ private HttpClientContext httpClientContext = null; /** * httpclient的请求对象 线程池 */ private CloseableHttpClient httpclient = null; /** * 用回来获取请求响应的对象 */ private CloseableHttpResponse closeableHttpResponse = null; /** * get请求对象 */ private HttpGet httpGet = null; /** * post请求对象 */ private HttpPost httpPost = null; /** * 服务器响应超时 单位毫秒 */ private int socketTimeout = 20000; /** * 连接被阻塞超时 单位毫秒 */ private int connectTimeout = 20000; /** * 请求超时的时间 单位毫秒 */ private int connectionRequestTimeout = 20000; /** * 最大不要超过1000 */ private static int maxConnTotal = 10; /** * 实际的单个连接池大小,如tps定为50,那就配置50 */ private static int maxConnPerRoute = 20; private String accept = "*/*"; private String referer = ""; private String contentType = ""; private String origin = ""; private String userAgent = "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.102 Safari/537.36"; private boolean autoSaveReferer; /** * 自动保存上一个请求源 true 自动保存/false 不自动保存(默认) */ public void setAutoSaveReferer(boolean autoSaveReferer) { this.autoSaveReferer = autoSaveReferer; } /** * 先前网页的地址 */ public void setReferer(String referer) { this.referer = referer; } /** * 客户端能够接收的内容类型 */ public void setAccept(String accept) { this.accept = accept; } /** * 请求的与实体对应的MIME信息 */ public void setContentType(String contentType) { this.contentType = contentType; } /** * 请求的来源-post使用,等同于Referer头 */ public void setOrigin(String origin) { this.origin = origin; } /** * 注明客户端请求的触发器版本 * * @param userAgent */ public void setUserAgent(String userAgent) { this.userAgent = userAgent; } /** * 服务器响应超时 单位毫秒 * * @param socketTimeout */ public void setSocketTimeout(int socketTimeout) { this.socketTimeout = socketTimeout; } /** * 连接被阻塞超时 单位毫秒 * * @param connectTimeout */ public void setConnectTimeout(int connectTimeout) { this.connectTimeout = connectTimeout; } /** * 请求超时的时间 单位毫秒 * * @param connectionRequestTimeout */ public void setConnectionRequestTimeout(int connectionRequestTimeout) { this.connectionRequestTimeout = connectionRequestTimeout; } /** * 最大的请求连接数 注意:最大不要超过1000 * * @param maxConnTotal */ public static void setMaxConnTotal(int maxConnTotal) { HttpClient.maxConnTotal = maxConnTotal; } /** * 实际的单个连接池大小,如tps定为50,那就配置50 * * @param maxConnPerRoute */ public static void setMaxConnPerRoute(int maxConnPerRoute) { HttpClient.maxConnPerRoute = maxConnPerRoute; } private boolean isAutoSaveReferer() { return autoSaveReferer; } /** * 构造函数 无参 */ public HttpClient() { initHttpRequest(); } /** * 构造函数 初始化包含UR * * @param URL */ public HttpClient(String URL) { this.URL = URL; initHttpRequest(); } /** * 构造函数 初始化包含URL和请求类型 * * @param URL * @param METHOD_NAME */ public HttpClient(String URL, String METHOD_NAME) { this.URL = URL; this.METHOD_NAME = METHOD_NAME; initHttpRequest(); } /** * 初始化htpclinet的请求对象 */ public void initHttpRequest() { if (METHOD_NAME.equalsIgnoreCase("get")) { if (httpGet == null) { if (StringUtil.isNotEmpty(URL)) { httpGet = new HttpGet(URL); } else { httpGet = new HttpGet(); } } else { try { httpGet.setURI(new java.net.URI(URL)); } catch (Exception e) { e.printStackTrace(); } } httpGet.setHeader("Accept", accept); httpGet.setHeader("User-Agent", userAgent); if (StringUtil.isNotEmpty(contentType)) { httpGet.setHeader("Content-Type", contentType); } if (StringUtil.isNotEmpty(referer)) { httpGet.setHeader("Referer", referer); } } else if (METHOD_NAME.equalsIgnoreCase("post")) { if (httpPost == null) { if (StringUtil.isNotEmpty(URL)) { httpPost = new HttpPost(URL); } else { httpPost = new HttpPost(); } } else { try { httpPost.setURI(new java.net.URI(URL)); } catch (Exception e) { e.printStackTrace(); } } httpPost.setHeader("Accept", accept); if (StringUtil.isNotEmpty(contentType)) { httpPost.setHeader("Content-Type", contentType); } httpPost.setHeader("Origin", origin); httpPost.setHeader("User-Agent", userAgent); if (StringUtil.isNotEmpty(referer)) { httpPost.setHeader("Referer", referer); } } initHttpClinet(); } /** * 设置提交方式 get/post * * @param method * @throws Exception */ public void setMethod(String method) throws Exception { try { if (StringUtil.isNotEmpty(method)) { METHOD_NAME = method; initHttpRequest(); } else { throw new Exception("参数不能为空,method is null"); } } catch (Exception e) { throw new Exception(e.getMessage()); } } /** * 关闭client连接对象 释放对象 并重新初始化 * * @throws Exception */ public void closeClient(boolean isInit) { if (httpclient != null) { try { // 关闭请求 httpclient.getConnectionManager().shutdown(); HttpClientUtils.closeQuietly(httpclient); httpclient = null; if (closeableHttpResponse != null) { closeableHttpResponse.close();//防止线程池一直占用,无法释放内存,导致后面的请求响应堵塞 } if (httpGet != null) { httpGet = null; } if (httpPost != null) { httpPost = null; } } catch (Exception e) { e.printStackTrace(); } finally { if (isInit) {//如果是异常关的httpclient对象一定要重新初始化对象,以免访问出现空指针 initHttpClinet(); } } } } /** * 初始化clinet请求对象-并初始化HTTP/HTTPS两种协议 */ public void initHttpClinet() { if (httpclient == null) { try { System.setProperty("jsse.enableSNIExtension", "false"); //采用绕过验证的方式处理https请求 SSLContext sslcontext = createIgnoreVerifySSL(); // 设置协议http和https对应的处理socket链接工厂的对象 Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory>create() .register("http", PlainConnectionSocketFactory.INSTANCE) .register("https", new SSLConnectionSocketFactory(sslcontext)) .build(); Protocol myhttps = new Protocol("https", new MySSLProtocolSocketFactory(), 443); Protocol.registerProtocol("https", myhttps); PoolingHttpClientConnectionManager connManager = new PoolingHttpClientConnectionManager(socketFactoryRegistry); RequestConfig defaultRequestConfig = RequestConfig.custom() .setSocketTimeout(socketTimeout) .setConnectTimeout(connectTimeout) .setConnectionRequestTimeout(connectionRequestTimeout) .setStaleConnectionCheckEnabled(true) .build(); httpclient = HttpClients.custom() .setDefaultRequestConfig(defaultRequestConfig).setMaxConnTotal(maxConnTotal) .setMaxConnPerRoute(maxConnPerRoute).setConnectionManager(connManager) .build(); /* .setSSLSocketFactory(new SSLConnectionSocketFactory(sslcontext))*/ } catch (Exception e) { e.printStackTrace(); } } } /** * 请求数据并返回字符串类型 * * @return * @throws Exception */ public String request() throws Exception { try { HttpEntity entity = request(URL); InputStream inputStream = entity.getContent(); if (inputStream != null) { return readLineInputStream("utf-8", inputStream); } else { return ""; } } catch (Exception e) { throw new Exception(msgException(e)); } finally { closeHttpResponse(); } } /** * 请求数据并返回一个数据实体 * * @param url * @return * @throws Exception */ public HttpEntity request(String url) throws Exception { try { if (StringUtil.isNotEmpty(url)) { URL = url; } else { throw new Exception("参数不能为空,url is null"); } if (StringUtil.isEmpty(origin)) { origin = URL; } initHttpRequest(); if (httpHost != null) { closeableHttpResponse = httpclient.execute(httpHost, METHOD_NAME.equalsIgnoreCase("get") ? httpGet : httpPost); } else if (httpHost != null && httpClientContext != null) { closeableHttpResponse = httpclient.execute(httpHost, METHOD_NAME.equalsIgnoreCase("get") ? httpGet : httpPost, httpClientContext); } else { closeableHttpResponse = httpclient.execute(METHOD_NAME.equalsIgnoreCase("get") ? httpGet : httpPost); } if (isAutoSaveReferer()) { setReferer(URL); } return closeableHttpResponse.getEntity(); } catch (Exception e) { closeClient(true); //如果出现异常了就进行请求释放,防止异常未捕获导致回收失败 throw new Exception(msgException(e)); } finally { if (httpPost != null) httpPost.setEntity(null); } } /** * 请求数据并返回数据 自定义流转文本编码格式 * * @param url * @param utf * @return * @throws Exception */ public String request(String url, String utf) throws Exception { try { utf = StringUtil.isEmpty(utf) ? "utf-8" : utf; HttpEntity entity = request(url); InputStream inputStream = entity.getContent(); if (inputStream != null) { return readLineInputStream(utf, inputStream); } else { return ""; } } catch (Exception e) { throw new Exception(msgException(e)); } finally { closeHttpResponse(); } } /** * 请求并返回byte数组数据 * * @param url * @param numBer * @return * @throws Exception */ public byte[] request(String url, Integer numBer) throws Exception { try { return toByteArrays(request(url).getContent(), numBer); } catch (EOFException e) { throw new Exception(e.getMessage()); } finally { closeHttpResponse(); } } /** * 文件流转byte数组 * * @param in * @param numBer * @return * @throws Exception */ public byte[] toByteArrays(InputStream in, Integer numBer) throws Exception { numBer = numBer == null ? 8 : numBer; ByteArrayOutputStream out = new ByteArrayOutputStream(); byte[] buffer = new byte[1024 * numBer]; int i = 0; while ((i = in.read(buffer)) != -1) { out.write(buffer, 0, i); } return out.toByteArray(); } /** * 重载读取流 * * @param utf * @param httpEntity * @return * @throws IOException */ public String readLineInputStream(String utf, HttpEntity httpEntity) throws IOException { return readLineInputStream(utf, httpEntity.getContent()); } /** * 重载读取流 * * @param utf * @param inputStream * @return * @throws IOException */ public String readLineInputStream(String utf, InputStream inputStream) throws IOException { BufferedReader bf = null; InputStreamReader isr = null; try { isr = new InputStreamReader(inputStream, utf); bf = new BufferedReader(isr); StringBuffer buffer = new StringBuffer(); String line = ""; while ((line = bf.readLine()) != null) { buffer.append(line); } return buffer.toString(); } catch (Exception e) { e.printStackTrace(); } finally { bf.close(); isr.close(); inputStream.close(); } return ""; } /** * 重载读取流 * * @param inputStream * @return * @throws IOException */ public String readLineInputStream(InputStream inputStream) throws IOException { return readLineInputStream("utf-8", inputStream); } /** * 重载读取流 * * @param httpEntity * @return * @throws IOException */ public String readLineInputStream(HttpEntity httpEntity) throws Exception { try { if (httpEntity != null) { return readLineInputStream("utf-8", httpEntity.getContent()); } else { return ""; } } catch (Exception e) { e.printStackTrace(); throw new Exception("读取文件流异常:" + e.getMessage()); } } /** * 设置cookie * * @param cookie */ public void setCookie(String cookie) { if (METHOD_NAME.equalsIgnoreCase("get")) { httpGet.setHeader("Cookie", cookie); } else if (METHOD_NAME.equalsIgnoreCase("post")) { httpPost.setHeader("Cookie", cookie); } } public void setHeader(String headerName, String headerVal) throws Exception { setHeader(new CommonMap<String, String>(headerName, headerVal)); } /** * 设置Header * * @param header */ public void setHeader(Map<String, String> header) throws Exception { try { if (header != null) { for (String hd : header.keySet()) { if (METHOD_NAME.equalsIgnoreCase("get")) { httpGet.setHeader(hd, header.get(hd)); } else if (METHOD_NAME.equalsIgnoreCase("post")) { httpPost.setHeader(hd, header.get(hd)); } } } } catch (Exception e) { throw new Exception("setHeader 异常:" + e.getMessage()); } } /** * 设置post请求参数 string * * @param params * @throws Exception */ public void setEntity(String params) throws Exception { setEntity(getUrlParams(params)); } /** * 设置post请求参数 map * * @param params * @throws Exception */ public void setEntity(Map<String, String> params) throws Exception { try { if (METHOD_NAME.equalsIgnoreCase("post")) { httpPost.setEntity(new UrlEncodedFormEntity( getNameValuePairs(params), Consts.UTF_8)); } } catch (Exception e) { throw new Exception("setEntity 异常:" + e.getMessage()); } } /** * 设置post请求参数 map * * @param json * @throws Exception */ public void setEntity(StringEntity json) throws Exception { try { if (METHOD_NAME.equalsIgnoreCase("post")) { httpPost.setEntity(json); } } catch (Exception e) { throw new Exception("setEntity 异常:" + e.getMessage()); } } /** * 获取返回值的类型 * * @return */ public Header getContentType() throws Exception { if (closeableHttpResponse == null || closeableHttpResponse.getEntity() == null) { throw new Exception("java.lang.NullPointerException: closeableHttpResponse 为空,请先初始化对象。"); } return closeableHttpResponse.getEntity().getContentType(); } /** * 获取响应的实体类型 并获取具体类型:jpeg/html/png/gif...... * * @param isFormat * @return */ public String getContentType(boolean isFormat) { String contentType = ""; try { if (isFormat) { contentType = getContentType().toString(); if (StringUtil.isNotEmpty(contentType)) { int endIndex = contentType.length(); if (contentType.indexOf(";") != -1) { endIndex = contentType.indexOf(";"); } contentType = StringUtil.isNotEmpty(contentType) ? contentType.substring(contentType.indexOf("/") + 1, endIndex) : ""; } } else { return getContentType().toString(); } } catch (Exception e) { e.printStackTrace(); } return contentType; } /** * 获取返回值的状态 * 100 客户端可以继续 * 101 指示服务器正根据 Upgrade 头切换协议 * 200 请求正常成功 * 201 指示请求成功并在服务器上创建了一个新资源 * 202 指示已接受请求进行处理但处理尚未完成 * 203 指示客户端呈现的元信息并不源自服务器 * 204 指示请求成功但没有返回新信息 * 205 指示代理应该 重置导致请求被发送的文档视图 * 206 指示服务器已完成对资源的部分 GET 请求 * 300 请求的资源对应于表示形式集合中的某种表示形式,每种表示形式都有自己的特定位置 * 301 指示已经将资源永久地移动到了某个新位置,并且将来的引用应将新 URI 用于其请求 * 302 指示已经将资源暂时地移动到了另一个位置,但将来的引用仍应使用原来的 URI 访问该资源。 保留此定义是为了向后兼容。SC_FOUND 现在是首选定义 * 303 指示可在另一个 URI 之下找到该请求的响应 * 304 指示条件 GET 操作发现资源可用但不可修改 * 305 指示必须 通过 Location 字段给定的代理访问请求资源 * 307 指示请求的资源暂时驻留在另一个 URI 之下。临时 URI 应该 通过响应中的 Location 字段提供 * 400 指示客户端发送的请求在语法上不正确 * 401 指示请求需要进行 HTTP 验证 * 402 保留此代码以备将来使用 * 403 指示服务器理解请求但拒绝完成它 * 404 指示请求的资源不可用 * 405 指示 Request-Line 中指定的方法不支持 Request-URI 标识的资源 * 406 指示请求标识的资源只能生成响应实体,根据请求中发送的 accept 头,这些响应实体具有不可接受的内容特征 * 407 指示客户端必须 首先通过代理验证其自身 * 408 指示客户端没有在服务器准备等待的时间内生成请求 * 409 指示由于与当前资源状态冲突请求无法完成 * 410 指示资源在服务器上不再可用并且不知道转发地址。应该 认为此条件是永久性的 * 411 指示在没有定义 Content-Length 的情况下无法处理请求 * 412 指示在服务器上测试一个或多个请求头字段中给出的前提时,该前提被求值为 false * 413 指示因为请求实体大于服务器愿意或能够处理的实体,所以服务器拒绝处理请求 * 414 指示因为 Request-URI 的长度大于服务器愿意解释的 Request-URI 长度,所以服务器拒绝为请求提供服务 * 415 指示因为请求实体的格式不受请求方法的请求资源支持,所以服务器拒绝为请求提供服务 * 416 指示服务器无法服务于请求的字节范围 * 417 指示服务器无法服务于请求的字节范围 * 500 指示 HTTP 服务器内存在错误使服务器无法完成请求 * 501 指示 HTTP 服务器不支持完成请求所需的功能 * 502 指示 HTTP 服务器在充当代理或网关时从它参考的服务器接收到一个无效响应 * 503 指示 HTTP 服务器暂时过载,并且无法处理请求 * 504 指示服务器在充当网关或代理时没有从上游服务器接收到及时的响应 * 505 指示服务器不支持或拒绝支持请求消息中使用的 HTTP 协议版本 * * @return */ public int getStatusCode() throws Exception { if (closeableHttpResponse == null || closeableHttpResponse.getStatusLine() == null) { throw new Exception("java.lang.NullPointerException: closeableHttpResponse 为空,请先初始化对象。"); } try { return closeableHttpResponse.getStatusLine().getStatusCode(); } catch (Exception e) { throw new Exception(e.getMessage()); } } public CloseableHttpResponse getHttpResponse() throws Exception { try { return closeableHttpResponse; } catch (Exception e) { throw new Exception(e.getMessage()); } } /** * 关闭线程池,防止堵塞(这里需要手动调用,由于这里吧响应和请求封装在一个类了所以只能在外面手动调用释放) * * @throws IOException */ public void closeHttpResponse() throws IOException { if (closeableHttpResponse != null) { closeableHttpResponse.close();//防止线程池一直占用,无法释放内存,导致后面的请求响应堵塞 } } /** * 关闭线程池,防止堵塞(这里需要手动调用,由于这里吧响应和请求封装在一个类了所以只能在外面手动调用释放) * 如果出现发送httpclient请求后一直无响应,应该是线程池占用完了,所以每次调用request后记得在finally手动调用本方法CloseHttpResponse * * @param entity 访问流结束后需要传递实体流进来并释放掉 * @throws IOException */ public void closeHttpResponse(HttpEntity entity) throws IOException { if (closeableHttpResponse != null) { EntityUtils.consume(entity); closeableHttpResponse.close();//防止线程池一直占用,无法释放内存,导致后面的请求响应堵塞 } } /** * 服务器认证信息 * * @param userName 登录信息的用户名 * @param userPwd 登录信息的密码 * @throws Exception */ public void setCredentials(String userName, String userPwd) throws Exception { try { if (httpHost == null) { throw new Exception("java.lang.NullPointerException: httpHost 为空,请先初始化对象。"); } credsProvider = new BasicCredentialsProvider(); credsProvider.setCredentials( new AuthScope(httpHost.getHostName(), httpHost.getPort()), new UsernamePasswordCredentials(userName, userPwd)); // 创建 AuthCache 对象 AuthCache authCache = new BasicAuthCache(); //创建 BasicScheme,并把它添加到 auth cache中 BasicScheme basicAuth = new BasicScheme(); authCache.put(httpHost, basicAuth); // 把AutoCache添加到上下文中 httpClientContext = HttpClientContext.create(); httpClientContext.setCredentialsProvider(credsProvider); httpClientContext.setAuthCache(authCache); } catch (Exception e) { throw new Exception(msgException(e)); } } /** * 设置HTTP请求代理模式 * 格式:127.0.0.0:8888 * * @param hostVal * @throws Exception */ public void setHttpHost(String hostVal) throws Exception { if (StringUtil.isNotEmpty(hostVal) && hostVal.indexOf(":") != -1) { try { String ip = hostVal.substring(0, hostVal.indexOf(":")); String host = hostVal.substring(hostVal.indexOf(":") + 1); if (StringUtil.isNotEmpty(ip) && isIP(ip) && StringUtil.isNotEmpty(host)) { httpHost = new HttpHost(ip, Integer.parseInt(host)); } } catch (Exception e) { throw new Exception(msgException(e)); } } else { throw new Exception("httphost 参数内容有误,正确示范:127.0.1.1:8888"); } } /** * 通过map对象转换为数据实体 * * @param params * @return */ private static List<NameValuePair> getNameValuePairs(Map<String, String> params) { List<NameValuePair> nvps = new ArrayList<NameValuePair>(); if (params != null && params.keySet().size() > 0) { Iterator iterator = params.entrySet().iterator(); while (iterator.hasNext()) { Map.Entry entry = (Map.Entry) iterator.next(); nvps.add(new BasicNameValuePair((String) entry.getKey(), (String) entry.getValue())); } } return nvps; } /** * json url Transformation map json参数标准化为map对象 * * @param param * @return */ public static Map<String, String> getUrlParams(String param) { Map<String, String> map = new HashMap<String, String>(0); if (param == null || param.length() <= 0) { return map; } String[] params = param.split("&"); for (int i = 0; i < params.length; i++) { String[] p = params[i].split("="); if (p.length != 0) { map.put(p[0], p.length == 2 && p[1] != null && p[1].length() != 0 ? p[1] : ""); } } return map; } /** * 判断是否为IP对象 * * @param addr * @return */ public boolean isIP(String addr) throws Exception { try { if (addr.length() < 7 || addr.length() > 15 || "".equals(addr)) { return false; } /** * 判断IP格式和范围 */ String rexp = "([1-9]|[1-9]\d|1\d{2}|2[0-4]\d|25[0-5])(\.(\d|[1-9]\d|1\d{2}|2[0-4]\d|25[0-5])){3}"; Pattern pat = Pattern.compile(rexp); Matcher mat = pat.matcher(addr); boolean ipAddress = mat.find(); return ipAddress; } catch (Exception e) { throw new Exception("isIP exception 验证IP失败....." + msgException(e)); } } /** * 判断是否是图片类型的文件 * * @param html */ public boolean isImage(String html) { if (StringUtil.isNotEmpty(html)) { if (ImageType.BMP.toString().equalsIgnoreCase(html) || ImageType.gif.toString().equalsIgnoreCase(html) || ImageType.jpeg.toString().equalsIgnoreCase(html) || ImageType.png.toString().equalsIgnoreCase(html)) { return true; } } else { return false; } return false; } /** * 判断是否是图片类型的文件 */ public boolean isImage() { try { String requestType = getContentType(true); if (StringUtil.isNotEmpty(requestType)) { return isImage(requestType); } } catch (Exception e) { e.printStackTrace(); } return false; } /** * 图片类型的枚举 */ public enum ImageType { png, gif, jpg, jpeg, BMP, } /** * 绕过验证-HTTPS * * @return * @throws NoSuchAlgorithmException * @throws KeyManagementException */ public static SSLContext createIgnoreVerifySSL() throws KeyManagementException, NoSuchAlgorithmException { SSLContext sc = SSLContext.getInstance("SSLv3"); // 实现一个X509TrustManager接口,用于绕过验证,不用修改里面的方法 X509TrustManager trustManager = new X509TrustManager() { @Override public void checkClientTrusted( java.security.cert.X509Certificate[] paramArrayOfX509Certificate, String paramString) throws CertificateException { } @Override public void checkServerTrusted( java.security.cert.X509Certificate[] paramArrayOfX509Certificate, String paramString) throws CertificateException { } @Override public java.security.cert.X509Certificate[] getAcceptedIssuers() { return null; } }; sc.init(null, new TrustManager[]{trustManager}, null); return sc; } /** * 打印错误的异常详情 * * @param e * @return */ public String msgException(Exception e) { String msg = ""; if (e != null && e.getStackTrace().length != 0) { StackTraceElement stackTraceElement = e.getStackTrace()[0];// 得到异常棧的首个元素 msg = String.format("出现异常的类文件:%s,错误行数:%s,错误方法体:%s", stackTraceElement.getFileName(), stackTraceElement.getLineNumber(), stackTraceElement.getMethodName()); /* System.out.println("File="+stackTraceElement.getFileName());// 打印文件名 System.out.println("Line="+stackTraceElement.getLineNumber());// 打印出错行号 System.out.println("Method="+stackTraceElement.getMethodName());// 打印出错方法*/ } return msg; } }
代码演示
1、使用搜狐网做示例:
1.代码区域
public static void main(String args[]) { try { /*声明封装类 默认请求是get*/ HttpClient client = new HttpClient("http://www.sohu.com/picture/209151068?_f=index_news_25"); client.setHttpHost("192.168.3.2:8888"); System.out.println(client.request()); client.setMethod("post");//登录改为post请求 client.setEntity("domain=sohu.com&callback=passport200007278089333261106_cb1512742508288&appid=1019&userid=XXXXXXXXXXXXXXXX&password=XXXXXXXXXXXXX&persistentcookie=0"); client.setContentType("application/x-www-form-urlencoded"); String loginHtml = client.request("http://passport.sohu.com/apiv2/login", "utf-8");//登录搜狐网站 System.out.println(loginHtml); client.setMethod("get");//登录改为post请求 loginHtml = client.request("http://passport.sohu.com/apiv2/toolbar/userinfo?callback=jQuery112404914197299918357_1512742508303&_=1512742508445", "utf-8");//获取部分个人信息 System.out.println(loginHtml); } catch (Exception e) { e.printStackTrace(); } }
2.响应请求
<!DOCTYPE html><html><head> <title>壮观!1180架无人机升空在广州塔前表演-搜狐大视野-搜狐新闻</title> <meta name="keywords" content="壮观,1180,无人机,升空,空在,广州,表演"/>
<meta name="description" content="12月7日晚,广州。在《祝酒歌》合唱歌声中,1180架无人机编队从海心沙飞起,亮灯形成“财富”两个汉字,现场市民齐齐仰头观看。此次无人机编队利用“科技舞蹈”,表达对2017广州某论坛的欢迎,给出席论坛的嘉宾带来惊喜。" /><meta charset="utf-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=Edge,chrome=1"/><meta name="renderer" content="webkit"> <meta name="viewport" content="width=device-width, initial-scale=1,maximum-scale=1" />
<link rel="icon" href="//statics.itc.cn/web/static/images/pic/sohu-logo/favicon.ico" type="image/x-icon"/><link rel="shortcut icon" href="//statics.itc.cn/web/static/images/pic/sohu-logo/favicon.ico" type="image/x-icon"/>
<link rel="apple-touch-icon" sizes="57x57" href="//statics.itc.cn/web/static/images/pic/sohu-logo/logo-57.png" /><link rel="apple-touch-icon" sizes="72x72" href="//statics.itc.cn/web/static/images/pic/sohu-logo/logo-72.png" />
<link rel="apple-touch-icon" sizes="114x114" href="//statics.itc.cn/web/static/images/pic/sohu-logo/logo-114.png" /><link rel="apple-touch-icon" sizes="144x144" href="//statics.itc.cn/web/static/images/pic/sohu-logo/logo-144.png" />
<link href="//statics.itc.cn/web/v3/static/css/main-6708fcb576.css" rel="stylesheet"/><script> // 加载监控代码</script><!--[if lt IE 9]><script src="//statics.itc.cn/web/v3/static/js/es5-shim-08e41cfc3e.min.js"></script>
<script src="//statics.itc.cn/web/v3/static/js/es5-sham-1d5fa1124b.min.js"></script><script src="//statics.itc.cn/web/v3/static/js/html5shiv-21fc8c2ba6.js"></script>
<link href="//statics.itc.cn/web/v3/static/css/ie8hack-9dce3c3b96.css" rel="stylesheet" /><![endif]--><script type="text/javascript">//解決IE8,IE9不支持console的问题(function() { var method; var noop = function() {};
var methods = [ 'assert', 'clear', 'count', 'debug', 'dir', 'dirxml', 'error', 'exception', 'group', 'groupCollapsed', 'groupEnd', 'info', 'log', 'markTimeline', 'profile', 'profileEnd', 'table', 'time'
, 'timeEnd', 'timeStamp', 'trace', 'warn' ]; var length = methods.length; var console = (window.console = window.console || {}); while (length--) { method = methods[length]; // Only stub undefin
ed methods. if (!console[method]) { console[method] = noop; } }}());</script><script type="text/javascript"> (function () { var html = document.getElementsByTagName("html")[0]; var width = Math.min(document.
documentElement.clientWidth, 790); width = width < 320 ? 320 : width; if (document.documentElement.clientWidth <= 1024) { html.style.fontSize = width / 790 * 79 + 'px'; } if (window.addEventListener) { window.
addEventListener('resize', resizeHandler); } else if (window.attachEvent) { window.attachEvent('onresize', resizeHandler); } function resizeHandler() { if (document.documentElement.clientWidth <= 1024) {
var width = Math.min(document.documentElement.clientWidth, 790); width = width < 320 ? 320 : width; html.style.fontSize = width / 790 * 79 + 'px'; } else { html.style.fontSize = "16px"; }
}; })();</script></head><body class="dsy-article"><div class="wrapper-box"><header id="main-header" class="article-head"> <div class="area"> <div class="head-nav left"> <ul>
<li class="index"><a href="http://www.sohu.com"><em class="icon-home icon"></em><em class="sohu-logo">搜狐首页</em></a></li> <li><a href="http://news.sohu.com/">新闻</a></li>
<li><a href="http://sports.sohu.com/">体育</a></li> <li><a href="http://auto.sohu.com/">汽车</a></li> <li><a href="http://www.focus.cn/">房产</a></li>
<li><a href="http://travel.sohu.com/">旅游</a></li> <li><a href="http://learning.sohu.com/">教育</a></li> <li><a href="http://fashion.sohu.com/">时尚</a></li>
<li><a href="http://it.sohu.com/">科技</a></li> <li><a href="http://business.sohu.com/">财经</a></li> <li><a href="http://yule.sohu.com/">娱乐</a></li>
<li class="more-nav"><a href="javascript:void(0)">更多<em class="cor"></em></a> <div class="more-nav-box">
<a href="http://baobao.sohu.com/">母婴</a> <a href="http://health.sohu.com/">健康</a> <a href="http://history.sohu.com/">历史</a>
<a href="http://mil.sohu.com/">军事</a> <a href="http://chihe.sohu.com/">美食</a>
<a href="http://cul.sohu.com/">文化</a> <a href="http://astro.sohu.com/">星座</a> <a href="http://society.sohu.com/">社会</a>
<a href="http://game.sohu.com/">游戏</a> <a href="http://fun.sohu.com/">搞笑</a> <a href="http://acg.sohu.com/">动漫</a>
<a href="http://pets.sohu.com/">宠物</a> </div> </li> </ul> </div>
<div id="head-login" class="right login"> <!--<span class="login-before"><a class="login-sohu" data-role="login-btn" href="javascript:void(0)"><i class="icon-user"></i>登录狐友</a></span> <span class="login-after" style="display:none;">
<a href="#" target="_blank" class="user"><img src="images/pic/pic01.jpg" alt="我叫名字特别长"></a> <a href="#" target="_blank" class="write-link">写文章</a> </span>-->
</div> </div> </header><div class="logo-search area"> <div class="left logo"><a href="javascript:void(0)">大视野</a></div> <div id="search" class="search left"><input type="text"
class="search-input left" value="大家正在搜:北京公租房:将为“新北京人”单划30%房源" /><a href="#" target="_blank" class="search-btn"><i class="search-icon icon"></i></a></div></div><div class="dsy-wrap"> <div class="dsy-contentA area clearfix">
<div class="article-title"> <h1 id="article-title-hash">壮观!1180架无人机升空在广州塔前表演</h1> <div class="info"> <span class="name"><img src="http://sucimg.itc.cn/avatarimg/965df594fbf44e3d86a2264f20d744b6_1506565321449"
alt="">一个普通的号</span><span class="time">2017-12-08 07:21:26</span> </div> <div class="func"> <span class="restart-link hid"><a href="javascript:;" class="link"><i class="icon restart-icon"></i><em class="num">重新浏览</em>
</a></span> <span class="com-link"> <a href="#comment_area" class="link"> <i class="icon com-icon"></i> <em data-role="comment-count" class="num">0</em> </a>
</span> <span class="zan-link" pic-likes="209151068"> <a href="javascript:;" class="link add-likes"> <i class="icon zan-icon"></i> <i class="icon unzan-icon hid"></i>
<em class="num"></em> </a> </span> </div> </div> <div class="pic-main"> <div class="pic-area">
<div class="picture"><i></i><img data-url="//5b0988e595225.cdn.sohucs.com/images/20171208/8678adb12de345e4a3e4047cf759338d.jpeg" src="//5b0988e595225.cdn.sohucs.com/c_zoom,h_77/images/20171208/8678adb12de345e4a3e4047cf759338d.jpeg" data-ev="10410060" alt=""></div>
<div class="picture hid"><i></i><img data-url="//5b0988e595225.cdn.sohucs.com/images/20171208/ebb3f770a164426f885fff1ba7d25fbf.jpeg" src="//5b0988e595225.cdn.sohucs.com/c_zoom,h_77/images/20171208/ebb3f770a164426f885fff1ba7d25fbf.jpeg"
alt=""></div> <div class="picture hid"><i></i><img data-url="//5b0988e595225.cdn.sohucs.com/images/20171208/d1962cd561214eada020425faac85f70.jpeg" src="//5b0988e595225.cdn.sohucs.com/c_zoom,h_77/images/20171208/d1962cd561214eada020
425faac85f70.jpeg" alt=""></div> <div class="picture hid"><i></i><img data-url="//5b0988e595225.cdn.sohucs.com/images/20171208/4b955cf5b33044e88584e0f07b66f4b7.jpeg" src="//5b0988e595225.cdn.sohucs.com/c_zoom,h_77/images/20171208/4
b955cf5b33044e88584e0f07b66f4b7.jpeg" alt=""></div> <div class="picture hid"><i></i><img data-url="//5b0988e595225.cdn.sohucs.com/images/20171208/75a2e6dcdd714089a3503c3820bc2631.jpeg" src="//5b0988e595225.cdn.sohucs.com/c_zoom,h_77
/images/20171208/75a2e6dcdd714089a3503c3820bc2631.jpeg" alt=""></div> <div class="picture hid"><i></i><img data-url="//5b0988e595225.cdn.sohucs.com/images/20171208/22d27f5cc0c54435a8bdbd2bb80f0f87.jpeg" src="//5b0988e595225.cdn.sohuc
s.com/c_zoom,h_77/images/20171208/22d27f5cc0c54435a8bdbd2bb80f0f87.jpeg" alt=""></div> <div class="picture hid"><i></i><img data-url="//5b0988e595225.cdn.sohucs.com/images/20171208/42e389e7c76a4dabae945ed91bf5e2de.jpeg" src="//5b0988e595225.cdn.sohucs.com/c_zoom,h_77/images/20171208/42e389e7c76a4dabae945ed91bf5e2de.jpeg" alt=""></div> <div class="picture hid"><i></i><img data-url="//5b0988e595225.cdn.sohucs.com/images/20171208/68652014966b4f53a0152af1c95dcdb7.jpeg" src="//5b0988e595225.cdn.sohucs.com/c_zoom,h_77/images/20171208/68652014966b4f53a0152af1c95dcdb7.jpeg" alt=""></div> <div class="picture hid"><i></i><img data-url="//5b0988e595225.cdn.sohucs.com/images/20171208/4c6ee145a6234594b8e081ad8831f8ba.jpeg" src="//5b0988e595225.cdn.sohucs.com/c_zoom,h_77/images/20171208/4c6ee145a6234594b8e081ad8831f8ba.jpeg" data-ev="10410059" alt=""></div> <div class="switch-btn"> <a href="javascript:;" class="btn-pre hid pre-img-btn"> <span class="bg"></span> <i class="icon pre-icon hid" title="上一图片"></i></a> <a href="javascript:;" class="btn-next next-img-btn"> <span class="bg"></span> <i class="icon next-icon hid" title="下一图片"></i> </a> </div> <div class="explain"> <div class="bg-area"></div> <div class="pic-number"><em class="num">1</em>/<em class="total">12</em></div> <div class="pic-exp"> <div class="txt"> <p>12月7日晚,广州。在《祝酒歌》合唱歌声中,1180架无人机编队从海心沙飞起,亮灯形成“财富”两个汉字,现场市民齐齐仰头观看。此次无人机编队利用“科技舞蹈”,表达对2017广州某论坛的欢迎,给出席论坛的嘉宾带来惊喜。</p> <p class="hid">据悉,这是继2017年元宵节广州在海心沙创造的1000架无人机表演破吉尼斯世界纪录之后,带来的数量更多的无人机编队飞行表演。图为无人机拼凑“财富”二字。</p> <p class="hid">现场图。</p> <p class="hid">现场图。</p> <p class="hid">现场图。</p> <p class="hid">现场图。</p> <p class="hid">现场图。</p> <p class="hid">现场图。</p> <p class="hid">现场图。</p> </div> </div> </div> <div class="operation"> <a href="javascript:;" data-cv="10410064" class="btn-original btn-include-text" data-cv=""> <span class="show-hint-text hid">查看原图</span> </a> <a href="javascript:;" data-cv="10410063" class="btn-slide btn-include-text" data-cv=""> <span class="show-hint-text hid">全屏模式</span> </a> </div> </div> <div class="pic-small-group"> <div class="pic-list"> <div class="scroll"> <div class="con"> <div class="pic cur"><img data-url="//5b0988e595225.cdn.sohucs.com/images/20171208/8678adb12de345e4a3e4047cf759338d.jpeg" src="//5b0988e595225.cdn.sohucs.com/c_zoom,h_77/images/20171208/8678adb12de345e4a3e4047cf759338d.jpeg" alt=""> <div class="bg"></div> </div> <div class="pic"><img data-url="//5b0988e595225.cdn.sohucs.com/images/20171208/ebb3f770a164426f885fff1ba7d25fbf.jpeg" src="//5b0988e595225.cdn.sohucs.com/c_zoom,h_77/images/20171208/ebb3f770a164426f885fff1ba7d25fbf.jpeg" alt=""> <div class="bg"></div> </div> <div class="pic"><img data-url="//5b0988e595225.cdn.sohucs.com/images/20171208/d1962cd561214eada020425faac85f70.jpeg" src="//5b0988e595225.cdn.sohucs.com/c_zoom,h_77/images/20171208/d1962cd561214eada020425faac85f70.jpeg" alt=""> <div class="bg"></div> </div> <div class="pic"><img data-url="//5b0988e595225.cdn.sohucs.com/images/20171208/4b955cf5b33044e88584e0f07b66f4b7.jpeg" src="//5b0988e595225.cdn.sohucs.com/c_zoom,h_77/images/20171208/4b955cf5b33044e88584e0f07b66f4b7.jpeg" alt=""> <div class="bg"></div> </div> <div class="pic"><img data-url="//5b0988e595225.cdn.sohucs.com/images/20171208/75a2e6dcdd714089a3503c3820bc2631.jpeg" src="//5b0988e595225.cdn.sohucs.com/c_zoom,h_77/images/20171208/75a2e6dcdd714089a3503c3820bc2631.jpeg" alt=""> <div class="bg"></div> </div> <div class="pic"><img data-url="//5b0988e595225.cdn.sohucs.com/images/20171208/22d27f5cc0c54435a8bdbd2bb80f0f87.jpeg" src="//5b0988e595225.cdn.sohucs.com/c_zoom,h_77/images/20171208/22d27f5cc0c54435a8bdbd2bb80f0f87.jpeg" alt=""> <div class="bg"></div> </div> <div class="pic"><img data-url="//5b0988e595225.cdn.sohucs.com/images/20171208/42e389e7c76a4dabae945ed91bf5e2de.jpeg" src="//5b0988e595225.cdn.sohucs.com/c_zoom,h_77/images/20171208/42e389e7c76a4dabae945ed91bf5e2de.jpeg" alt=""> <div class="bg"></div> </div> <div class="pic"><img data-url="//5b0988e595225.cdn.sohucs.com/images/20171208/68652014966b4f53a0152af1c95dcdb7.jpeg" src="//5b0988e595225.cdn.sohucs.com/c_zoom,h_77/images/20171208/68652014966b4f53a0152af1c95dcdb7.jpeg" alt=""> <div class="bg"></div> </div> <div class="pic"><img data-url="//5b0988e595225.cdn.sohucs.com/images/20171208/4c6ee145a6234594b8e081ad8831f8ba.jpeg" src="//5b0988e595225.cdn.sohucs.com/c_zoom,h_77/images/20171208/4c6ee145a6234594b8e081ad8831f8ba.jpeg" alt=""> <div class="bg"></div> </div> </div> </div> <div class="btns"><a class="btnl unbtnl pre-pic-group" href="javascript:void(0)"></a><a class="btnr next-pic-group" href="javascript:void(0)"></a></div> </div> </div> </div> <div class="pic-last hid"> <div class="last-mod clearfix"> <div class="title">大家正在看</div> <div class="left pic-group"> <ul> <li><a title="洛杉矶当局预警:山火极危险 将有爆炸性增长" class="jump-next-pic" id="209185533" href="/picture/209185533" data-cv="10410061" target="_blank"><img src="//5b0988e595225.cdn.sohucs.com/a_auto,c_cut,x_0,y_0,w_640,h_426/images/20171208/e1e939a8d84f449cabd030b09aa2ab99.jpeg" alt=""><span>洛杉矶当局预警:山火极危险 将有爆炸性增长</span></a></li> <li><a title="郑州警方破获特大外汇交易软件诈骗案刑拘35人" class="jump-next-pic" id="209182938" href="/picture/209182938" data-cv="10410061" target="_blank"><img src="//5b0988e595225.cdn.sohucs.com/a_auto,c_cut,x_0,y_0,w_930,h_620/images/20171208/17529c9a8fb243d6a10a09d56634d360.jpeg" alt=""><span>郑州警方破获特大外汇交易软件诈骗案刑拘35人</span></a></li> <li><a title="大佬们的保镖对比 李嘉诚的是退伍特种兵" class="jump-next-pic" id="209182740" href="/picture/209182740" data-cv="10410061" target="_blank"><img src="//5b0988e595225.cdn.sohucs.com/a_auto,c_cut,x_0,y_13,w_599,h_400/images/20171208/a583d1d2281046019c0bee9866731b05.jpeg" alt=""><span>大佬们的保镖对比 李嘉诚的是退伍特种兵</span></a></li> <li><a title="成都电子科大迎最美银杏季" class="jump-next-pic" id="209182230" href="/picture/209182230" data-cv="10410061" target="_blank"><img src="//5b0988e595225.cdn.sohucs.com/a_auto,c_cut,x_125,y_0,w_762,h_508/images/20171208/88337338e83c44ad8f156c8fa42a6e57.jpeg" alt=""><span>成都电子科大迎最美银杏季</span></a></li> <li><a title="王菲、冯小刚的豪宅跟她的相比简直太寒酸!" class="jump-next-pic" id="209181480" href="/picture/209181480" data-cv="10410061" target="_blank"><img src="//5b0988e595225.cdn.sohucs.com/a_auto,c_cut,x_0,y_10,w_586,h_391/images/20171208/301449365f6041d38289174cd2df60cc.jpeg" alt=""><span>王菲、冯小刚的豪宅跟她的相比简直太寒酸!</span></a></li> <li><a title="史上最奇葩汽车造型 这些车主脑洞真大" class="jump-next-pic" id="209180962" href="/picture/209180962" data-cv="10410061" target="_blank"><img src="//5b0988e595225.cdn.sohucs.com/a_auto,c_cut,x_0,y_12,w_640,h_426/images/20171208/a3ff6181309a40deb0e4f3e008121f7f.jpeg" alt=""><span>史上最奇葩汽车造型 这些车主脑洞真大</span></a></li> </ul> </div> <div class="right last-ri"> <div class="godR"> </div> </div> </div> <div class="last-btn"><a href="javascript:;" class="bl pre-img-btn"></a> <a href="/picture/209185533" data-cv="10410062" class="br next-pic-collection"></a></div> </div> </div> <div class="original-box"> <div class="img-wrap"> <div class="original-pic"><img src="" alt=""></div> </div> <span target="_blank" class="original-close"></span> </div> <div class="slide-box"> <div class="slide-btn"> <span target="_blank" class="slide-quit btn-include-text"> <span class="show-hint-text hid">退出全屏</span> </span> <span target="_blank" class="slide-stop btn-include-text"> <span class="show-hint-text hid">暂停</span> </span> <span target="_blank" class="slide-play hid btn-include-text"> <span class="show-hint-text hid">播放</span> </span> </div> <div class="slide-main"> <div class="slide-pic"> <div class="slide-con"> <div class="picture show"><i></i><img data-url="//5b0988e595225.cdn.sohucs.com/images/20171208/8678adb12de345e4a3e4047cf759338d.jpeg" src="//5b0988e595225.cdn.sohucs.com/c_zoom,h_77/images/20171208/8678adb12de345e4a3e4047cf759338d.jpeg" alt=""></div> <div class="picture"><i></i><img data-url="//5b0988e595225.cdn.sohucs.com/images/20171208/ebb3f770a164426f885fff1ba7d25fbf.jpeg" src="//5b0988e595225.cdn.sohucs.com/c_zoom,h_77/images/20171208/ebb3f770a164426f885fff1ba7d25fbf.jpeg" alt=""></div> <div class="picture"><i></i><img data-url="//5b0988e595225.cdn.sohucs.com/images/20171208/d1962cd561214eada020425faac85f70.jpeg" src="//5b0988e595225.cdn.sohucs.com/c_zoom,h_77/images/20171208/d1962cd561214eada020425faac85f70.jpeg" alt=""></div> <div class="picture"><i></i><img data-url="//5b0988e595225.cdn.sohucs.com/images/20171208/4b955cf5b33044e88584e0f07b66f4b7.jpeg" src="//5b0988e595225.cdn.sohucs.com/c_zoom,h_77/images/20171208/4b955cf5b33044e88584e0f07b66f4b7.jpeg" alt=""></div> <div class="picture"><i></i><img data-url="//5b0988e595225.cdn.sohucs.com/images/20171208/75a2e6dcdd714089a3503c3820bc2631.jpeg" src="//5b0988e595225.cdn.sohucs.com/c_zoom,h_77/images/20171208/75a2e6dcdd714089a3503c3820bc2631.jpeg" alt=""></div> <div class="picture"><i></i><img data-url="//5b0988e595225.cdn.sohucs.com/images/20171208/22d27f5cc0c54435a8bdbd2bb80f0f87.jpeg" src="//5b0988e595225.cdn.sohucs.com/c_zoom,h_77/images/20171208/22d27f5cc0c54435a8bdbd2bb80f0f87.jpeg" alt=""></div> <div class="picture"><i></i><img data-url="//5b0988e595225.cdn.sohucs.com/images/20171208/42e389e7c76a4dabae945ed91bf5e2de.jpeg" src="//5b0988e595225.cdn.sohucs.com/c_zoom,h_77/images/20171208/42e389e7c76a4dabae945ed91bf5e2de.jpeg" alt=""></div> <div class="picture"><i></i><img data-url="//5b0988e595225.cdn.sohucs.com/images/20171208/68652014966b4f53a0152af1c95dcdb7.jpeg" src="//5b0988e595225.cdn.sohucs.com/c_zoom,h_77/images/20171208/68652014966b4f53a0152af1c95dcdb7.jpeg" alt=""></div> <div class="picture"><i></i><img data-url="//5b0988e595225.cdn.sohucs.com/images/20171208/4c6ee145a6234594b8e081ad8831f8ba.jpeg" src="//5b0988e595225.cdn.sohucs.com/c_zoom,h_77/images/20171208/4c6ee145a6234594b8e081ad8831f8ba.jpeg" alt=""></div> </div> </div> <div class="slide-lr"> <span class="btn-pre"></span> <span class="btn-next"></span> </div> <div class="slide-explain"> <span class="btn-fold" title="隐藏"> <span class="bg-area"></span> <i class="icon fold-icon"></i> </span> <span class="btn-unfold hid" title="显示"> <span class="bg-area"></span> <i class="icon unfold-icon"></i> </span> <div class="explain"> <div class="bg-area"></div> <div class="pic-number"><em class="num">1</em>/<em class="total">12</em></div> <div class="pic-exp"> <h3>壮观!1180架无人机升空在广州塔前表演</h3> <p>12月7日晚,广州。在《祝酒歌》合唱歌声中,1180架无人机编队从海心沙飞起,亮灯形成“财富”两个汉字,现场市民齐齐仰头观看。此次无人机编队利用“科技舞蹈”,表达对2017广州某论坛的欢迎,给出席论坛的嘉宾带来惊喜。</p> <p class="hid">据悉,这是继2017年元宵节广州在海心沙创造的1000架无人机表演破吉尼斯世界纪录之后,带来的数量更多的无人机编队飞行表演。图为无人机拼凑“财富”二字。</p> <p class="hid">现场图。</p> <p class="hid">现场图。</p> <p class="hid">现场图。</p> <p class="hid">现场图。</p> <p class="hid">现场图。</p> <p class="hid">现场图。</p> <p class="hid">现场图。</p> </div> </div> </div> </div> </div></div> <div class="dsy-contentB area clearfix"> <div class="left main"><div class="article-oper clearfix"> <div class="article-oper-l left"> <span class="read-num">阅读 (<em data-role="pv" data-val="22"></em>)</span> </div> <div class="article-oper-r right"> <span class="uninterested" id="uninterested"></span> <a class="complain-link" target="_blank" href="http://quan.sohu.com/q/545c9b6bf6c43b5569fe64a2"><em class="complain-icon icon"></em>投诉</a> </div></div><div class="article-recom clear" id="sogou-words"></div> <div class="god-main" data-role="god_column"></div><div class="comment" id="comment_area"> <div id="mp-comment" sid="209151068"></div> </div> <div class="god-main" data-role="god_column"></div> </div> <div class="right sidebar"> <div class="bordR godR" data-role="godR"></div><div class="hot-article bordR clearfix" data-role='hot-news'></div> <div class="bordR godR" data-role="godR"></div> </div><div id="float-btn" class="float-links"></div> </div></div><script src="//statics.itc.cn/web/v3/static/js/lib-111eab4f1d.js"></script><!--<script src="//statics.itc.cn/web/v3/static/js/ie8hack-07e05e83f1.js"></script>--><script src="//txt.go.sohu.com/ip/soip"></script><script src="//statics.itc.cn/web/v3/static/js/main-2c6afe69e7.js"></script><script src="//js.sohu.com/pv.js"></script><script charset="utf8"> try { window.sohu_mp.pic_collections({ channel_id: "43", news_id: "209151068", back_url: "//www.sohu.com", media_id: "99984058", title: "壮观!1180架无人机升空在广州塔前表演", }) } catch (e) { var html = '<div class="err-js">' + '<span><em class="icon err-js-icon"></em>JS加载错误,请重新加载。</span>' + '<a href="javascript:window.location.reload()" target="_blank" class="cached-btn"' + '><em class="icon-cached"></em>刷新</a></div>'; $(document.body).prepend(html); console.log(e) // Raven.captureException(e); // 此处应捕获错误 }</script><!--[if lt IE 8]><script type="text/javascript">(function(){ var ua = navigator.userAgent; var version; var html = '<div class="area clear">' + '<div class="ie-low">' + '<p>您的浏览器版本过低<br>为了更好的体验,请升级你的浏览器。</p>' + '<h5><a href="https://ie.sogou.com" target="_blank" class="upgrade-btn">马上升级</a></h5>' + '</div></div>'; if (/MSIE ([^;]+)/.test(ua)) { version = parseInt(RegExp["$1"]); if (version<8) { document.body.innerHTML=html; var reg = new RegExp("(^| )SUV=([^;]*)(;|$)"); var suvs = unescape(document.cookie.match(reg)[2]); var spv_server_src = "http://pv.sohu.com/action.gif?actionId=10210078&SUV="+suvs; var scripts = document.createElement('script'); scripts.src = spv_server_src; document.body.appendChild(scripts); Raven.captureException(new Error('ie'+version)); } }})()</script><![endif]--></body></html> <script> document.domain = "sohu.com"; parent.passport200007278089333261106_cb1512742508288({"code":0,"data":"","msg":"登陆成功"});</script> jQuery112404914197299918357_1512742508303({"code":0,"data":{"avatar":"http://photo.pic.sohu.com/images/oldblog/person/11111.gif","isMpUser":0,"nickname":"狐狐网友"},"msg":"get userinfo success"}) ()
方法概要
限定符和类型 | 方法和说明 |
---|---|
void |
closeClient(boolean isInit)
关闭client连接对象 释放对象 并重新初始化
|
void |
closeHttpResponse()
关闭线程池,防止堵塞(这里需要手动调用,由于这里吧响应和请求封装在一个类了所以只能在外面手动调用释放)
|
void |
closeHttpResponse(org.apache.http.HttpEntity entity)
关闭线程池,防止堵塞(这里需要手动调用,由于这里吧响应和请求封装在一个类了所以只能在外面手动调用释放) 如果出现发送httpclient请求后一直无响应,应该是线程池占用完了,所以每次调用request后记得在finally手动调用本方法CloseHttpResponse
|
static javax.net.ssl.SSLContext |
createIgnoreVerifySSL()
绕过验证-HTTPS
|
org.apache.http.Header |
getContentType()
获取返回值的类型
|
java.lang.String |
getContentType(boolean isFormat)
获取响应的实体类型 并获取具体类型:jpeg/html/png/gif......
|
org.apache.http.client.methods.CloseableHttpResponse |
getHttpResponse() |
int |
getStatusCode()
获取返回值的状态 100 客户端可以继续 101 指示服务器正根据 Upgrade 头切换协议 200 请求正常成功 201 指示请求成功并在服务器上创建了一个新资源 202 指示已接受请求进行处理但处理尚未完成 203 指示客户端呈现的元信息并不源自服务器 204 指示请求成功但没有返回新信息 205 指示代理应该 重置导致请求被发送的文档视图 206 指示服务器已完成对资源的部分 GET 请求 300 请求的资源对应于表示形式集合中的某种表示形式,每种表示形式都有自己的特定位置 301 指示已经将资源永久地移动到了某个新位置,并且将来的引用应将新 URI 用于其请求 302 指示已经将资源暂时地移动到了另一个位置,但将来的引用仍应使用原来的 URI 访问该资源。
|
static java.util.Map<java.lang.String,java.lang.String> |
getUrlParams(java.lang.String param)
json url Transformation map json参数标准化为map对象
|
void |
initHttpClinet()
初始化clinet请求对象-并初始化HTTP/HTTPS两种协议
|
void |
initHttpRequest()
初始化htpclinet的请求对象
|
boolean |
isImage()
判断是否是图片类型的文件
|
boolean |
isImage(java.lang.String html)
判断是否是图片类型的文件
|
boolean |
isIP(java.lang.String addr)
判断是否为IP对象
|
java.lang.String |
msgException(java.lang.Exception e)
打印错误的异常详情
|
java.lang.String |
readLineInputStream(org.apache.http.HttpEntity httpEntity)
重载读取流
|
java.lang.String |
readLineInputStream(java.io.InputStream inputStream)
重载读取流
|
java.lang.String |
readLineInputStream(java.lang.String utf, org.apache.http.HttpEntity httpEntity)
重载读取流
|
java.lang.String |
readLineInputStream(java.lang.String utf, java.io.InputStream inputStream)
重载读取流
|
java.lang.String |
request()
请求数据并返回字符串类型
|
org.apache.http.HttpEntity |
request(java.lang.String url)
请求数据并返回一个数据实体
|
byte[] |
request(java.lang.String url, java.lang.Integer numBer)
请求并返回byte数组数据
|
java.lang.String |
request(java.lang.String url, java.lang.String utf)
请求数据并返回数据 自定义流转文本编码格式
|
void |
setAccept(java.lang.String accept)
客户端能够接收的内容类型
|
void |
setAutoSaveReferer(boolean autoSaveReferer)
自动保存上一个请求源 true 自动保存/false 不自动保存(默认)
|
void |
setConnectionRequestTimeout(int connectionRequestTimeout)
请求超时的时间 单位毫秒
|
void |
setConnectTimeout(int connectTimeout)
连接被阻塞超时 单位毫秒
|
void |
setContentType(java.lang.String contentType)
请求的与实体对应的MIME信息
|
void |
setCookie(java.lang.String cookie)
设置cookie
|
void |
setCredentials(java.lang.String userName, java.lang.String userPwd)
服务器认证信息
|
void |
setEntity(java.util.Map<java.lang.String,java.lang.String> params)
设置post请求参数 map
|
void |
setEntity(java.lang.String params)
设置post请求参数 string
|
void |
setEntity(org.apache.http.entity.StringEntity json)
设置post请求参数 map
|
void |
setHeader(java.util.Map<java.lang.String,java.lang.String> header)
设置Header
|
void |
setHeader(java.lang.String headerName, java.lang.String headerVal) |
void |
setHttpHost(java.lang.String hostVal)
设置HTTP请求代理模式 格式:127.0.0.0:8888
|
static void |
setMaxConnPerRoute(int maxConnPerRoute)
实际的单个连接池大小,如tps定为50,那就配置50
|
static void |
setMaxConnTotal(int maxConnTotal)
最大的请求连接数 注意:最大不要超过1000
|
void |
setMethod(java.lang.String method)
设置提交方式 get/post
|
void |
setOrigin(java.lang.String origin)
请求的来源-post使用,等同于Referer头
|
void |
setReferer(java.lang.String referer)
先前网页的地址
|
void |
setSocketTimeout(int socketTimeout)
服务器响应超时 单位毫秒
|
void |
setUserAgent(java.lang.String userAgent)
注明客户端请求的触发器版本
|
byte[] |
toByteArrays(java.io.InputStream in, java.lang.Integer numBer)
文件流转byte数组
|