HttpURLConnection

Java常用方法   2025-01-11 17:40   155   0  

一、HTTP

1、依赖

commons-lang3-3.12.0.jar
commons-io-2.11.0.jar
slf4j-api-1.7.36.jar
slf4j-log4j12-1.7.7.jar
log4j-1.2.17.jar

2、RestMock.java

package com.chenwc.util;

import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Map.Entry;

import com.chenwc.enums.RequestMethodEnum;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.net.ssl.HttpsURLConnection;

public class RestMock {

    /**
     * 连接超时时间,30秒
     */
    private static final int CONNECT_TIME_OUT = 30 * 1000;
    /**
     * 读取超时时间,30秒
     */
    private static final int READ_TIME_OUT = 30 * 1000;

    private static final Logger log = LoggerFactory.getLogger(RestMock.class);

    /**
     * 发送post请求,默认超时时间30秒
     *
     * @param url           请求路径
     * @param hearderParams 请求头,如Content-type、Content-Length等
     * @param body          请求体,如json、xml、text、html等
     * @return 响应信息
     */
    public static String sendPost(String url,
                                  Map<String, String> hearderParams, String body) {
        return getResultByHttp(RequestMethodEnum.POST, url, hearderParams, body, READ_TIME_OUT, CONNECT_TIME_OUT);
    }

    /**
     * 发送post请求,默认超时时间30秒
     *
     * @param url           请求路径
     * @param hearderParams 请求头,如Content-type、Content-Length等
     * @return 响应信息
     */
    public static String sendPost(String url,
                                  Map<String, String> hearderParams) {
        return getResultByHttp(RequestMethodEnum.POST, url, hearderParams, "", READ_TIME_OUT, CONNECT_TIME_OUT);
    }

    /**
     * 发送post请求,默认超时时间30秒
     *
     * @param url 请求路径
     * @return 响应信息
     */
    public static String sendPost(String url) {
        return getResultByHttp(RequestMethodEnum.POST, url, new HashMap<>(), "", READ_TIME_OUT, CONNECT_TIME_OUT);
    }

    /**
     * 发送get请求,默认超时时间30秒
     *
     * @param url 请求路径
     * @return 响应信息
     */
    public static String sendGet(String url) {
        return getResultByHttp(RequestMethodEnum.GET, url, new HashMap<>(), "", READ_TIME_OUT, CONNECT_TIME_OUT);
    }

    /**
     * 发送get请求,默认超时时间30秒
     *
     * @param url           请求路径
     * @param hearderParams 请求头,如Content-type、Content-Length等
     * @return 响应信息
     */
    public static String sendGet(String url,
                                 Map<String, String> hearderParams) {
        return getResultByHttp(RequestMethodEnum.GET, url, hearderParams, "", READ_TIME_OUT, CONNECT_TIME_OUT);
    }

    /**
     * 发送get请求,默认超时时间30秒
     *
     * @param url           请求路径
     * @param hearderParams 请求头,如Content-type、Content-Length等
     * @param parameterMap  请求参数
     * @return 响应信息
     */
    public static String sendGet(String url,
                                 Map<String, String> hearderParams, Map<String, String> parameterMap) {
        String paramerterString = generateGetParameter(parameterMap);
        if (StringUtils.isNotEmpty(paramerterString)) {
            if (url.endsWith("?")) {
                url = url + paramerterString;
            } else {
                url = url + "?" + paramerterString;
            }
        }
        return getResultByHttp(RequestMethodEnum.GET, url, hearderParams, "", READ_TIME_OUT, CONNECT_TIME_OUT);
    }

