/**
* @ProjectName: 智能建筑
* @Copyright: 2012 HangZhou Hikvision System Technology Co., Ltd. All Right Reserved.
* @address: http://www.hikvision.com
* @date: Oct 31, 2014 1:36:15 PM
* @Description: 本内容仅限于杭州海康威视数字技术系统公司内部使用,禁止转发.
*/
package com.hikvision.cms.common.util;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.nio.charset.Charset;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import org.apache.commons.httpclient.DefaultHttpMethodRetryHandler;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpException;
import org.apache.commons.httpclient.HttpMethod;
import org.apache.commons.httpclient.HttpStatus;
import org.apache.commons.httpclient.methods.DeleteMethod;
import org.apache.commons.httpclient.methods.EntityEnclosingMethod;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.methods.PutMethod;
import org.apache.commons.httpclient.methods.RequestEntity;
import org.apache.commons.httpclient.methods.StringRequestEntity;
import org.apache.commons.httpclient.params.HttpMethodParams;
import org.apache.commons.httpclient.protocol.Protocol;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.util.StreamUtils;
import com.hikvision.cms.common.config.PropertiesReader;
import com.hikvision.cms.common.util.coder.MD5Util;
import com.hikvision.cms.common.util.json.JsonUtils;
/**
* <p>
* </p>
*
* @author fanghuaichang Oct 31, 2014 1:36:15 PM
* @version V1.0
* @modificationHistory=========================逻辑或功能性重大变更记录
* @modify by user: {修改人} Oct 31, 2014
* @modify by reason:{方法名}:{原因}
*/
public class HttpClientUtils {
// 连接超时
protected static final Integer DEFAULT_CONNECTION_TIME_OUT = 2000;
// 读取超时
protected static final Integer DEFAULT_SOCKET_TIME_OUT = 5000;
//最大读取超时时间
protected static final Integer MAX_SOCKET_TIME_OUT = 80000;
//Default HttpServletRequest's header contentType value
protected static final String DEFAULT_CONTENT_TYPE = "application/json";
public static final String XML_CONTENT_TYPE = "application/xml";
protected static final String DEFAULT_CHAR_SET = "UTF-8";
private static String getDefaultSecretKey(){
return PropertiesReader.getProperty("http.intf.passport.secretKey");
}
/**
*
* @author fanghuaichang 2015年7月2日 下午6:14:21
* @param connectionTimeout
* @param socketTimeout
* @modificationHistory=========================逻辑或功能性重大变更记录
* @modify by user: {修改人} 2015年7月2日
* @modify by reason:{原因}
*/
protected static void checkTimeoutParameter(Integer connectionTimeout, Integer socketTimeout){
if (connectionTimeout == null || connectionTimeout < 0 || connectionTimeout > DEFAULT_CONNECTION_TIME_OUT){
throw new IllegalArgumentException("connectionTimeout should between [0," + DEFAULT_CONNECTION_TIME_OUT+"] ms");
}
if (socketTimeout == null || socketTimeout < 0 || socketTimeout > MAX_SOCKET_TIME_OUT){
throw new IllegalArgumentException("socketTimeout should between [0," + MAX_SOCKET_TIME_OUT+"] ms");
}
}
/**
*
* @author fanghuaichang 2015年7月2日 下午6:05:35
* @param connectionTimeout
* @param socketTimeout
* @return
* @modificationHistory=========================逻辑或功能性重大变更记录
* @modify by user: {修改人} 2015年7月2日
* @modify by reason:{原因}
*/
protected static HttpClient createHttpClient(Integer connectionTimeout, Integer socketTimeout){
HttpClient httpClient = new HttpClient();
httpClient.getHttpConnectionManager().getParams().setConnectionTimeout(connectionTimeout);
httpClient.getHttpConnectionManager().getParams().setSoTimeout(socketTimeout);
return httpClient;
}
/**
* 设置网路连接策略:禁用掉网络不通时的 三次连接 尝试过程
* @author fanghuaichang 2015年5月5日 下午7:13:55
* @param httpMethod
* @modificationHistory=========================逻辑或功能性重大变更记录
* @modify by user: {修改人} 2015年5月5日
* @modify by reason:{原因}
*/
protected static void setHttpMethodRetryHandler(HttpMethod httpMethod){
httpMethod.getParams().setParameter(HttpMethodParams.RETRY_HANDLER, new DefaultHttpMethodRetryHandler(0, false));
}
/**
*
* @author fanghuaichang 2015年6月29日 下午5:26:15
* @param jsonText
* @param contentType
* @param charSet
* @return
* @modificationHistory=========================逻辑或功能性重大变更记录
* @modify by user: {修改人} 2015年6月29日
* @modify by reason:{原因}
*/
protected static RequestEntity createStringRequestEntity(String jsonText, String contentType, String charSet){
RequestEntity requestEntity = null;
try {
requestEntity = new StringRequestEntity(jsonText, contentType, charSet);
} catch (UnsupportedEncodingException e) {
// we can ignore it
}
return requestEntity;
}
/**
*
* @author fanghuaichang 2015年6月30日 下午4:57:39
* @param url
* @param secretKey
* @return
* @modificationHistory=========================逻辑或功能性重大变更记录
* @modify by user: {修改人} 2015年6月30日
* @modify by reason:{原因}
*/
protected static String generateUrlWithToken(String url, String secretKey){
// token value = Md5(url + secretKey);
url = formatUrl(url);
String token = MD5Util.md5(url + secretKey);
if (url.indexOf("?") != -1){
return url + "&token=" + token;
}
return url + "?token=" + token;
}
protected static String formatUrl(String url){
String tempUrl = null;
String URI = null;
if (url.startsWith("http://")){
tempUrl = url.substring("http://".length());
int index = tempUrl.indexOf("/");
URI = tempUrl.substring(index);
String ipPort = tempUrl.substring(0, index);
String[] ipPortSplitArray = ipPort.split(":");
if (ipPortSplitArray.length <= 1){
return "http://" + ipPort + URI;
} else {
if ("80".equals(ipPortSplitArray[1])){
ipPort = ipPort.replace(":80", "");
}
return "http://" + ipPort + URI;
}
}
if (url.startsWith("https://")){
tempUrl = url.substring("https://".length());
int index = tempUrl.indexOf("/");
URI = tempUrl.substring(index);
String ipPort = tempUrl.substring(0, index);
String[] ipPortSplitArray = ipPort.split(":");
if (ipPortSplitArray.length <= 1){
return "https://" + ipPort + URI;
} else {
if("443".equals(ipPortSplitArray[1])){
ipPort = ipPort.replace(":443", "");
}
return "https://" + ipPort + URI;
}
}
return url;
}
/**
*
* @author fanghuaichang 2015年6月29日 下午5:13:35
* @param url
* @param shm
* @param jsonText
* @return
* @throws HttpException
* @modificationHistory=========================逻辑或功能性重大变更记录
* @modify by user: {修改人} 2015年6月29日
* @modify by reason:{原因}
*/
protected static String doExecuteMethod(String url, SupportHttpMethod shm, String jsonText, String secretKey,
Integer connectionTimeout, Integer socketTimeout) throws HttpException{
if (StringUtils.isEmpty(url)){
throw new NullPointerException("Parameter url should not be null");
}
if (secretKey != null){
url = generateUrlWithToken(url, secretKey);
}
String content = null;
Protocol.registerProtocol("https",new Protocol("https", new MySSLProtocolSocketFactory(), 443));
HttpClient httpClient = createHttpClient(connectionTimeout, socketTimeout);
HttpMethod httpMethod = null;
EntityEnclosingMethod entityEnclosingMethod = null;
/*try {
url = URLEncoder.encode(url, DEFAULT_CHAR_SET);
} catch (UnsupportedEncodingException e1) {
//ignore it
}*/
if (shm == SupportHttpMethod.Get){
httpMethod = new GetMethod(url);
} else if (shm == SupportHttpMethod.Del){
httpMethod = new DeleteMethod(url);
} else if (shm == SupportHttpMethod.Post){
entityEnclosingMethod = new PostMethod(url);
RequestEntity requestEntity = createStringRequestEntity(jsonText, DEFAULT_CONTENT_TYPE, DEFAULT_CHAR_SET);
entityEnclosingMethod.setRequestEntity(requestEntity);
} else {
entityEnclosingMethod = new PutMethod(url);
RequestEntity requestEntity = createStringRequestEntity(jsonText, DEFAULT_CONTENT_TYPE, DEFAULT_CHAR_SET);
entityEnclosingMethod.setRequestEntity(requestEntity);
}
// 设置网路重连策略
setHttpMethodRetryHandler(httpMethod != null ? httpMethod : entityEnclosingMethod);
InputStream inputStream = null;
try {
// 执行method
int responseCode = httpClient.executeMethod(httpMethod != null ? httpMethod : entityEnclosingMethod);
if (responseCode != HttpStatus.SC_OK) {
throw new HttpException("HttpClientUtils execute Method failed responseCode:" + responseCode);
}
//It is strongly recommended, to use getResponseAsStream if the content length of the response
//is unknown or resonably large.
inputStream = httpMethod != null ? httpMethod.getResponseBodyAsStream() : entityEnclosingMethod.getResponseBodyAsStream();
content = StreamUtils.copyToString(inputStream, Charset.forName(DEFAULT_CHAR_SET));
} catch (Exception e) {
throw new HttpException("HttpClientUtils execute Method failed url:[" + url + "] error", e);
} finally {
if (httpMethod != null) {
httpMethod.releaseConnection();
}
if (entityEnclosingMethod != null){
entityEnclosingMethod.releaseConnection();
}
IOUtils.closeQuietly(inputStream);
}
return content;
}
private static String doExecuteMethod(String url, SupportHttpMethod shm, String text, String secretKey,
Integer connectionTimeout, Integer socketTimeout, String contentType) throws HttpException{
if (StringUtils.isEmpty(url)){
throw new NullPointerException("Parameter url should not be null");
}
if (secretKey != null){
url = generateUrlWithToken(url, secretKey);
}
String content = null;
Protocol.registerProtocol("https",new Protocol("https", new MySSLProtocolSocketFactory(), 443));
HttpClient httpClient = createHttpClient(connectionTimeout, socketTimeout);
HttpMethod httpMethod = null;
EntityEnclosingMethod entityEnclosingMethod = null;
if (shm == SupportHttpMethod.Get){
httpMethod = new GetMethod(url);
} else if (shm == SupportHttpMethod.Del){
httpMethod = new DeleteMethod(url);
} else if (shm == SupportHttpMethod.Post){
entityEnclosingMethod = new PostMethod(url);
RequestEntity requestEntity = createStringRequestEntity(text, contentType, DEFAULT_CHAR_SET);
entityEnclosingMethod.setRequestEntity(requestEntity);
} else {
entityEnclosingMethod = new PutMethod(url);
RequestEntity requestEntity = createStringRequestEntity(text, contentType, DEFAULT_CHAR_SET);
entityEnclosingMethod.setRequestEntity(requestEntity);
}
// 设置网路重连策略
setHttpMethodRetryHandler(httpMethod != null ? httpMethod : entityEnclosingMethod);
InputStream inputStream = null;
try {
// 执行method
int responseCode = httpClient.executeMethod(httpMethod != null ? httpMethod : entityEnclosingMethod);
if (responseCode != HttpStatus.SC_OK) {
throw new HttpException("HttpClientUtils execute Method failed responseCode:" + responseCode);
}
//It is strongly recommended, to use getResponseAsStream if the content length of the response
//is unknown or resonably large.
inputStream = httpMethod != null ? httpMethod.getResponseBodyAsStream() : entityEnclosingMethod.getResponseBodyAsStream();
content = StreamUtils.copyToString(inputStream, Charset.forName(DEFAULT_CHAR_SET));
} catch (Exception e) {
throw new HttpException("HttpClientUtils execute Method failed url:[" + url + "] error", e);
} finally {
if (httpMethod != null) {
httpMethod.releaseConnection();
}
if (entityEnclosingMethod != null){
entityEnclosingMethod.releaseConnection();
}
IOUtils.closeQuietly(inputStream);
}
return content;
}
/**
* Get resource by url
* @author fanghuaichang 2015年5月5日 下午6:41:16
* @param url
* @return
* @throws HttpException
* @modificationHistory=========================逻辑或功能性重大变更记录
* @modify by user: {修改人} 2015年5月5日
* @modify by reason:{原因}
*/
public static String doGet(String url) throws HttpException {
return doGet(url, DEFAULT_CONNECTION_TIME_OUT, DEFAULT_SOCKET_TIME_OUT);
}
/**
*
* @author fanghuaichang 2015年7月2日 下午6:09:52
* @param url
* @param connectionTimeout
* @param socketTimeout
* @return
* @modificationHistory=========================逻辑或功能性重大变更记录
* @modify by user: {修改人} 2015年7月2日
* @modify by reason:{原因}
*/
public static String doGet(String url, Integer connectionTimeout, Integer socketTimeout) throws HttpException {
checkTimeoutParameter(connectionTimeout, socketTimeout);
return doExecuteMethod(url, SupportHttpMethod.Get, null, null, connectionTimeout, socketTimeout);
}
/**
*
* @author fanghuaichang 2015年6月30日 下午4:26:03
* @param url
* @param secretKey
* @return
* @throws HttpException
* @modificationHistory=========================逻辑或功能性重大变更记录
* @modify by user: {修改人} 2015年6月30日
* @modify by reason:{原因}
*/
public static String doGet(String url, String secretKey) throws HttpException{
return doGet(url, secretKey, DEFAULT_CONNECTION_TIME_OUT, DEFAULT_SOCKET_TIME_OUT);
}
/**
*
* @author fanghuaichang 2015年7月2日 下午6:34:29
* @param url
* @param secretKey
* @param connectionTimeout
* @param socketTimeout
* @return
* @throws HttpException
* @modificationHistory=========================逻辑或功能性重大变更记录
* @modify by user: {修改人} 2015年7月2日
* @modify by reason:{原因}
*/
public static String doGet(String url, String secretKey, Integer connectionTimeout, Integer socketTimeout) throws HttpException{
if (StringUtils.isEmpty(secretKey)){
throw new IllegalArgumentException("secretKey should not be null!");
}
checkTimeoutParameter(connectionTimeout, socketTimeout);
return doExecuteMethod(url, SupportHttpMethod.Get, null, secretKey, connectionTimeout, socketTimeout);
}
/**
*
* <p></p>
* @author fanghuaichang
* @version V1.0
* @date 2015年8月6日 下午4:04:35
* @param url
* @return
* @throws HttpException
*
* @modificationHistory=========================逻辑或功能性重大变更记录
* @modify by user: {修改人} 2015年8月6日
* @modify by reason:{方法名}:{原因}
* @since
*/
public static String doGetDefaultSecurity(String url) throws HttpException{
return doGet(url, getDefaultSecretKey());
}
/**
*
* <p></p>
* @author fanghuaichang
* @version V1.0
* @date 2015年8月6日 下午4:05:53
* @param url
* @param connectionTimeout
* @param socketTimeout
* @return
* @throws HttpException
*
* @modificationHistory=========================逻辑或功能性重大变更记录
* @modify by user: {修改人} 2015年8月6日
* @modify by reason:{方法名}:{原因}
* @since
*/
public static String doGetDefaultSecurity(String url, Integer connectionTimeout, Integer socketTimeout) throws HttpException{
return doGet(url, getDefaultSecretKey(), connectionTimeout, socketTimeout);
}
/**
* Add resource by url
* @author fanghuaichang 2015年5月5日 下午8:17:41
* @param url
* @param jsonText: a json string
* @return
* @throws HttpException
* @modificationHistory=========================逻辑或功能性重大变更记录
* @modify by user: {修改人} 2015年5月5日
* @modify by reason:{原因}
*/
public static String doPost(String url, String jsonText) throws HttpException {
return doPost(url, jsonText, DEFAULT_CONNECTION_TIME_OUT, DEFAULT_SOCKET_TIME_OUT);
}
public static String doContentTypePost(String url, String text, String contentType) throws HttpException {
return doPost(url, text, DEFAULT_CONNECTION_TIME_OUT, DEFAULT_SOCKET_TIME_OUT, contentType);
}
/**
*
* @author fanghuaichang 2015年7月2日 下午6:28:46
* @param url
* @param jsonText
* @param connectionTimeout 单位:ms
* @param socketTimeout 单位:ms
* @return
* @throws HttpException
* @modificationHistory=========================逻辑或功能性重大变更记录
* @modify by user: {修改人} 2015年7月2日
* @modify by reason:{原因}
*/
public static String doPost(String url, String jsonText, Integer connectionTimeout, Integer socketTimeout) throws HttpException {
if (StringUtils.isEmpty(jsonText)){
throw new IllegalArgumentException("doPost method jsonText should not be empty!");
}
checkTimeoutParameter(connectionTimeout, socketTimeout);
return doExecuteMethod(url, SupportHttpMethod.Post, jsonText, null, connectionTimeout, socketTimeout);
}
public static String doPost(String url, String text, Integer connectionTimeout, Integer socketTimeout, String contentType) throws HttpException {
if (StringUtils.isEmpty(text)){
throw new IllegalArgumentException("doPost method jsonText should not be empty!");
}
checkTimeoutParameter(connectionTimeout, socketTimeout);
return doExecuteMethod(url, SupportHttpMethod.Post, text, null, connectionTimeout, socketTimeout, contentType);
}
/**
*
* @author fanghuaichang 2015年6月30日 下午4:32:42
* @param url
* @param jsonText
* @param secretKey
* @return
* @throws HttpException
* @modificationHistory=========================逻辑或功能性重大变更记录
* @modify by user: {修改人} 2015年6月30日
* @modify by reason:{原因}
*/
public static String doPost(String url, String jsonText, String secretKey) throws HttpException {
return doPost(url, jsonText, secretKey, DEFAULT_CONNECTION_TIME_OUT, DEFAULT_SOCKET_TIME_OUT);
}
/**
*
* @author fanghuaichang 2015年7月2日 下午6:30:25
* @param url
* @param jsonText
* @param secretKey
* @param connectionTimeout 单位:ms
* @param socketTimeout 单位:ms
* @return
* @throws HttpException
* @modificationHistory=========================逻辑或功能性重大变更记录
* @modify by user: {修改人} 2015年7月2日
* @modify by reason:{原因}
*/
public static String doPost(String url, String jsonText, String secretKey, Integer connectionTimeout, Integer socketTimeout) throws HttpException {
if (StringUtils.isEmpty(jsonText)){
throw new IllegalArgumentException("doPost method jsonText should not be empty!");
}
if (StringUtils.isEmpty(secretKey)){
throw new IllegalArgumentException("secretKey should not be null!");
}
checkTimeoutParameter(connectionTimeout, socketTimeout);
return doExecuteMethod(url, SupportHttpMethod.Post, jsonText, secretKey, connectionTimeout, socketTimeout);
}
/**
*
* <p></p>
* @author fanghuaichang
* @version V1.0
* @date 2015年8月6日 下午4:11:15
* @param url
* @param jsonText
* @return
* @throws HttpException
*
* @modificationHistory=========================逻辑或功能性重大变更记录
* @modify by user: {修改人} 2015年8月6日
* @modify by reason:{方法名}:{原因}
* @since
*/
public static String doPostDefaultSecurity(String url, String jsonText) throws HttpException {
return doPost(url, jsonText, getDefaultSecretKey(), DEFAULT_CONNECTION_TIME_OUT, DEFAULT_SOCKET_TIME_OUT);
}
/**
*
* <p></p>
* @author fanghuaichang
* @version V1.0
* @date 2015年8月26日 下午2:55:55
* @param url
* @return
* @throws HttpException
*
* @modificationHistory=========================逻辑或功能性重大变更记录
* @modify by user: {修改人} 2015年8月26日
* @modify by reason:{方法名}:{原因}
* @since
*/
public static String doPostDefaultSecurity(String url) throws HttpException{
Map<String, String> hashMap = new HashMap<String, String>();
hashMap.put("key", "value");
return doPostDefaultSecurity(url, JsonUtils.object2Json(hashMap));
}
public static String doPostDefaultSecurity(String url,int connectTimeout,int socketTimeout) throws HttpException{
Map<String, String> hashMap = new HashMap<String, String>();
hashMap.put("key", "value");
return doPostDefaultSecurity(url,JsonUtils.object2Json(hashMap),connectTimeout,socketTimeout);
}
/**
*
* <p></p>
* @author fanghuaichang
* @version V1.0
* @date 2015年8月6日 下午4:11:47
* @param url
* @param jsonText
* @param connectionTimeout
* @param socketTimeout
* @return
* @throws HttpException
*
* @modificationHistory=========================逻辑或功能性重大变更记录
* @modify by user: {修改人} 2015年8月6日
* @modify by reason:{方法名}:{原因}
* @since
*/
public static String doPostDefaultSecurity(String url, String jsonText, Integer connectionTimeout, Integer socketTimeout) throws HttpException {
return doPost(url, jsonText, getDefaultSecretKey(), connectionTimeout, socketTimeout);
}
/**
*
* @author fanghuaichang 2015年6月15日 下午4:27:02
* @param request
* @param closeStream
* @return
* @throws HttpException
* @modificationHistory=========================逻辑或功能性重大变更记录
* @modify by user: {修改人} 2015年6月15日
* @modify by reason:{原因}
*/
public static String getRequestData(HttpServletRequest request)throws HttpException{
if (request == null){
throw new NullPointerException("HttpServletRequest is null!");
}
InputStream inputStream = null;
byte[] bytes = new byte[1024];
int line = 0;
StringBuffer buffer = new StringBuffer();
try {
inputStream = request.getInputStream();
while ((line = inputStream.read(bytes)) != -1){
buffer.append(new String(bytes, 0, line, "UTF-8"));
}
} catch (Exception e){
throw new HttpException("HttpClientUtils getRequestData error", e);
} finally{
if (inputStream != null){
try {
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return buffer.toString();
}
}
enum SupportHttpMethod{
Get, Post, Put,Del
}