Java 发送Http请求 java.net.URL

本文介绍了一个用于模拟HTTP协议的工具类,包含GET和POST请求的实现,以及如何上传文件。详细展示了如何设置请求头,读取响应内容,并提供了文件上传的具体流程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

package com.demo.utils;

import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

import java.net.HttpURLConnection;
import java.net.URL;


/**
 * http工具
 * @author lenovo
 *
 */
public final class HttpRequestUtils {
    /**
     * 模拟http协议发送get请求
     **/
    public static String sendGetRequest(String url) {
        String result = "";
        InputStream in = null;

        HttpURLConnection connection = null;

        try {
            URL httpUrl = new URL(url);
            connection = (HttpURLConnection) httpUrl.openConnection();
            connection.setRequestProperty("accept", "*/*");
            connection.setRequestProperty("Charset", "UTF-8");
            connection.setRequestProperty("connection", "Keep-Alive");
            connection.setRequestProperty("user-agent",
                    "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
            connection.setRequestMethod("GET");
            connection.connect();

            if (connection.getResponseCode() == 200) {
                in = connection.getInputStream();

                ByteArrayOutputStream bs = new ByteArrayOutputStream();
                int n = 0;
                byte[] datas = new byte[2048];

                while ((n = in.read(datas)) != -1) {
                    bs.write(datas, 0, n);
                }

                bs.flush();
                result = new String(bs.toByteArray(), "utf-8");
            }
        } catch (Exception ex) {
            ex.printStackTrace();
        } finally {
            try {
                if (in != null) {
                    in.close();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }

            try {
                connection.disconnect();
            } catch (Exception ex) {
            }
        }

        return result;
    }

    /**
     * 模拟http协议发送post请求
     **/
    public static String sendPostRequest(String url, String param) {
        InputStream in = null;
        String result = "";
        HttpURLConnection connection = null;

        try {
            URL httpUrl = new URL(url);
            connection = (HttpURLConnection) httpUrl.openConnection();
            connection.setRequestProperty("accept", "*/*");
            connection.setRequestProperty("Charset", "UTF-8");
            connection.setRequestProperty("connection", "Keep-Alive");
            connection.setRequestProperty("user-agent",
                    "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
            connection.setRequestMethod("POST");
            connection.setDoOutput(true);
            connection.setDoInput(true);
            connection.setUseCaches(false);
            connection.getOutputStream().write(param.getBytes("utf-8"));
            connection.getOutputStream().flush();

            if (connection.getResponseCode() == 200) {
                in = connection.getInputStream();

                ByteArrayOutputStream bs = new ByteArrayOutputStream();
                int n = 0;
                byte[] datas = new byte[2048];

                while ((n = in.read(datas)) != -1) {
                    bs.write(datas, 0, n);
                }

                bs.flush();
                result = new String(bs.toByteArray(), "utf-8");
            }
        } catch (Exception ex) {
            ex.printStackTrace();
        } finally {
            try {
                if (in != null) {
                    in.close();
                }
            } catch (IOException ex) {
                ex.printStackTrace();
            }

            try {
                connection.disconnect();
            } catch (Exception ex) {
            }
        }

        return result;
    }

    /**
     * 普通post文件上传
     */
    public static String upLoadAttachment(String url, String fileName, File file) {
        String result = null;

        HttpURLConnection connection = null;
        BufferedReader reader = null;

        try {
            URL httpUrl = new URL(url);
            connection = (HttpURLConnection) httpUrl.openConnection();
            connection.setRequestProperty("accept", "*/*");
            connection.setRequestProperty("Charset", "UTF-8");
            connection.setRequestProperty("connection", "Keep-Alive");
            connection.setRequestProperty("user-agent",
                    "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
            connection.setRequestMethod("POST");
            connection.setConnectTimeout(5000);
            connection.setReadTimeout(5000);
            connection.setDoOutput(true);
            connection.setDoInput(true);
            connection.setUseCaches(false);

            String bound = "----------" + System.currentTimeMillis();
            connection.setRequestProperty("Content-Type",
                    "multipart/form-data; boundary=" + bound);

            StringBuilder sb = new StringBuilder();
            sb.append("--");
            sb.append(bound);
            sb.append("\r\n");
            sb.append("Content-Disposition: form-data;name=\"" + fileName +
                    "\";filename=\"" + file.getName() + "\"\r\n");
            sb.append("Content-Type:application/octet-stream\r\n\r\n");

            byte[] data = sb.toString().getBytes("utf-8");
            OutputStream out = new DataOutputStream(connection.getOutputStream());
            out.write(data);

            DataInputStream in = new DataInputStream(new FileInputStream(file));
            int bytes = 0;
            byte[] bufferOut = new byte[1024];

            while ((bytes = in.read(bufferOut)) != -1) {
                out.write(bufferOut, 0, bytes);
            }

            in.close();

            byte[] foot = ("\r\n--" + bound + "--\r\n").getBytes("utf-8"); // 定义最后数据分隔线
            out.write(foot);
            out.flush();
            out.close();

            InputStream inn = connection.getInputStream();
            ByteArrayOutputStream bs = new ByteArrayOutputStream();
            int n = 0;
            byte[] datas = new byte[2048];

            while ((n = inn.read(datas)) != -1) {
                bs.write(datas, 0, n);
            }

            bs.flush();
            result = new String(bs.toByteArray(), "utf-8");

            return result;
        } catch (Exception ex) {
            ex.printStackTrace();
        } finally {
            try {
                connection.disconnect();
            } catch (Exception ex) {
            }
        }

        return null;
    }
}

 

<think>好的,用户现在遇到了一个问题,他们在容器内部使用服务名称`ocr_service`时出现了`java.net.UnknownHostException: ocr_service`异常,但之前通过`nslookup`确认DNS解析是正常的。需要分析问题原因并提供解决方案。 首先,回顾之前的分析:容器的网络配置正确,`ocr_service`在Docker的自定义网络`zjck-net`中,IP地址为`172.18.0.6`,并且容器内部的DNS服务器是Docker内置的`127.0.0.11`,`nslookup`可以成功解析`ocr_service`到正确的IP。同时,服务在容器内监听`8866`端口,绑定在`0.0.0.0`,说明服务本身配置正确,可以接受外部连接。 现在的问题是,当应用程序尝试通过主机名`ocr_service`进行连接时,却无法解析,导致异常。可能的几个原因需要逐一排查: 1. **DNS解析失败**:虽然`nslookup`可以解析,但应用程序使用的DNS解析方式可能不同。比如,Java应用可能使用了不同的DNS解析机制,或者存在缓存问题。 2. **JVM的DNS缓存**:Java虚拟机可能有DNS缓存,导致即使DNS配置正确,旧的缓存信息仍被使用,从而无法解析新的记录。 3. **应用程序配置问题**:可能在代码中硬编码了某些DNS设置,或者未正确配置使用系统的DNS解析器。 4. **Docker网络配置问题**:虽然网络配置看起来正确,但可能存在其他容器或网络设置导致的问题,如容器不在同一网络,或者DNS服务未正确运行。 **具体分析步骤**: - **检查应用程序的DNS解析机制**:确认应用程序是否使用了与`nslookup`相同的DNS服务器。`nslookup`使用的是系统配置的DNS,而Java应用默认可能使用不同的方式。可以检查Java的DNS设置,或者尝试在代码中强制指定DNS服务器。 - **验证JVM的DNS缓存**:Java默认会缓存DNS解析结果,可以通过设置`networkaddress.cache.ttl`来调整缓存时间,或者禁用缓存,以测试是否是缓存导致的问题。 - **检查容器是否在同一个Docker网络**:确保所有需要通信的容器都连接到同一个自定义网络`zjck-net`,这样Docker的内置DNS才能正确解析服务名称。 - **确认服务名称的正确性**:在代码中使用的服务名称是否与Docker容器名称或服务名称一致,是否存在拼写错误。 - **网络连接测试**:在容器内部使用`ping`或`curl`命令测试连接到`ocr_service`,确认网络层是否可达,而不仅仅是DNS解析正确。 - **检查防火墙或安全组设置**:虽然Docker通常会自动处理网络规则,但有时宿主机或容器内部的防火墙可能会阻止连接,需要确认相关端口是否开放。 **解决方案建议**: 1. **强制使用IPv4**:Java可能优先尝试IPv6解析,而Docker网络可能仅配置了IPv4。可以通过JVM参数`-Djava.net.preferIPv4Stack=true`强制使用IPv4。 2. **调整JVM DNS缓存设置**:在启动JVM时添加参数,如`-Dsun.net.inetaddr.ttl=0`来禁用DNS缓存,或者设置较短的TTL值,以便及时获取最新的DNS记录。 3. **检查容器网络连接**:确保发起请求的容器和`ocr_service`容器都连接到同一个Docker网络`zjck-net`,否则无法通过服务名称解析。 4. **使用Docker内部DNS**:在应用程序中,确保DNS解析使用的是Docker内置的DNS服务器`127.0.0.11`,而非外部DNS服务器。 5. **代码中直接使用IP地址测试**:作为临时解决方案,将`ocr_service`替换为`172.18.0.6`,如果连接成功,则问题确实出在DNS解析上,需进一步排查Java的DNS配置。 6. **查看Java应用的详细错误日志**:确认是否有更详细的错误信息,例如连接超时或其他网络问题,帮助进一步定位问题。 **验证步骤**: - 在应用程序所在的容器内部,运行`ping ocr_service`,确认是否能解析出正确的IP并收到响应。 - 使用`curl http://ocr_service:8866`或类似命令测试HTTP连接,确认服务是否可达。 - 检查Java应用的启动参数,确认是否有自定义的DNS设置或网络配置。 通过以上步骤,可以逐步缩小问题范围,最终找到导致`UnknownHostException`的具体原因,并采取相应的解决措施。</think>以下是针对您遇到的问题的详细分析和解决方案: --- ### **问题诊断** #### **现象描述** - 在容器内部通过`nslookup ocr_service`能正确解析到IP `172.18.0.6` - 服务端口`8866`监听正常(`0.0.0.0:8866`) - 但Java应用程序报错:`java.net.UnknownHostException: ocr_service: 未知的名称或服务` #### **根本原因** 1. **Java DNS解析机制与Docker的兼容性问题** - Java默认优先使用IPv6解析,而Docker自定义网络可能仅配置IPv4地址。 - Java的DNS缓存机制可能导致无法及时更新Docker动态分配的容器IP。 2. **容器间网络配置问题** - 发起请求的容器与`ocr_service`可能不在同一Docker网络(`zjck-net`)。 - 容器未正确使用Docker内置DNS服务器(`127.0.0.11`)。 --- ### **解决方案** #### 方法一:强制Java使用IPv4(推荐) 在Java启动命令中添加以下参数,强制使用IPv4协议: ```bash -Djava.net.preferIPv4Stack=true ``` **示例**: ```bash java -Djava.net.preferIPv4Stack=true -jar your_application.jar ``` #### 方法二:禁用JVM DNS缓存 调整DNS缓存时间,确保实时解析Docker动态IP: ```bash -Dsun.net.inetaddr.ttl=0 # 禁用缓存 -Dsun.net.inetaddr.negative.ttl=0 ``` **示例**: ```bash java -Dsun.net.inetaddr.ttl=0 -Dsun.net.inetaddr.negative.ttl=0 -jar your_application.jar ``` #### 方法三:检查容器网络配置 1. **确认容器在同一网络** 运行以下命令检查所有容器是否连接到`zjck-net`: ```bash docker network inspect zjck-net | grep "Containers" ``` 2. **显式指定容器网络** 启动其他容器时,需明确加入`zjck-net`网络: ```bash docker run --network zjck-net your_image ``` #### 方法四:直接使用容器IP(临时测试) 在代码中暂时将`ocr_service`替换为`172.18.0.6`,验证服务是否可达: ```java String serviceUrl = "http://172.18.0.6:8866"; ``` - 若测试成功,说明问题出在DNS解析环节。 --- ### **验证步骤** 1. **测试容器间连通性** 在发起请求的容器内执行: ```bash ping ocr_service # 应返回IP 172.18.0.6 curl http://ocr_service:8866 # 验证HTTP连接 ``` 2. **检查DNS解析日志** 在Java应用中启用DNS调试日志: ```bash -Djavax.net.debug=all ``` 3. **查看Docker DNS配置** 进入容器检查`/etc/resolv.conf`文件,确认DNS服务器为`127.0.0.11`: ```bash docker exec -it your_container cat /etc/resolv.conf ``` --- ### **配置示意图** ```plaintext Java应用容器 -> Docker DNS (127.0.0.11) -> 解析 ocr_service -> 172.18.0.6:8866 ``` --- ### **附加说明** - **Docker DNS工作原理** Docker为每个自定义网络维护一个内嵌DNS服务器(`127.0.0.11`),容器间通过服务名称通信时,需确保所有容器在同一网络。 - **Java与IPv6的兼容性** 若容器未启用IPv6,需强制Java使用IPv4协议,避免因协议不匹配导致解析失败。 通过上述方法,应能解决`UnknownHostException`问题。若仍不生效,请提供应用程序的完整错误日志及容器网络拓扑。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值