    /**
     * 发送请求
     *
     * @param requestMethod  请求方式
     * @param url            请求路径
     * @param hearderParams  请求头,如Content-type、Content-Length等
     * @param body           请求体,如json、xml、text、html等
     * @param connectTimeOut 连接超时时间
     * @param readTimeOut    读取响应超时时间
     * @return 响应信息
     */
    public static String getResultByHttp(RequestMethodEnum requestMethod, String url,
                                         Map<String, String> hearderParams, String body, int connectTimeOut, int readTimeOut) {

        log.info("请求url------------->: {}", url);
        log.info("请求方法------------>: {}", requestMethod.getRequestMethod());
        if (null != hearderParams && !hearderParams.isEmpty()) {
            for (String key : hearderParams.keySet()) {
                log.info("添加的请求头信息---------->: {}:{}", key, hearderParams.get(key));
            }
        }
        if (StringUtils.isNotEmpty(body)) {
            log.info("请求体-------------->: {}", body);
        }
        log.info("连接超时时间-------->: {} ms", connectTimeOut);
        log.info("读取响应超时时间----->: {} ms", readTimeOut);
        HttpURLConnection conn = null;
        OutputStream output = null;
        InputStream inputStream = null;
        // 定义返回结果
        String result = "";
        try {
            long start = System.currentTimeMillis();
            // Java的URL网络类可以让你通过URL去连接网络服务器并获取资源
            URL u = new URL(url);
            log.info("开始建立连接............");
            // HttpURLConnection是Java的标准类,它继承自URLConnection,可用于向指定网站发送GET请求、POST请求
            // 得到网络访问对象java.net.HttpURLConnection
            conn = (HttpURLConnection) u.openConnection();
            //跳过所有https证书认证
            boolean useHttps = url.startsWith("https");
            if (useHttps) {
                TrustAllHosts.trustAllHosts((HttpsURLConnection) conn);
                ((HttpsURLConnection) conn).setHostnameVerifier(TrustAllHosts.DO_NOT_VERIFY);
            }
            // 设置是否向HttpURLConnection输出
            conn.setDoInput(true);
            // 设置是否从httpUrlConnection读入
            conn.setDoOutput(true);
            // 连接超时时间
            conn.setConnectTimeout(connectTimeOut);
            // 读取超时时间
            conn.setReadTimeout(readTimeOut);
            // 请求方式
            conn.setRequestMethod(requestMethod.getRequestMethod());
            // 放入需要添加的请求头参数
            if (null != hearderParams) {
                for (Entry<String, String> entry : hearderParams.entrySet()) {
                    String key = entry.getKey();
                    String value = entry.getValue();
                    conn.setRequestProperty(key, value);
                }
            }
            // 建立连接
            conn.connect();
            log.info("建立连接成功............");
            if (StringUtils.isNotEmpty(body)) {
                // 定义输出流,加入请求报文
                output = conn.getOutputStream();
                log.info("开始写入请求体............");
                output.write(body.getBytes(StandardCharsets.UTF_8));
                output.flush();
                log.info("写入请求体成功............");
            }
            Map<String, List<String>> responseHeader = conn.getHeaderFields();
            if (null != responseHeader && !responseHeader.isEmpty()) {
                for (String key : responseHeader.keySet()) {
                    if (null != key) {
                        log.info("响应头信息---------->: {}:{}", key, responseHeader.get(key).get(0));
                    } else {
                        log.info("响应头信息---------->: {}", responseHeader.get(null).get(0));
                    }
                }
            }
            int statusCode = conn.getResponseCode();
            log.info("请求响应码:{}", statusCode);
            if (200 == statusCode) {
                log.info("开始读取响应............");
                inputStream = conn.getInputStream();
                result = IOUtils.toString(inputStream, StandardCharsets.UTF_8);
                log.info("读取响应成功............");
                long end = System.currentTimeMillis();
                log.info("请求耗时----------->: {} ms", (end - start));
            } else {
                log.error("请求失败,HTTP 请求响应码不等于 200!!!");
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (null != conn) {
                    conn.disconnect();
                }
                if (null != output) {
                    output.close();
                }
                if (null != inputStream) {
                    inputStream.close();
                }
            } catch (Exception e2) {
                // TODO: handle exception
                e2.printStackTrace();
            }
        }
        return result;
    }

    /**
     * 使用GET方法下载文件
     *
     * @param url      请求路径
     * @param filePath 文件保存路径
     */
    public static void downloadFileByGet(String url, String filePath) {
        downloadFileByGet(url, new HashMap<>(), new HashMap<>(), filePath);
    }

