前言
- 使用Apache的HttpClient库,添加Apache HttpClient的依赖。
- 工具类的封装。通常,工具类需要处理GET、POST请求,可能还有其他方法如PUT、DELETE。需要设计一个工具类,提供静态方法,可以发送请求,并处理响应。同时要考虑连接超时、读取超时的设置,以及请求头的配置,比如Content-Type、User-Agent等
- 然后,需要处理请求参数的封装。对于GET请求,参数通常是查询字符串;对于POST,可能需要表单参数或者JSON body。因此,工具类可能需要支持不同的参数类型,比如使用Map<String, String>来传递表单参数,或者直接传入一个JSON字符串作为请求体。
- 异常处理也是关键。网络请求可能会抛出IOException等异常,工具类需要捕获这些异常,并可能转换成自定义异常,或者返回null,或者记录日志,具体取决于设计选择。需要灵活处理错误,所以可能需要将异常抛出让调用者处理,或者在工具类内部处理并返回错误信息。
- 另外,响应处理方面,需要将HttpEntity转换为字符串,并正确关闭连接,确保资源释放。使用EntityUtils.toString时要注意字符编码,通常使用UTF-8。同时,需要关闭HttpResponse和HttpClient,或者使用try-with-resources来自动管理资源,但Apache HttpClient 4.x版本的response关闭可能需要注意,需要确保正确关闭流。
注意事项
-
工具类可能包含sendGet和sendPost方法。例如,sendGet接收URL和参数Map,构造带查询参数的URL;sendPost接收URL和可能的表单参数或JSON body,并设置合适的Content-Type。此外,可能需要设置请求头,比如设置JSON的Content-Type为application/json。
-
工具类的设计要尽量简洁,可配置。比如,可以允许自定义连接超时时间、读取超时时间,或者设置默认的请求头。可能使用HttpClient的配置,比如RequestConfig来设置超时参数。
-
可能的陷阱包括:未正确处理参数编码,比如在GET请求中,参数需要进行URL编码;在POST发送表单时,需要将参数转换为UrlEncodedFormEntity;发送JSON时,要使用StringEntity,并设置Content-Type为application/json。
-
需要注意线程安全,HttpClient通常建议重用实例,所以工具类中可能使用静态的CloseableHttpClient实例,并通过静态代码块初始化,确保线程安全。但需确认是否每次请求需要新的实例,或者可以共享。根据Apache HttpClient文档,建议重复使用同一个实例,因为它是线程安全的,并且管理连接池更高效。所以工具类中可以创建一个单例的HttpClient实例。
-
另外,工具类可能需要处理不同的Content-Type,比如POST发送JSON时,需要设置对应的头信息,并处理不同的数据体。因此,sendPost可能需要参数来指定发送的数据类型,或者通过方法重载来处理不同情况。
-
例如,提供sendPostForm用于发送表单,sendPostJson用于发送JSON。或者,在方法中传递一个contentType参数,并根据类型构造不同的HttpEntity。
-
或者,更灵活的方式是让调用者传入一个HttpEntity对象,这样工具类更通用,但使用起来可能不够方便。所以需要在易用性和灵活性之间权衡。
-
这里工具类可以提供两个方法:一个处理表单参数(Map类型),另一个处理JSON字符串。
-
整体思路
-
引入Apache HttpClient依赖。
-
创建HttpClientUtil类,封装创建HttpClient实例的方法,配置超时等参数。
-
实现sendGet方法,处理参数拼接和编码。
-
实现sendPost方法,处理表单或JSON数据的提交。
-
处理响应,将结果转换为字符串。
-
异常处理,关闭资源。
-
提供使用示例。
代码示例
Maven依赖
<dependency><groupId>org.apache.httpcomponents</groupId><artifactId>httpclient</artifactId><version>4.5.13</version>
</dependency>
HttpClientUtil
import org.apache.http.HttpEntity;
import org.apache.http.NameValuePair;
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.utils.URIBuilder;
import org.apache.http.entity.StringEntity;
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 java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;public class HttpClientUtil {// 超时配置(单位:毫秒)private static final int CONNECT_TIMEOUT = 5000;private static final int SOCKET_TIMEOUT = 5000;// 创建可复用的HttpClient实例private static final CloseableHttpClient httpClient = HttpClients.custom().setDefaultRequestConfig(RequestConfig.custom().setConnectTimeout(CONNECT_TIMEOUT).setSocketTimeout(SOCKET_TIMEOUT).build()).build();/*** 发送GET请求* @param url 请求地址* @param params 请求参数* @return 响应内容*/public static String sendGet(String url, Map<String, String> params) {HttpGet httpGet = new HttpGet(buildUri(url, params));try (CloseableHttpResponse response = httpClient.execute(httpGet)) {return handleResponse(response);} catch (IOException e) {throw new RuntimeException("GET请求失败", e);}}/*** 发送POST表单请求(application/x-www-form-urlencoded)* @param url 请求地址* @param formData 表单数据* @return 响应内容*/public static String sendPostForm(String url, Map<String, String> formData) {HttpPost httpPost = new HttpPost(url);List<NameValuePair> params = new ArrayList<>();formData.forEach((k, v) -> params.add(new BasicNameValuePair(k, v)));httpPost.setEntity(new UrlEncodedFormEntity(params, "UTF-8"));return executePost(httpPost);}/*** 发送POST JSON请求(application/json)* @param url 请求地址* @param json JSON字符串* @return 响应内容*/public static String sendPostJson(String url, String json) {HttpPost httpPost = new HttpPost(url);StringEntity entity = new StringEntity(json, "UTF-8");entity.setContentType("application/json");httpPost.setEntity(entity);return executePost(httpPost);}private static String executePost(HttpPost httpPost) {try (CloseableHttpResponse response = httpClient.execute(httpPost)) {return handleResponse(response);} catch (IOException e) {throw new RuntimeException("POST请求失败", e);}}private static URI buildUri(String url, Map<String, String> params) {try {URIBuilder uriBuilder = new URIBuilder(url);if (params != null) {params.forEach(uriBuilder::addParameter);}return uriBuilder.build();} catch (URISyntaxException e) {throw new IllegalArgumentException("URL格式错误", e);}}private static String handleResponse(CloseableHttpResponse response) throws IOException {int statusCode = response.getStatusLine().getStatusCode();if (statusCode != 200) {throw new RuntimeException("HTTP响应异常,状态码:" + statusCode);}HttpEntity entity = response.getEntity();return entity != null ? EntityUtils.toString(entity, "UTF-8") : null;}
}
使用示例
import java.util.HashMap;
import java.util.Map;public class Example {public static void main(String[] args) {// GET请求示例String getUrl = "https://api.example.com/data";Map<String, String> params = new HashMap<>();params.put("key1", "value1");params.put("key2", "value2");String getResponse = HttpClientUtil.sendGet(getUrl, params);System.out.println("GET响应内容:" + getResponse);// POST表单示例String postFormUrl = "https://api.example.com/submit";Map<String, String> formData = new HashMap<>();formData.put("username", "testuser");formData.put("password", "testpass");String postFormResponse = HttpClientUtil.sendPostForm(postFormUrl, formData);System.out.println("POST表单响应:" + postFormResponse);// POST JSON示例String postJsonUrl = "https://api.example.com/submit-json";String jsonPayload = "{\"name\":\"John\", \"age\":30}";String postJsonResponse = HttpClientUtil.sendPostJson(postJsonUrl, jsonPayload);System.out.println("POST JSON响应:" + postJsonResponse);}
}
总结
工具类特点:
- 线程安全: 使用单个共享的HttpClient实例,复用连接池资源
- 超时配置: 统一设置5秒连接/读取超时
- 编码处理: 统一使用UTF-8编码
- 异常处理: 将检查异常转换为运行时异常,简化调用
- 支持多种请求:
- GET请求(带查询参数)
- POST表单(application/x-www-form-urlencoded)
- POST JSON(application/json)
- 响应处理: 自动验证状态码并转换响应内容
注意事项:
- 根据实际情况调整超时时间配置
- 生产环境建议添加日志记录
- 需要处理其他状态码(如3xx重定向)时可扩展handleResponse方法
- 如需添加自定义请求头,可扩展方法参数
- 注意及时释放资源,使用try-with-resources自动关闭响应
可根据实际需求进一步扩展支持:
- 文件上传
- HTTPS配置
- 代理设置
- 请求重试机制
- 更完善的异常处理等