HTTP协议的特点如下:
1.支持客户/服务器模式。
2.简单快速:客户向服务器请求服务时,只需传送请求方法和路径。请求方法常用的有GET、HEAD、POST。每种方法规定了客户与服务器联系的类型不同。
由于HTTP协议简单,使得HTTP服务器的程序规模小,因而通信速度很快。
3.灵活:HTTP允许传输任意类型的数据对象。正在传输的类型由Content-Type加以标记。
4.无连接:无连接的含义是限制每次连接只处理一个请求。服务器处理完客户的请求,并收到客户的应答后,即断开连接。采用这种方式可以节省传输时间。
5.无状态:HTTP协议是无状态协议。无状态是指协议对于事务处理没有记忆能力。缺少状态意味着如果后续处理需要前面的信息,则它必须重传,这样可能导致每次连接传送的数据量增大。另一方面,在服务器不需要先前信息时它的应答就较快。
HttpClient
HttpClient 是Apache HttpComponents 下的子项目,用来提供高效的、最新的、功能丰富的支持 HTTP 协议的客户端编程工具包,并且它支持 HTTP 协议最新的版本和建议。HttpClient 不是浏览器,它是一个客户端 HTTP 协议传输类库。HttpClient 被用来发送和接受 HTTP 消息。HttpClient 不会处理 HTTP 消息的内容,不会进行 javascript 解析,不会关心 content type,如果没有明确设置,HttpClient 也不会对请求进行格式化、重定向 url,或者其他任何和 HTTP 消息传输相关的功能。
使用步骤:
使用HttpClient发送请求、接收响应很简单,一般需要如下几步即可。
-
创建HttpClient对象。
-
创建请求方法的实例,并指定请求URL。如果需要发送GET请求,创建HttpGet对象;如果需要发送POST请求,创建HttpPost对象。
-
如果需要发送请求参数,可调用HttpGet、HttpPost共同的setParams(HetpParams params)方法来添加请求参数;对于HttpPost对象而言,也可调用setEntity(HttpEntity entity)方法来设置请求参数。
-
调用HttpClient对象的execute(HttpUriRequest request)发送请求,该方法返回一个HttpResponse。
-
调用HttpResponse的getAllHeaders()、getHeaders(String name)等方法可获取服务器的响应头;调用HttpResponse的getEntity()方法可获取HttpEntity对象,该对象包装了服务器的响应内容。程序可通过该对象获取服务器的响应内容。
-
释放连接。无论执行方法是否成功,都必须释放连接
具体代码实现如下:
pom.xml添加httpclient的maven坐标依赖
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
</dependency>
HttpClientUtil工具类
public class HttpClientUtil {
private static PoolingHttpClientConnectionManager connectionManager;
private static String DEFAULT_STR = "";
private static String UTF_8 = "UTF-8";
private final static int CONNECT_TIMEOUT = 3000;// 连接超时毫秒 ps:表示建立连接的超时时间
private final static int SOCKET_TIMEOUT = 10000;// 传输超时毫秒 ps:表示数据传输处理时间
private final static int REQUESTCONNECT_TIMEOUT = 2000;// 从线程池获取连接超时时间毫秒
private final static int MAX_TOTAL = 50;// 线程池的最大连接数
private final static int CONNECT_DEFAULT_ROUTE = 5;// 每个路由默认基础的连接数
private static void init() {
if (connectionManager == null) {
connectionManager = new PoolingHttpClientConnectionManager();
connectionManager.setMaxTotal(MAX_TOTAL);// 整个连接池最大连接数
// 可用空闲连接过期时间,重用空闲连接时会先检查是否空闲时间超过这个时间,如果超过,释放socket重新建立
//connectionManager.setValidateAfterInactivity(50000);
connectionManager.setDefaultMaxPerRoute(CONNECT_DEFAULT_ROUTE);// 每路由最大连接数,默认值是2
}
}
/**
* 通过连接池获取HttpClient
* @return
*/
private static CloseableHttpClient getHttpClient() {
init();
Builder builder = RequestConfig.custom();
RequestConfig config = builder.setSocketTimeout(SOCKET_TIMEOUT)
.setConnectTimeout(CONNECT_TIMEOUT)
.setConnectionRequestTimeout(REQUESTCONNECT_TIMEOUT)
.build();
CloseableHttpClient client = HttpClients.custom()
.setMaxConnPerRoute(CONNECT_DEFAULT_ROUTE)
.disableConnectionState().setDefaultRequestConfig(config)
.setConnectionManager(connectionManager).build();
return client;
}
/**
*
* @param url
* @return
* @throws IOException
*/
public static String httpGetRequest(String url) throws Exception {
HttpGet httpGet = new HttpGet(url);
return getResult(httpGet);
}
public static String httpGetRequest(String url, Map<String, Object> params) throws Exception {
URIBuilder ub = new URIBuilder();
ub.setPath(url);
ArrayList<NameValuePair> pairs = covertParams2NVPS(params);
ub.setParameters(pairs);
HttpGet httpGet = new HttpGet(ub.build());
return getResult(httpGet);
}
public static String httpGetRequest(String url, Map<String, Object> headers
, Map<String, Object> params) throws Exception {
URIBuilder ub = new URIBuilder();
ub.setPath(url);
ArrayList<NameValuePair> pairs = covertParams2NVPS(params);
ub.setParameters(pairs);
HttpGet httpGet = new HttpGet(ub.build());
for (Map.Entry<String, Object> param : headers.entrySet()) {
httpGet.addHeader(param.getKey(), String.valueOf(param.getValue()));
}
return getResult(httpGet);
}
public static String httpPostRequest(String url) throws IOException {
HttpPost httpPost = new HttpPost(url);
return getResult(httpPost);
}
public static String httpPostRequest(String url, Map<String, Object> params) throws Exception {
HttpPost httpPost = new HttpPost(url);
ArrayList<NameValuePair> pairs = covertParams2NVPS(params);
httpPost.setEntity(new UrlEncodedFormEntity(pairs, UTF_8));
return getResult(httpPost);
}
public static String httpPostRequest(String url, String jsonParams) throws Exception {
HttpPost httpPost = new HttpPost(url);
StringEntity se = new StringEntity(jsonParams,UTF_8);
httpPost.setEntity(se);
httpPost.setHeader("Content-Type","application/json");
return getResult(httpPost);
}
public static String httpPostRequest(String url, String jsonParams,Map<String,String> headerMap) throws Exception {
HttpPost httpPost = new HttpPost(url);
StringEntity se = new StringEntity(jsonParams,UTF_8);
httpPost.setEntity(se);
for (String s : headerMap.keySet()) {
httpPost.setHeader(s,headerMap.get(s));
}
return getResult(httpPost);
}
public static String httpPostXMLDataRequest(String url, String xmlData) throws Exception {
HttpPost httpPost = new HttpPost(url);
httpPost.addHeader("Content-Type", "text/xml");
httpPost.setEntity(new StringEntity(xmlData, UTF_8));
return getResult(httpPost);
}
/**
* post请求传输json参数
*
* @param url url地址
* @return
*/
public static JSONObject httpPost(String url, JSONObject jsonParam) {
// post请求返回结果
CloseableHttpClient httpClient = getHttpClient();
JSONObject jsonResult = null;
HttpPost httpPost = new HttpPost(url);
try {
if (null != jsonParam) {
// 解决中文乱码问题
StringEntity entity = new StringEntity(jsonParam.toString(), "utf-8");
entity.setContentEncoding("UTF-8");
entity.setContentType("application/json");
httpPost.setEntity(entity);
}
CloseableHttpResponse result = httpClient.execute(httpPost);
log.info("httpPost : {}" , result);
// 请求发送成功,并得到响应
if (result.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
String str = "";
try {
// 读取服务器返回过来的json字符串数据
str = EntityUtils.toString(result.getEntity(), "utf-8");
// 把json字符串转换成json对象
jsonResult = JSONObject.parseObject(str);
} catch (Exception e) {
log.error("post请求提交失败:" + url, e);
}
}
} catch (IOException e) {
log.error("post请求提交失败:" + url, e);
} finally {
httpPost.releaseConnection();
}
return jsonResult;
}
/**
* post
* @param url (a=3&b=2 形式)
* @param headers 请求头
* @param params 参数
* @return
* @throws IOException
*/
public static String httpPostRequest(String url, Map<String, Object> headers
, Map<String, Object> params) throws Exception {
HttpPost httpPost = new HttpPost(url);
for (Map.Entry<String, Object> param : headers.entrySet()) {
httpPost.addHeader(param.getKey(), String.valueOf(param.getValue()));
}
ArrayList<NameValuePair> pairs = covertParams2NVPS(params);
httpPost.setEntity(new UrlEncodedFormEntity(pairs, UTF_8));
return getResult(httpPost);
}
private static ArrayList<NameValuePair> covertParams2NVPS(Map<String, Object> params) {
ArrayList<NameValuePair> pairs = new ArrayList<NameValuePair>();
for (Map.Entry<String, Object> param : params.entrySet()) {
pairs.add(new BasicNameValuePair(param.getKey(), String.valueOf(param.getValue())));
}
return pairs;
}
/**
* post
* @param url (JSON 形式)
* @param headers 请求头
* @param
* @return
* @throws IOException
*/
public static String httpPostRequest(String url, Map<String, Object> headers, String jsonParams
) throws Exception {
HttpPost httpPost = new HttpPost(url);
for (Map.Entry<String, Object> param : headers.entrySet()) {
httpPost.setHeader(param.getKey(), String.valueOf(param.getValue()));
}
StringEntity se = new StringEntity(jsonParams,UTF_8);
httpPost.setEntity(se);
return getResult(httpPost);
}
/**
* 处理Http请求
*
* @param request
* @return string
* @throws IOException
*/
private static String getResult(HttpRequestBase request) throws IOException {
CloseableHttpClient httpClient = getHttpClient();
CloseableHttpResponse response = null;
InputStream in = null;
try {
response = httpClient.execute(request);
HttpEntity entity = response.getEntity();
in = response.getEntity().getContent();
if (entity != null) {
String result = EntityUtils.toString(entity, Charset.forName(UTF_8));
response.close();
return result;
}
} catch (ConnectTimeoutException e) {
// 连接超时异常
log.error("connect timeout {}", e);
} catch (SocketTimeoutException e) {
// 读取超时异常
log.error("read timeout {}", e);
} catch (ClientProtocolException e) {
// 该异常通常是协议错误导致:比如构造HttpGet对象时传入协议不对(将'http'写成'htp')or响应内容不符合
log.error("protocol exception {}", e);
} catch (ParseException e) {
// 解析异常
log.error("parse exception {}", e);
} catch (IOException e) {
// 该异常通常是网络原因引起的,如HTTP服务器未启动等
log.error("network exception {}", e);
} catch (Exception e) {
log.error("other exception {}", e);
} finally {
if (response != null) {
try {
response.close();
} catch (IOException e) {
e.printStackTrace();
}
}
//in.close();作用就是将用完的连接释放,下次请求可以复用
//这里特别注意的是,如果不使用in.close();而仅仅使用response.close();结果就是连接会被关闭,并且不能被复用,这样就失去了采用连接池的意义。
if (in != null) {
try {
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return DEFAULT_STR;
}
/*处理xujianexcel上传接口*/
public static String FilehttpPostRequest(String url, Map<String, Object> headers, Map<String, String> jsonParams,String filePath) throws Exception {
HttpPost httpPost = new HttpPost(url);
for (Map.Entry<String, Object> param : headers.entrySet()) {
httpPost.setHeader(param.getKey(), String.valueOf(param.getValue()));
}
File file = new File(filePath);
// 相当于<input type="file" name="file"/>
MultipartEntityBuilder builder = MultipartEntityBuilder.create();
builder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
//builder.addBinaryBody("wj", inputStream, ContentType.create("multipart/form-data"), "test.pdf");
builder.addBinaryBody("file", new FileInputStream(file), ContentType.create("multipart/form-data"), file.getName());
for (Map.Entry<String, String> entry : jsonParams.entrySet()) {
String key = entry.getKey();
// 相当于<input type="text" name="userName" value=userName>
StringBody value = new StringBody(entry.getValue(),ContentType.create("multipart/form-data"));
builder.addTextBody(key,entry.getValue(),ContentType.create("multipart/form-data"));
}
HttpEntity reqEntity = builder.build();
httpPost.setEntity(reqEntity);
return getResult(httpPost);
}
//当多个文件需要上传时,对文件进行组装
public void addFileBodyPart(String paramName, ArrayList<FileBody> fileBodys, MultipartEntity reqEntity){
if(fileBodys == null || fileBodys.size() < 1 || reqEntity == null || paramName == null){
return;
}
for(FileBody iteam : fileBodys){
reqEntity.addPart(paramName,iteam);
}
}
/**
* 发送get请求
*
* @param url 路径
* @return
*/
public static JSONObject httpGet(String url) {
// get请求返回结果
JSONObject jsonResult = null;
CloseableHttpClient client = getHttpClient();
// 发送get请求
HttpGet request = new HttpGet(url);
try {
CloseableHttpResponse response = client.execute(request);
// 请求发送成功,并得到响应
if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
// 读取服务器返回过来的json字符串数据
HttpEntity entity = response.getEntity();
String strResult = EntityUtils.toString(entity, "utf-8");
// 把json字符串转换成json对象
jsonResult = JSONObject.parseObject(strResult);
} else {
log.error("get请求提交失败:" + url);
}
} catch (IOException e) {
log.error("get请求提交失败:" + url, e);
} finally {
request.releaseConnection();
}
return jsonResult;
}
}