    /**
     * 使用GET方法下载文件
     *
     * @param url           请求路径
     * @param hearderParams 请求头,如Content-type、Content-Length等
     * @param parameterMap  表单参数
     * @param filePath      文件保存路径
     */
    public static void downloadFileByGet(String url, Map<String, String> hearderParams,
                                         Map<String, String> parameterMap, String filePath) {
        String paramerterString = generateGetParameter(parameterMap);
        if (StringUtils.isNotEmpty(paramerterString)) {
            if (url.endsWith("?")) {
                url = url + paramerterString;
            } else {
                url = url + "?" + paramerterString;
            }
        }
        log.info("请求url------------->: {}", url);
        log.info("请求方法------------>: {}", RequestMethodEnum.GET.getRequestMethod());
        if (null != hearderParams && !hearderParams.isEmpty()) {
            for (String key : hearderParams.keySet()) {
                log.info("添加的请求头信息---------->: {}:{}", key, hearderParams.get(key));
            }
        }
        log.info("连接超时时间-------->: {} ms", CONNECT_TIME_OUT);
        log.info("读取响应超时时间----->: {} ms", READ_TIME_OUT);
        HttpURLConnection conn = null;
        InputStream inputStream = null;
        FileOutputStream fos = null;
        ByteArrayOutputStream bos = null;
        File fileExists = new File(filePath);
        try {
            long start = System.currentTimeMillis();
            if (!fileExists.exists()) {
                if (!mkdirParents(fileExists)) {
                    log.info("创建父级目录失败!");
                    return;
                }
                if (!fileExists.createNewFile()) {
                    log.info("创建文件: {} 失败!", filePath);
                    return;
                }
            }
            // Java的URL网络类可以让你通过URL去连接网络服务器并获取资源
            URL u = new URL(url);
            log.info("开始建立连接............");
            // HttpURLConnection是Java的标准类,它继承自URLConnection,可用于向指定网站发送GET请求、POST请求
            // 得到网络访问对象java.net.HttpURLConnection
            conn = (HttpURLConnection) u.openConnection();
            //跳过所有https证书认证
            boolean useHttps = url.startsWith("https");
            if (useHttps) {
                TrustAllHosts.trustAllHosts((HttpsURLConnection) conn);
                ((HttpsURLConnection) conn).setHostnameVerifier(TrustAllHosts.DO_NOT_VERIFY);
            }
            // 设置是否向HttpURLConnection输出
            conn.setDoInput(true);
            // 设置是否从httpUrlConnection读入
            conn.setDoOutput(true);
            // 连接超时时间
            conn.setConnectTimeout(CONNECT_TIME_OUT);
            // 读取超时时间
            conn.setReadTimeout(READ_TIME_OUT);
            // 请求方式
            conn.setRequestMethod(RequestMethodEnum.GET.getRequestMethod());
            // 放入需要添加的请求头参数
            if (null != hearderParams) {
                for (Entry<String, String> entry : hearderParams.entrySet()) {
                    String key = entry.getKey();
                    String value = entry.getValue();
                    conn.setRequestProperty(key, value);
                }
            }
            // 建立连接
            conn.connect();
            log.info("建立连接成功............");
            Map<String, List<String>> responseHeader = conn.getHeaderFields();
            if (null != responseHeader && !responseHeader.isEmpty()) {
                for (String key : responseHeader.keySet()) {
                    if (null != key) {
                        log.info("响应头信息---------->: {}:{}", key, responseHeader.get(key).get(0));
                    } else {
                        log.info("响应头信息---------->: {}", responseHeader.get(null).get(0));
                    }
                }
            }
            int statusCode = conn.getResponseCode();
            log.info("请求响应码:{}", statusCode);
            if (200 == statusCode) {
                log.info("开始读取响应............");
                inputStream = conn.getInputStream();
                byte[] buffer = new byte[1024];
                int len = 0;
                bos = new ByteArrayOutputStream();
                while ((len = inputStream.read(buffer)) != -1) {
                    bos.write(buffer, 0, len);
                }
                byte[] getData = bos.toByteArray();
                fos = new FileOutputStream(fileExists);
                fos.write(getData);
                log.info("下载文件成功!");
                log.info("文件保存到:{}", filePath);
                log.info("读取响应成功............");
                long end = System.currentTimeMillis();
                log.info("请求耗时----------->: {} ms", (end - start));
            } else {
                log.error("请求失败,HTTP 请求响应码不等于 200!!!");
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (null != conn) {
                    conn.disconnect();
                }
                if (null != inputStream) {
                    inputStream.close();
                }
                if (null != fos) {
                    fos.close();
                }
                if (null != bos) {
                    bos.close();
                }
            } catch (Exception e2) {
                // TODO: handle exception
                e2.printStackTrace();
            }
        }
    }

