Java常用HTTP工具类,支持get,post,put,delete几种method方式,可自定义参数,自定义header,请求内容等;
新增对HTTPS的支技;
HttpUtils.java
import org.apache.commons.lang3.StringUtils;
import org.springframework.util.Assert;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLSession;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.Charset;
import java.security.SecureRandom;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.HashMap;
import java.util.Map;
/**
* @author JL
* @version V1.0
* @Description 用java.net.HttpURLConnection进行http操作工具类
*/
public class HttpUtils {
static final int CONNECT_TIMEOUT_MILLES = 3000;
static final Charset ENCODING;
public static final String HTTP_GET = "GET";
public static final String HTTP_PUT = "PUT";
public static final String HTTP_POST = "POST";
public static final String HTTP_DELETE = "DELETE";
static final String [] METHODS;
static {
ENCODING = Charset.forName("UTF-8");
METHODS = new String[]{HTTP_GET, HTTP_PUT, HTTP_POST, HTTP_DELETE};
}
public static String doGet(String url, Map headers, Map params, String content) throws IOException {
return doOutput(url, HTTP_GET, headers, params, content);
}
public static String doPost(String url, Map headers, Map params, String content) throws IOException {
return doOutput(url, HTTP_POST, headers, params, content);
}
public static String doSslGet(String url, Map headers, Map params, String content) throws IOException {
return doOutput(url, HTTP_GET, headers, params, content, true);
}
public static String doSslPost(String url, Map headers, Map params, String content) throws IOException {
return doOutput(url, HTTP_POST, headers, params, content, true);
}
public static String doJsonPost(String url, Map headers, Map params, String content) throws IOException {
params = (params != null) ? params : new HashMap<>();
params.put("Content-Type", "application/Json; charset=UTF-8");
return doOutput(url, HTTP_POST, headers, params, content);
}
public static String doPut(String url, Map headers, Map params, String content) throws IOException {
return doOutput(url, HTTP_PUT, headers, params, content);
}
public static String doDelete(String url, Map headers, Map params, String content) throws IOException {
return doOutput(url, HTTP_DELETE, headers, params, content);
}
public static String doOutput(final String url,final String method,final Map headers,final Map params,final String content) throws IOException {
return doOutput(url, method, headers, params, content,false);
}
public static String doOutput(final String url,final String method,final Map headers,final Map params,final String content,boolean isSsl) throws IOException {
HttpURLConnection conn = null;
try{
conn = createConnection(setParams(url, params), isSsl);
setMethod(conn, method);
setHeaders(conn, headers);
conn.connect();
output(conn, content);
return input(conn);
}catch(IOException ioe){
ioe.printStackTrace();
throw ioe;
} finally{
connClose(conn);
}
}
private static void connClose(HttpURLConnection conn){
if (conn != null){
conn.disconnect();
}
}
private static String input(HttpURLConnection conn) throws IOException{
int len ;
char[] cbuf = new char[1024 * 8];
StringBuilder buf = new StringBuilder();
int status = conn.getResponseCode();
InputStream in = null;
BufferedReader reader = null;
try{
in = conn.getErrorStream();
if (in == null && status < 400) { //400或以上表示:访问的页面域名不存在或者请求错误、服务端异常
in = conn.getInputStream();
}
if (in != null){
reader = new BufferedReader(new InputStreamReader(in, ENCODING));
while ((len = reader.read(cbuf)) > 0){
buf.append(cbuf, 0 , len);
}
}
}finally{
if (reader != null){
reader.close();
}
if (in != null){
in.close();
}
}
return buf.toString();
}
private static void output(HttpURLConnection conn, String content) throws IOException {
if (StringUtils.isBlank(content))
return ;
OutputStream out = conn.getOutputStream();
try{
out.write(content.getBytes(ENCODING));
} finally{
if (out != null){
out.flush();
out.close();
}
}
}
private static HttpURLConnection createConnection(String url, boolean isSsl) throws IOException {
if (isSsl) {
try {
httpssl();//ssl协议
} catch (Exception e) {
e.printStackTrace();
}
}
HttpURLConnection conn = (HttpURLConnection)(new URL(url)).openConnection();
setConfig(conn);
return conn;
}
private static void setMethod(HttpURLConnection conn, String method) throws IOException{
Assert.isTrue(StringUtils.containsAny(method,METHODS),"只支持GET、POST、PUT、DELETE操作");
conn.setRequestMethod(method);
}
private static void setConfig(HttpURLConnection conn){
conn.setConnectTimeout(CONNECT_TIMEOUT_MILLES);
conn.setUseCaches(false);
conn.setInstanceFollowRedirects(true);
conn.setRequestProperty("Connection", "close");
//conn.setRequestProperty("Content-Type", "application/Json; charset=UTF-8");//这个根据需求,自已加,也可以放到headersc参数内
conn.setDoOutput(true);//是否启用输出流,method=get,请求参数是拼接在地址档,默认为false
conn.setDoInput(true);//是否启用输入流
}
private static void setHeaders(HttpURLConnection conn, Map headers){
if (headers == null || headers.size() <= 0) return ;
headers.forEach((k,v) -> conn.setRequestProperty(k,v));//设置自定义header参数
}
private static String setParams(String url, Map params){
if (params == null || params.size() <= 0)
return url;
StringBuilder sb = new StringBuilder(url);
sb.append("?");
params.forEach((k,v)->sb.append(k).append("=").append(v).append("&"));
return sb.substring(0, sb.length() - 1);
}
/**
* 创建ssl连接
* SSL协议位于TCP/IP协议与各种应用层协议之间,为数据通讯提供安全支持,提供如下支持:
* 1)认证用户和服务器,确保数据发送到正确的客户机和服务器;
* 2)加密数据以防止数据中途被窃取;
* 3)维护数据的完整性,确保数据在传输过程中不被改变。
* @throws Exception
*/
public static void httpssl() throws Exception {
javax.net.ssl.TrustManager[] trustAllCerts = new javax.net.ssl.TrustManager[1];
javax.net.ssl.TrustManager tm = new SslManager();
trustAllCerts[0] = tm;
javax.net.ssl.SSLContext sc = javax.net.ssl.SSLContext.getInstance("SSL");
sc.init(null, trustAllCerts, new SecureRandom());
javax.net.ssl.HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
javax.net.ssl.HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() {
public boolean verify(String str, SSLSession session) {
return true;
}
});
}
//TrustManager是JSSE 信任管理器的基接口,管理和接受提供的证书,通过JSSE可以很容易地编程实现对HTTPS站点的访问
//X509TrustManager此接口的实例管理使用哪一个 X509 证书来验证远端的安全套接字
public static class SslManager implements TrustManager, X509TrustManager {
@Override
public void checkClientTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {
}
@Override
public void checkServerTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {
}
@Override
public X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[0];
}
}
public static void main(String[] args) throws IOException {
// https://www.baidu.com/s?wd=HttpURLConnection
// Map params = new HashMap();
// params.put("wd","HttpURLConnection");
// String html = doGet("https://www.baidu.com/s",null, params, null);
// System.out.println(html);
//https 测试
String httpsUrl = "https://ifeve.com/google-guava/";
String html2 = doSslGet(httpsUrl,null, null, null);
System.out.println(html2);
}
}
说明:
做过项目的人都知道,很多写过的可重复利用的代码块或有用的工具类没有怎么整理,当需要的时候,又得打开项目查找一翻,虽然功能开发不难,但是又得花时间成本去写去测试,这样的重复造轮子的事情太多次了;因此不如把轮子保留,供大家一起使用;
1.这个轮子可以有:需要使用的时候确实还不存在这个组件。
2.我需要的时候轮子不在:每一种技术或工具产生都有它的项目背景,当代码写在项目里的时候,我知道有这个东西,当换了一个项目或公司后,没有备份也没有记录,这个时候你不在了,又得花时间手打一遍;
3.我不知道是不是造轮子:大多数情况下初学者很难分清楚自己是不是在重复造轮子,事实上造轮子不是我目的。我的目的是完成工作任务,任务完成的速度越快越好,质量越高越好。而不是去判断自己在不在造轮子。
4.不想重复花时间造轮子:有时候还会碰到一些并不困难但是很占时间的东西,当然有现成的轮子是花时间最少的;
5.我就是想学习轮子:初学者的并不是在重复造轮子,而是学习后以提高为自己的知识与技能。
轮子有过测试,但难免有失误,如有错误处,还敬请指出;