http client 工具类
2018-07-20 来源:open-open
HttpConn
public class HttpConn {
private final static Logger logger = LoggerFactory.getLogger(HttpConn.class);
//MIME-TYPE
public static final String MIME_TYPE_PLAIN = "text/plain";
public static final String MIME_TYPE_XML = "text/xml";
public static final String MIME_TYPE_HTML = "text/html";
public static final String MIME_TYPE_JSON = "application/json";
//REQUEST METHOD
public static final String METHOD_GET = "GET";
public static final String METHOD_POST = "POST";
//HTTP STATUS
public static final int HTTP_RESSTATUS_SUCCESS = 200;
public static final int HTTP_RESSTATUS_NOT_FOUND = 404;
//Default Values
public static final String DETAULT_ENCODING = "UTF-8";
public static final Charset DEFAULT_CHARSET = Consts.UTF_8;
public static final int REQUEST_TIMEOUT = 5 * 1000; // 请求超时时间
public static final int CONNECTION_TIMEOUT = 10 * 1000; // 连接超时时间
public static final int SOCKET_TIMEOUT = 10 * 1000; // 数据传输超时
public static final int POOL_MAX_SIZE = 200; // 连接池最大连接数
public static final int POOL_MAX_SIZE_PER_ROUTER = 200; // 每个路由最大连接数
//Request Params
private String reqUrl;
private String reqMethod;
private Map<String, String> reqParams;//请求参数
private String reqPostString;//post内容
private String reqCharset;
private String reqContentType;//请求内容类型
private String reqFileKey;//上传文件在form-data的key值
private String reqFilePath;//上传的文件路径
//Response Infos
private int resCode;
private boolean resSuccess = false;//是否正常响应,即返回200
private String resStatues;
private long resLength;
private String resEncoding;
private String resContentType;
private String resBody;
private String resFilePath;
private boolean resFileSaveSuccess = false;//响应文件是否保存成功
//
private static PoolingHttpClientConnectionManager cm = null;
private static CloseableHttpClient client = null;
private HttpUriRequest request = null;
private CloseableHttpResponse response = null;
/**
* 初始化连接池与Client
* */
static{
try {
// 初始化SSL环境
SSLContextBuilder sslContextbuilder = new SSLContextBuilder();
sslContextbuilder.useTLS();
SSLContext sslContext = sslContextbuilder.loadTrustMaterial(null, new TrustStrategy() {
// 信任所有
public boolean isTrusted(X509Certificate[] chain, String authType) throws CertificateException
{
return true;
}
}).build();
//注册协议
ConnectionSocketFactory plainCSF = PlainConnectionSocketFactory.INSTANCE;
ConnectionSocketFactory sslCSF = new SSLConnectionSocketFactory(sslContext, SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory> create()
.register("http", plainCSF)
.register("https", sslCSF)
.build();
// 创建连接池
cm = new PoolingHttpClientConnectionManager(socketFactoryRegistry);
// 初始化Socket配置
SocketConfig socketConfig = SocketConfig.custom()
.setTcpNoDelay(true)
.build();
cm.setDefaultSocketConfig(socketConfig);
// Http消息约束
// MessageConstraints messageConstraints = MessageConstraints.custom().
// setMaxHeaderCount(200).
// setMaxLineLength(2000).build();
// http连接设置
ConnectionConfig connectionConfig = ConnectionConfig.custom()
.setMalformedInputAction(CodingErrorAction.IGNORE) //忽略不合法的输入
.setUnmappableInputAction(CodingErrorAction.IGNORE) //忽略不匹配的输入
.setCharset(DEFAULT_CHARSET)
// .setMessageConstraints(messageConstraints)
.build();
cm.setDefaultConnectionConfig(connectionConfig);
cm.setMaxTotal(POOL_MAX_SIZE); //连接池最大连接数
cm.setDefaultMaxPerRoute(POOL_MAX_SIZE_PER_ROUTER); //每个路由最大连接数
// 请求设置
RequestConfig requestConfig = RequestConfig.custom()
.setConnectionRequestTimeout(REQUEST_TIMEOUT) //请求超时
.setSocketTimeout(SOCKET_TIMEOUT) //Socket超时
.setConnectTimeout(CONNECTION_TIMEOUT) //连接超时
.build();
// 创建HttpClient
client = HttpClients.custom()
.disableRedirectHandling()
.setConnectionManager(cm)
.setDefaultRequestConfig(requestConfig)
.build();
// 启动连接池监控线程
HttpConnMonitorThread monitor = new HttpConnMonitorThread(cm);
monitor.start();
} catch (KeyManagementException e) {
logger.error("", e);
} catch (NoSuchAlgorithmException e) {
logger.error("", e);
} catch (KeyStoreException e) {
logger.error("", e);
}
}
/**
* 设置请求、连接、获取响应
* */
public boolean connect() throws ParseException, UnsupportedEncodingException, IOException {
try {
setReqInfo();
if(CommonUtil.isEmpty(this.request)){
throw new RuntimeException("HttpConn ,初始化请求失败!");
}
//执行连接,返回响应
HttpClientContext context = HttpClientContext.create();
this.response = client.execute(this.request, context);
//处理响应结果
if(CommonUtil.isEmpty(this.response)){
throw new RuntimeException("HttpConn ,响应获取失败!");
}
setResInfo();
} finally {
try {
if(this.response != null)
this.response.close();
} catch (IOException e) {
logger.error(e.getMessage());
}
}
return true;
}
/**
* 设置请求参数
* */
private void setReqInfo() throws ParseException, UnsupportedEncodingException, IOException{
if(!CommonUtil.isEmpty(this.reqFilePath))//上传,使用POST
this.reqMethod = METHOD_POST;
if(!CommonUtil.isEmpty(this.reqPostString))//post参数,使用POST
this.reqMethod = METHOD_POST;
if(CommonUtil.isEmpty(this.reqMethod))
this.reqMethod = METHOD_GET;
if(CommonUtil.isEmpty(this.reqContentType)) //设置内容类型,默认为text/plain
this.reqContentType = MIME_TYPE_PLAIN;
if(CommonUtil.isEmpty(this.reqCharset)) //设置编码格式
this.reqCharset = DETAULT_ENCODING;
//将请求参数转换为字符串形式
String paramString = null;
if(!CommonUtil.isEmpty(this.reqParams)){
List<NameValuePair> paramList = new ArrayList<NameValuePair>();
Iterator<Map.Entry<String, String>> it = this.reqParams.entrySet().iterator();
while(it.hasNext()){
Map.Entry<String, String> entry = it.next();
paramList.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));
}
paramString = EntityUtils.toString(new UrlEncodedFormEntity(paramList, this.reqCharset == null?DETAULT_ENCODING : this.reqCharset));
}
//GET请求
if(this.reqMethod.equalsIgnoreCase(METHOD_GET)){
//设置请求参数
if(!CommonUtil.isEmpty(paramString)){
if(this.reqUrl.trim().lastIndexOf("?") == -1){
this.reqUrl += "?" + paramString;
}else{
this.reqUrl += "&" + paramString;
}
}
//创建Get请求
HttpGet get = new HttpGet(this.reqUrl);
this.request = get;
}
//POST请求
else if(this.reqMethod.equals(METHOD_POST)){
HttpPost post = new HttpPost(this.reqUrl);
//post请求参数
if(!CommonUtil.isEmpty(this.reqPostString) || !CommonUtil.isEmpty(paramString)){
reqPostString = (reqPostString==null ? paramString : reqPostString);
StringEntity entity = null;
entity = new StringEntity(this.reqPostString, ContentType.create(this.reqContentType,this.reqCharset));
post.setEntity(entity);
}
//上传文件
else if(!CommonUtil.isEmpty(this.reqFilePath)){
MultipartEntityBuilder entityBuilder = MultipartEntityBuilder.create();
//以浏览器兼容模式运行,防止文件名乱码
entityBuilder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
// entityBuilder.setCharset(Consts.UTF_8);//设置编码格式
//设置文件信息
File uploadFile = new File(this.reqFilePath);
if(!uploadFile.exists()){
throw new RuntimeException("HttpConn:\""+reqFilePath+"\"路径不存在!");
}else{
if(CommonUtil.isEmpty(this.reqFileKey))
throw new RuntimeException("HttpConn: resFileKey为空!");
entityBuilder.addBinaryBody(this.reqFileKey, uploadFile);
}
//设置参数信息
if(!CommonUtil.isEmpty(this.reqParams)){
Iterator<Map.Entry<String, String>> it = this.reqParams.entrySet().iterator();
while(it.hasNext()){
Map.Entry<String, String> entry = it.next();
String key = entry.getKey();
StringBody body = new StringBody(entry.getValue(), ContentType.create("text/plain", DETAULT_ENCODING));
entityBuilder.addPart(key, body);
}
}
post.setEntity(entityBuilder.build());
}
this.request = post;
}
}
/**
* 处理响应数据
* @throws IllegalStateException
* @throws IOException
*/
private void setResInfo() throws IllegalStateException, IOException {
HttpEntity resEntity = this.response.getEntity();
//返回状态
this.resCode = this.response.getStatusLine().getStatusCode();
this.resStatues = this.response.getStatusLine().toString();
this.resLength = resEntity.getContentLength();
if(!CommonUtil.isEmpty(resEntity.getContentEncoding()))
this.resEncoding = resEntity.getContentEncoding().getValue();
if(this.resCode == HTTP_RESSTATUS_SUCCESS){
resSuccess = true;
//返回数据
this.resContentType = resEntity.getContentType().getValue();
if(CommonUtil.isEmpty(this.resEncoding)){
this.resEncoding = getEncoding(this.resContentType);
}
InputStream is = null;
FileOutputStream fos = null;
try{
is = resEntity.getContent();
//保存为文件
if(!CommonUtil.isEmpty(this.resFilePath)){
if(!CommonUtil.isFilePath(this.resFilePath)){
//从请求头获取文件名
String fileName = getValueFromHeader("Content-disposition", "filename");
if(fileName != null){
this.resFilePath += "_"+fileName;
}
}
File downFile = new File(this.resFilePath);
downFile.getParentFile().mkdirs();
fos = new FileOutputStream(downFile);
resEntity.writeTo(fos);
this.resFileSaveSuccess = true;
}
//保存为字符串
else{
if(CommonUtil.isEmpty(this.resEncoding))
this.resBody = EntityUtils.toString(resEntity, Consts.UTF_8);
else
this.resBody = EntityUtils.toString(resEntity, this.resEncoding);
}
}finally{
try {
if(is != null)
is.close();
if(fos != null)
fos.close();
} catch (Exception e) {
throw new RuntimeException("HttpConn : " + e.getMessage());
}
}
}else{
this.request.abort();//中止请求
throw new RuntimeException("HttpConn ,error status code : " + this.resCode);
}
//销毁
EntityUtils.consume(resEntity);
}
/**
* 从content-type获取编码格式
* @param contentType
* @return
*/
private String getEncoding(String contentType) {
String encoding = null;
int tmp = contentType.indexOf(";");
if(tmp > 0){
encoding = contentType.substring(tmp+1);
encoding = encoding.trim();
tmp = encoding.indexOf("=");
if(tmp > 0){
String[] entry = encoding.split("=");
if(entry[0].equalsIgnoreCase("charset") || entry[0].equalsIgnoreCase("encoding"))
encoding = entry[1].trim();
}
}
return encoding;
}
/**
* 从请求头中获取参数值
* @param headerName
* @param key
* @return
*/
private String getValueFromHeader(String headerName, String key) {
String value = null;
Header header = this.response.getFirstHeader(headerName);
if(!CommonUtil.isEmpty(header)){
if(CommonUtil.isEmpty(key)){
value = header.getValue();
}else{
HeaderElement[] elms = header.getElements();
for(HeaderElement elm : elms){
NameValuePair pair = elm.getParameterByName(key);
if(pair != null){
value = pair.getValue();
break;
}
}
}
}
return value;
}
public void setReqFilePath(String reqFileKey, String reqFilePath) {
this.reqFileKey = reqFileKey;
this.reqFilePath = reqFilePath;
}
public int getResCode() {
return resCode;
}
public String getResStatues() {
return resStatues;
}
public String getResType() {
return resContentType;
}
public String getResBody() {
return resBody;
}
public void setReqUrl(String reqUrl) {
this.reqUrl = reqUrl;
}
public void setReqMethod(String reqMethod) {
this.reqMethod = reqMethod;
}
public void setReqParams(Map<String, String> reqParams) {
this.reqParams = reqParams;
}
public void setReqPostString(String reqPostString) {
this.reqPostString = reqPostString;
}
public void setReqContentType(String reqContentType) {
this.reqContentType = reqContentType;
}
public void setResFilePath(String resFilePath) {
this.resFilePath = resFilePath;
}
public long getResLength() {
return resLength;
}
public String getResEncoding() {
return resEncoding;
}
public String getResContentType() {
return resContentType;
}
public boolean isResFileSaveSuccess() {
return resFileSaveSuccess;
}
public void setReqCharset(String reqCharset) {
this.reqCharset = reqCharset;
}
public boolean isResSuccess() {
return resSuccess;
}
public void setResSuccess(boolean resSuccess) {
this.resSuccess = resSuccess;
}
}
HttpConnMonitorThread
public class HttpConnMonitorThread extends Thread{
private final static Logger logger = LoggerFactory.getLogger(HttpConnMonitorThread.class);
private final HttpClientConnectionManager cm;
private volatile boolean shutdown;
private final static int WATING_TIME = 60 * 1000; // 轮询时间
private final static int IDLE_TIME = 30; // 空闲时间
public HttpConnMonitorThread(HttpClientConnectionManager cm) {
super();
this.cm = cm;
}
@Override
public void run() {
try {
while (!shutdown) {
synchronized (this) {
wait(WATING_TIME);
// 关闭过期连接
cm.closeExpiredConnections();
logger.info(">>>>>close expired connections.");
// 关闭空闲连接
cm.closeIdleConnections(IDLE_TIME, TimeUnit.SECONDS);
logger.info(">>>>>close idle connections.");
}
}
} catch (InterruptedException ex) {
logger.error("HttpConn Monitor error! ", ex);
}
}
/**
* 关闭轮询
*/
public void shutdown() {
shutdown = true;
synchronized (this) {
notifyAll();
}
}
}
版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com
特别注意:本站所有转载文章言论不代表本站观点!
本站所提供的图片等素材,版权归原作者所有,如需使用,请与原作者联系。
上一篇:android判断横竖屏
最新资讯
热门推荐