    /**
     * 根据map生成get请求参数,格式 A=a&B=b
     *
     * @param parameterMap 请求参数map
     * @return get请求参数url
     */
    private static String generateGetParameter(Map<String, String> parameterMap) {
        StringBuilder sb = new StringBuilder();
        if (null != parameterMap) {
            Set<String> keySet = parameterMap.keySet();
            int index = 1;
            for (String key : keySet) {
                String value = parameterMap.get(key);
                try {
                    value = URLEncoder.encode(value, String.valueOf(StandardCharsets.UTF_8));
                } catch (UnsupportedEncodingException e) {
                    e.printStackTrace();
                }
                if (index == keySet.size()) {
                    sb.append(key).append("=").append(value);
                } else {
                    sb.append(key).append("=").append(value).append("&");
                }
                index++;
            }
        }
        return sb.toString();
    }

    /**
     * 判断文件的父级目录是否存在,不存在则创建
     *
     * @param file 文件
     * @return true 父级目录存在或创建父级目录成功, false创建父级目录失败
     */
    public static boolean mkdirParents(File file) {
        if (!file.getParentFile().exists()) {
            return file.getParentFile().mkdirs();
        } else {
            return true;
        }
    }
}

3、RequestMethodEnum.java

package com.chenwc.enums;
/**
 * 一些常用http请求方法枚举
 * @author CalvinChan
 *
 */
public enum RequestMethodEnum {

    POST("POST"),
    GET("GET"),
    DELETE("DELETE"),
    PUT("PUT"),
    HEAD("HEAD"),
    PATCH("PATCH"),
    OPTIONS("OPTIONS"),
    TRACE("TRACE");

    private String requestMethod;

    private RequestMethodEnum(String requestMethod) {
        this.requestMethod = requestMethod;
    }

    public String getRequestMethod() {
        return requestMethod;
    }

    public void setRequestMethod(String requestMethod) {
        this.requestMethod = requestMethod;
    }
}

4、log4j.properties

log4j.rootLogger=info,stdout
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.out
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d %-5p %-5L --- [%-5t] %-10c : %m %n

5、测试

package com.chenwc;

import com.chenwc.enums.AlgorithmEnum;
import com.chenwc.enums.RequestMethodEnum;
import com.chenwc.util.RestMock;
import com.chenwc.util.ShaUtilsByJavaApi;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

public class Main {

    private static final Logger log = LoggerFactory.getLogger(Main.class);

    public static void main(String[] args){

        String result = "";
        String body = "{\"UUID\":\"3128a4de-2e29-49cd-b293-02af6c827d72\",\"title\":\"title\",\"Date\":\"2023-01-15 11:44:06.625\",\"content\":\"content\"}";

        //POST提交表单
        Map<String, String> header = new HashMap<>();
        header.put("Authorization", ShaUtilsByJavaApi.getShaHash(UUID.randomUUID().toString(), AlgorithmEnum.SHA_256));
        header.put("Cookie", String.valueOf(System.nanoTime()));
        header.put("Content-Type", "application/x-www-form-urlencoded;charset=UTF-8");
        result = RestMock.sendPost("http://localhost:9090/post_form?content=content&title=title", header);
        log.info("POST提交表单 Result: {}", result);

        //POST提交请求体
        header.put("Content-Type", "application/json;charset=UTF-8");
        result = RestMock.sendPost("http://localhost:9090/post_body", header, body);
        log.info("POST提交请求体 Result: {}", result);

        //GET提交表单
        Map<String, String> parameter = new HashMap<>();
        parameter.put("content", "content");
        parameter.put("title", "title");
        header.put("Content-Type", "application/x-www-form-urlencoded;charset=UTF-8");
        result = RestMock.sendGet("http://localhost:9090/get_form", header, parameter);
        log.info("GET提交表单 Result: {}", result);

        //OPTIONS提交请求
        result = RestMock.getResultByHttp(RequestMethodEnum.OPTIONS, "http://localhost:9090/put_body", new HashMap<>(), "", 3000, 3000);
        log.info("OPTIONS提交请求 Result: {}", result);

        //PUT提交请求体
        header.put("Content-Type", "application/json;charset=UTF-8");
        result = RestMock.getResultByHttp(RequestMethodEnum.PUT, "http://localhost:9090/put_body", header, body, 3000, 3000);
        log.info("PUT提交请求体 Result: {}", result);

        //自签证书
        result = RestMock.sendGet("https://192.168.100.129:9443/carbon/admin/login.jsp");
        log.info(result);
        //公网证书
        result = RestMock.sendGet("https://www.jianshu.com/p/a928b6c34f06");
        log.info(result);
    }
}

