项目背景
最近在项目上对接了国内某公司的报警信息,对接过程中有个不太好解决的问题,我在这里跟大家分享一下,希望能够对大家有所帮助。
希望你能够认真、用心观看,会对你有帮助的。
异常再现
我需要在服务器上访问用户给我提供的一个公网的 https 接口地址,如下:

我在本地打成 jar 包后,我运行了一下,发现没有任何问题。
于是就通过用户的堡垒机,登录上去开始部署 jdk,然后将 jar 包上传,然后启动。
启动命令如下:
bash
java -server -jar sd-yunli.jar -server.port=8999 >> yunli.log 2>&1 &
启动之后报了个错误,如下:

提示找不到主机,于是我就去/etc/hosts中配置 host 主机名,如下:

配置好了,我再次启动了 jar 包,还是报同样的错误。
分析问题
我在离开客户现场之前,用户使用curl命令在服务器上,验证了他的接口没有问题。

大家可以看到没有任何问题,接口成功响应,所以我就不知道这是怎么回事了。
照理说同一台服务器使用curl命令,跟我用java程序跑应该差不多啊,怎么会这样呢?
大家别急,接下来就是重点。
剖析问题
curl命令
我们首先看下,curl命令为什么可以?
我们通过命令,查看curl命令的执行过程,执行如下命令:
bash
curl -v -X POST "接口地址" -F "files=@图片名称1" -F "files=@图片名称2"

我们看到该命令是通过一个代理完成了操作,所以就验证了为什么 curl 命令可以,我们用 java 程序不可以。
验证网络端口是否互通

通过telnet命令验证了,我本地是通的,服务器上是不通的。
解决问题
通过对 curl 命令的执行过程进行了剖析,我们发现 curl 走了代理,于是开始配置代理来解决这个问题。
使用环境变量(用户给出建议)

验证结果,还是连接超时。
通过 java 命令参数
java
java -Dhttps.proxyHost=10.*.*.16 -Dhttps.proxyPort=3*28 -server -jar sd-yunli.jar -server.port=8999 >> yunli.log 2>&1 &
验证结果,还是连接超时。
通过自定义验证(解决问题)
-
通过实现接口,自定义主机验证。
javapackage com.yunli.sd.config; import lombok.extern.slf4j.Slf4j; import javax.net.ssl.SSLSession; /** * 自定义主机名验证器 * @author pgq * @date 2026/02/08 10:33 */ @Slf4j public class HostnameVerifier implements javax.net.ssl.HostnameVerifier { @Override public boolean verify(String hostname, SSLSession session) { log.info("验证主机名:{}", hostname); return true; } } -
在 http 请求中使用该验证
javapackage com.yunli.sd.utils; import com.yunli.sd.config.HostnameVerifier; import com.yunli.sd.fetch.dto.WarningDto; import okhttp3.*; import org.apache.http.client.methods.CloseableHttpResponse; import org.apache.http.client.methods.HttpPost; import org.apache.http.entity.StringEntity; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClients; import org.apache.http.util.EntityUtils; import lombok.extern.slf4j.Slf4j; import java.io.File; @Slf4j public class HttpUtils { public static String uploadFile(WarningDto warningDto, String url) { String result = ""; try { OkHttpClient client = new OkHttpClient.Builder().hostnameVerifier(new HostnameVerifier()).build(); MultipartBody.Builder requestBodyBuilder = new MultipartBody.Builder() .setType(MultipartBody.FORM); File file1 = new File(warningDto.getOriginalPicture()); requestBodyBuilder.addFormDataPart("files", file1.getName(), RequestBody.create(MediaType.parse("image/jpeg"), file1)); File file2 = new File(warningDto.getDrawPicture()); requestBodyBuilder.addFormDataPart("files", file2.getName(), RequestBody.create(MediaType.parse("image/jpeg"), file2)); Request request = new Request.Builder() .url(url) .post(requestBodyBuilder.build()) .build(); Response response = client.newCall(request).execute(); if (response.isSuccessful()) { result = response.body().string(); log.info("上传成功,响应内容:{}", result); } else { log.info("上传失败,错误码:" + response.code()); } } catch (Exception e) { log.error("上传接口异常:{}", e); e.printStackTrace(); } return result; } }启动命令:
javajava -Dhttps.proxyHost=10.*.*.16 -Dhttps.proxyPort=3128 -server -jar sd-yunli.jar -server.port=8999 >> yunli.log 2>&1 &
总结
-
通过自定义接口,解决 https 接口地址证书验证无法通过的问题

-
其实我们也需要跟 curl 命令一样也需要走代理,我们通过 jar 命令行启动参数,去指定 https 协议需要使用的 host 和 port