1、code
package top.zywork.common;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.NameValuePair;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.CookieStore;
import org.apache.http.client.ResponseHandler;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.cookie.Cookie;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.entity.mime.content.FileBody;
import org.apache.http.entity.mime.content.StringBody;
import org.apache.http.impl.client.BasicCookieStore;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import top.zywork.enums.CharsetEnum;
import top.zywork.enums.ContentTypeEnum;
import top.zywork.enums.MIMETypeEnum;
import java.io.File;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.*;
/**
* Http操作类,主要用于发送get或post请求,对HttpClient的封装
*
* @author 危锦辉
* @version 1.0
*/
public class HttpUtils {
private static final Logger logger = LoggerFactory.getLogger(HttpUtils.class);
private static final HttpGet NONE_GET = null;
private static final HttpPost NONE_POST = null;
/**
* 用于接收服务端返回的cookies数据
*/
private static List cookies;
private static RequestConfig requestConfig = RequestConfig.custom()
.setSocketTimeout(15000)
.setConnectTimeout(15000)
.setConnectionRequestTimeout(15000)
.build();
/**
* HTTP GET请求访问指定的url
*
* @param url url,包括查询字符串
* @return 指定url所返回的字符串数据
*/
public static String get(String url) {
return send(new HttpGet(url), NONE_POST, stringResponseHandler);
}
/**
* HTTP POST请求访问指定的url
*
* @param url url,可包含查询字符串
* @return 指定url所返回的字符串数据
*/
public static String post(String url) {
return send(NONE_GET, new HttpPost(url), stringResponseHandler);
}
/**
* HTTP POST请求访问指定的url
*
* @param url url,可包含查询字符串
* @param params post请求发送的参数,参数为param1=value1¶m2=value2形式
* @return 请求返回相应的字符串数据
*/
public static String post(String url, String params) {
HttpPost httpPost = new HttpPost(url);
StringEntity stringEntity = new StringEntity(params, CharsetEnum.UTF8.getValue());
stringEntity.setContentType(ContentTypeEnum.FORM_URLENCODED.getValue());
httpPost.setEntity(stringEntity);
return send(NONE_GET, httpPost, stringResponseHandler);
}
/**
* HTTP POST请求访问指定的url
*
* @param url url,可包含查询字符串
* @param params key-value结构的参数
* @return 指定url响应的字符串数据
*/
public static String post(String url, Map params) {
HttpPost httpPost = new HttpPost(url);
List nameValuePairs = new ArrayList<>();
Set> entrySet = params.entrySet();
for (Map.Entry entry : entrySet) {
nameValuePairs.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));
}
try {
httpPost.setEntity(new UrlEncodedFormEntity(nameValuePairs, CharsetEnum.UTF8.getValue()));
} catch (UnsupportedEncodingException e) {
logger.error("http post not supported encoding: {}", e.getMessage());
}
return send(NONE_GET, httpPost, stringResponseHandler);
}
/**
* HTTP POST请求访问指定的url
*
* @param url url,可包含查询字符串
* @param params key-value结构的参数
* @param cookieList 需要提交到服务端的cookie数据,如果为null,则不提交cookie
* @param getCookie 判断是否需要从服务端获取cookie数据
* @return 指定url响应的字符串数据
*/
public static String post(String url, Map params, List cookieList, boolean getCookie) {
HttpPost httpPost = new HttpPost(url);
List nameValuePairs = new ArrayList<>();
Set> entrySet = params.entrySet();
for (Map.Entry entry : entrySet) {
nameValuePairs.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));
}
try {
httpPost.setEntity(new UrlEncodedFormEntity(nameValuePairs, CharsetEnum.UTF8.getValue()));
} catch (UnsupportedEncodingException e) {
logger.error("http post not supported encoding: {}", e.getMessage());
}
return send(NONE_GET, httpPost, cookieList, getCookie, stringResponseHandler);
}
/**
* 通过post请求上传单个文件
*
* @param url 请求地址,可包含查询字符串
* @param params 请求参数
* @param inputName 上传文件的input name
* @param filePath 上传文件的完整路径
* @return 请求响应返回的字符串数据
*/
public static String post(String url, Map params, String inputName, String filePath) {
return post(url, params, inputName, new File(filePath));
}
/**
* 通过post请求上传单个文件
*
* @param url 请求地址,可包含查询字符串
* @param params 请求参数
* @param inputName 上传文件的input name
* @param file 上传的文件,为File类型
* @return 请求响应返回的字符串数据
*/
public static String post(String url, Map params, String inputName, File file) {
Map files = new HashMap<>(1);
files.put(inputName, file);
return post(url, params, files);
}
/**
* 通过post请求上传多个文件
*
* @param url 请求地址,可包含查询字符串
* @param params 请求参数
* @param files 上传的文件,为Map结构,键为上传文件时对应的input name,值为File类型的文件
* @return 请求响应返回的字符串数据
*/
public static String post(String url, Map params, Map files) {
HttpPost httpPost = new HttpPost(url);
MultipartEntityBuilder multipartEntityBuilder = MultipartEntityBuilder.create();
Set> paramEntrySet = params.entrySet();
for (Map.Entry entry : paramEntrySet) {
multipartEntityBuilder.addPart(entry.getKey(), new StringBody(entry.getValue(), ContentType.TEXT_PLAIN));
}
Set> fileEntrySet = files.entrySet();
for (Map.Entry entry : fileEntrySet) {
multipartEntityBuilder.addPart(entry.getKey(), new FileBody(entry.getValue()));
}
HttpEntity entity = multipartEntityBuilder.build();
httpPost.setEntity(entity);
return send(NONE_GET, httpPost, stringResponseHandler);
}
/**
* 提交json格式数据到指定url
*
* @param url url,可包含查询字符中
* @param json json格式的字符串数据
* @return 指定url响应的字符串数据
*/
public static String postJSON(String url, String json) {
return post(url, json, MIMETypeEnum.JSON);
}
/**
* 提交xml格式数据到指定url
*
* @param url url,可以包含查询字符串
* @param xml xml格式的字符串数据
* @return 指定url响应的字符串数据
*/
public static String postXML(String url, String xml) {
return post(url, xml, MIMETypeEnum.XML);
}
/**
* 通过指定的数据类型把数据post提交到指定的url
*
* @param url url,可以包含查询字符串
* @param data 需要提交的数据
* @param dataTypeEnum 提交数据的MIME type
* @return 指定url响应的字符串数据
*/
public static String post(String url, String data, MIMETypeEnum dataTypeEnum) {
HttpPost httpPost = new HttpPost(url);
httpPost.addHeader("Content-type", dataTypeEnum.getMime() + "; charset=" + CharsetEnum.UTF8.getValue());
httpPost.addHeader("Accept", dataTypeEnum.getMime());
httpPost.setEntity(new StringEntity(data, CharsetEnum.UTF8.getValue()));
return send(NONE_GET, httpPost, stringResponseHandler);
}
/**
* 通过指定的数据类型把数据post提交到指定的url
*
* @param url url,可以包含查询字符串
* @param data 需要提交的数据
* @param dataTypeEnum 提交数据的MIME type
* @param cookieList 提交到服务端的cookie数据
* @param getCookie 是否需要从服务端获取cookie数据
* @return 指定url响应的字符串数据,并获取由服务端返回的cookie数据
*/
public static String post(String url, String data, MIMETypeEnum dataTypeEnum, List cookieList, boolean getCookie) {
HttpPost httpPost = new HttpPost(url);
httpPost.addHeader("Content-type", dataTypeEnum.getMime() + "; charset=" + CharsetEnum.UTF8.getValue());
httpPost.addHeader("Accept", dataTypeEnum.getMime());
httpPost.setEntity(new StringEntity(data, CharsetEnum.UTF8.getValue()));
return send(NONE_GET, httpPost, cookieList, getCookie, stringResponseHandler);
}
/**
* 发送HTTP请求,请求方式可以是GET,也可以是POST,并且需要指定相应的ResponseHandler
*
* @param httpGet 如果是GET请求,则传入HttpGet对象,如果为null,表示不使用GET请求
* @param httpPost 如果是POST请求,则传入HttpPost对象,如果为null,表示不使用POST请求
* @param responseHandler ResponseHandler响应处理对象
* @param 响应处理对象中可通过泛型来指定返回的具体数据类型
* @return 通过在ResponseHandler中指定的具体类型来返回响应数据
*/
private static T send(HttpGet httpGet, HttpPost httpPost, ResponseHandler responseHandler) {
CloseableHttpClient httpClient = HttpClients.createDefault();
T t = null;
try {
if (httpGet != null) {
httpGet.setConfig(requestConfig);
t = httpClient.execute(httpGet, responseHandler);
} else {
httpPost.setConfig(requestConfig);
t = httpClient.execute(httpPost, responseHandler);
}
} catch (IOException e) {
logger.error("http client execute error: {}", e.getMessage());
} finally {
try {
httpClient.close();
} catch (IOException e) {
logger.error("http client close error: {}", e.getMessage());
}
}
return t;
}
/**
* 获取服务端返回的cookie数据
*
* @return 服务端返回的cookie数据
*/
public static List getCookies() {
return cookies;
}
/**
* 发送HTTP请求,请求方式可以是GET,也可以是POST,并且需要指定相应的ResponseHandler
*
* @param httpGet 如果是GET请求,则传入HttpGet对象,如果为null,表示不使用GET请求
* @param httpPost 如果是POST请求,则传入HttpPost对象,如果为null,表示不使用POST请求
* @param cookieList 需要提交到服务端的cookie数据
* @param getCookie 是否需要从服务端获取cookie数据
* @param responseHandler ResponseHandler响应处理对象
* @param 响应处理对象中可通过泛型来指定返回的具体数据类型
* @return 通过在ResponseHandler中指定的具体类型来返回响应数据,并获取由服务端返回的cookie数据到cookies成员变量中
*/
private static T send(HttpGet httpGet, HttpPost httpPost, List cookieList, boolean getCookie, ResponseHandler responseHandler) {
CookieStore cookieStore = new BasicCookieStore();
CloseableHttpClient httpClient = HttpClients.custom().setDefaultCookieStore(cookieStore).build();
if (cookieList != null) {
for (Cookie cookie : cookieList) {
cookieStore.addCookie(cookie);
}
}
T t = null;
try {
if (httpGet != null) {
httpGet.setConfig(requestConfig);
t = httpClient.execute(httpGet, responseHandler);
} else {
httpPost.setConfig(requestConfig);
t = httpClient.execute(httpPost, responseHandler);
}
if (getCookie) {
cookies = cookieStore.getCookies();
}
} catch (IOException e) {
logger.error("http client execute error: {}", e.getMessage());
} finally {
try {
httpClient.close();
} catch (IOException e) {
logger.error("http client close error: {}", e.getMessage());
}
}
return t;
}
/**
* 获取String字符串响应的ResponseHandler
* 如果状态为200,则直接获取response结果,如果状态为302,则获取重定向的url,其他状态暂时返回非正常响应状态
*/
private static ResponseHandler stringResponseHandler = response -> {
int status = response.getStatusLine().getStatusCode();
if (status == HttpStatus.SC_OK) {
HttpEntity entity = response.getEntity();
return entity != null ? EntityUtils.toString(entity, CharsetEnum.UTF8.getValue()) : null;
} else if (status == HttpStatus.SC_MOVED_TEMPORARILY) {
return response.getFirstHeader("Location").getValue();
} else {
throw new ClientProtocolException("no normal status: " + status);
}
};
}
------------------------------------------------------------------------------------------------------------------------------
补充用到的几个枚举类
CharsetEnum:
package top.zywork.enums;
/**
* 编码格式枚举
* 创建于2017-08-15
*
* @author 危锦辉
* @version 1.0
*/
public enum CharsetEnum {
UTF8("UTF-8"),
GBK("GBK"),
GB2312("GB2312"),
ISO8859_1("ISO8859-1");
private String value;
CharsetEnum(String value) {
this.value = value;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
}
ContentTypeEnum:
package top.zywork.enums;
/**
* 常用内容类型枚举
* 创建于2017-09-14
*
* @author 危锦辉
* @version 1.0
* @see org.apache.http.entity.ContentType
* @see MIMETypeEnum
*/
public enum ContentTypeEnum {
HTML("text/html; charset=UTF-8"),
TEXT_PLAIN("text/plain; charset=UTF-8"),
XML("text/xml; charset=UTF-8"),
JSON("application/json; charset=UTF-8"),
FORM_URLENCODED("application/x-www-form-urlencoded"),
PNG("image/png");
private String value;
ContentTypeEnum(String value) {
this.value = value;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
}
MIMETypeEnum:
package top.zywork.enums;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.Map;
/**
* MIME Type枚举,常用的MIME Type
* 创建于2017-09-01
*
* @author 危锦辉
* @version 1.0
* @see top.zywork.enums.ContentTypeEnum
*/
public enum MIMETypeEnum {
TEXT("text", ".txt", "text/plain"),
HTML("html", ".html", "text/html"),
XML("xml", ".xml", "text/xml"),
JSON("json", ".json", "application/json"),
JPG("jpg", ".jpg", "image/jpeg"),
JPEG("jpeg", ".jpeg", "image/jpeg"),
GIF("gif", ".gif", "image/gif"),
PNG("png", ".png", "image/png"),
BMP("bmp", ".bmp", "image/bmp"),
PDF("pdf", ".pdf", "application/pdf"),
DOC("doc", ".doc", "application/msword"),
DOCX("docx", ".docx", "application/vnd.openxmlformats-officedocument.wordprocessingml.document"),
PPT("ppt", ".ppt", "application/vnd.ms-powerpoint"),
PPTX("pptx", ".pptx", "application/vnd.openxmlformats-officedocument.presentationml.presentation"),
XLS("xls", ".xls", "application/vnd.ms-excel"),
XLSX("xlsx", ".xlsx", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"),
ZIP("zip", ".zip", "application/zip"),
RAR("rar", ".rar", "application/x-rar-compressed");
private String value;
private String ext;
private String mime;
public static Map valueLookup;
static {
valueLookup = new HashMap<>();
for (MIMETypeEnum mimeTypeEnum : EnumSet.allOf(MIMETypeEnum.class)) {
valueLookup.put(mimeTypeEnum.getValue(), mimeTypeEnum);
}
}
MIMETypeEnum(String value, String ext, String mime) {
this.value = value;
this.ext = ext;
this.mime = mime;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
public String getExt() {
return ext;
}
public void setExt(String ext) {
this.ext = ext;
}
public String getMime() {
return mime;
}
public void setMime(String mime) {
this.mime = mime;
}
public static MIMETypeEnum findByValue(String value) {
return valueLookup.get(value);
}
}