二、HTTPS

1、HttpURLConnection 绕过 HTTPS 的 SSL 验证

package com.chenwc.util;

import com.chenwc.enums.HttpsAlgorithmEnum;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.net.ssl.*;
import java.security.SecureRandom;
import java.security.cert.X509Certificate;

/**
 * HttpURLConnection绕过HTTPS的SSL验证
 * @author chenwc
 */
public class TrustAllHosts {

    private static final Logger log = LoggerFactory.getLogger(TrustAllHosts.class);

    /**
     * 覆盖java默认的证书验证
     */
    private static final TrustManager[] trustAllCerts = new TrustManager[]{new X509TrustManager() {
        public X509Certificate[] getAcceptedIssuers() {
            return new X509Certificate[]{};
        }

        public void checkClientTrusted(X509Certificate[] chain, String authType) {
        }

        public void checkServerTrusted(X509Certificate[] chain, String authType) {
        }
    }};

    /**
     * 设置不验证主机
     */
    public static final HostnameVerifier DO_NOT_VERIFY = (hostname, session) -> true;

    /**
     * 信任所有
     *
     * @param connection https连接
     * @return SSLSocketFactory
     */
    public static SSLSocketFactory trustAllHosts(HttpsURLConnection connection) {
        SSLSocketFactory oldFactory = connection.getSSLSocketFactory();
        try {
            //设置HTTPS的加密算法名称
            SSLContext sc = SSLContext.getInstance(HttpsAlgorithmEnum.TLSV_1_2.getAlgorithm());
            sc.init(null, trustAllCerts, new SecureRandom());
            SSLSocketFactory newFactory = sc.getSocketFactory();
            log.info("SSLContext Version: {}", sc.getProtocol());
            connection.setSSLSocketFactory(newFactory);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return oldFactory;
    }
}

2、TLS/SSL 协议枚举

package com.chenwc.enums;

/**
 * TLS/SSL 协议枚举
 * @author chenwc
 */
public enum HttpsAlgorithmEnum {
    SSL("SSL"),
    TLS("TLS"),
    TLSV_1_1("TLSv1.1"),
    TLSV_1_2("TLSv1.2");
    //JDK8不支持TLSv1.3
    //TLSV_1_3("TLSv1.3");

    private String algorithm;

    HttpsAlgorithmEnum(String algorithm) {
        this.algorithm = algorithm;
    }

    public String getAlgorithm() {
        return algorithm;
    }

    public void setAlgorithm(String algorithm) {
        this.algorithm = algorithm;
    }

    /**
     * 根据算法名称获取 HttpsAlgorithmEnum
     * @param algo 算法名称
     * @return HttpsAlgorithmEnum
     */
    public HttpsAlgorithmEnum getAlgorithmEnum(String algo) {
        for (HttpsAlgorithmEnum algorithmEnum : HttpsAlgorithmEnum.values()) {
            if (algo.equals(algorithmEnum.getAlgorithm())) {
                return algorithmEnum;
            }
        }
        return null;
    }
}


博客评论
还没有人评论,赶紧抢个沙发~
发表评论
说明:请文明发言,共建和谐网络,您的个人信息不会被公开显示。