在使用httpclient请求用MultipartEntityBuilder配置参数时,远程服务器无法获取参数...

本文介绍了一种在使用HTTPClient进行远程服务器调用时遇到的问题,即远程服务器无法获取到HTTP Post请求中传递的参数。文章详细展示了在本地环境下能够正常获取参数的情况下,远程服务器却无法获取的具体情况,并给出了一个特定场景下的解决方案。

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

在使用httpclient请求时,远程服务器无法获取参数。
1、包版本:httpclient-4.5.3.jar,httpcore-4.4.6.jar,httpmime-4.5.3.jar
2、本地同一服务器通过httpclient调用可以获取到传递的参数([color=red]**通过**[/color])
3、本地不同服务器通过httpclient调用可以获取到传递的参数([color=red]**通过**[/color])
4、远程服务器通过httpclient调用不能获取到传递的参数([color=red]**不通过**[/color])
5、已确保参数名一致,因为换一种写法可以获取到参数

代码:

/**
* 提交数据,返回JSONObject对象
*
* @param url 请求路径
* @param headerParams 请求头消息参数
* @param requestParams 请求业务参数
*
* @return
*/
public static JSONObject httpPostToJson(String url,JSONObject headerParams,JSONObject requestParams) {
HttpPost httpPost = null;
JSONObject jsonObject = new JSONObject();
try {

// 创建HttpClient实例
HttpClient httpClient = HttpClients.createDefault();

// 创建httpPost实例,设置超时和头消息
httpPost = createHttpPost(url,headerParams);

//设置httpPost请求参数
setHttpRequestParams(httpPost, requestParams);

//执行httpPost请求
jsonObject = executeHttpClient(httpClient, httpPost);

} catch (Exception e) {
e.printStackTrace();
jsonObject.put("code", ERROR_STATUS_CODE);
jsonObject.put("msg", "服务器遇到错误,无法完成请求");
jsonObject.put("data", "{}");
}finally{
if(httpPost != null){
httpPost.abort();
}
}

/**
* 创建httpPost请求,设置超时和头消息
*
* @param _url 请求路径
* @param headerParams 头参数集合
* @return
*/
private static HttpPost createHttpPost(String _url, JSONObject headerParams)throws Exception{

// 创建Post方法实例
HttpPost httpPost = new HttpPost(_url);

// 设置连接超时
RequestConfig requestConfig = RequestConfig.custom()
.setConnectTimeout(CONNECT_TIME_OUT).setConnectionRequestTimeout(CONNECTION_REQUEST_TIME_OUT)
.setSocketTimeout(SOCKET_TIME_OUT).build();
httpPost.setConfig(requestConfig);

// 构造消息头

//设置头参数
if(headerParams != null){
for(Object key : headerParams.keySet()){
httpPost.setHeader(key.toString(), headerParams.getString(key.toString()));
}
}

return httpPost;
}

/**
* 设置请求参数
*
* @param httpPost
* @param jsonObj
* @param in
*/
private static void setHttpRequestParams(HttpPost httpPost,JSONObject jsonObj)throws Exception{
MultipartEntityBuilder builder = MultipartEntityBuilder.create();
builderHttpRequestParams(httpPost, builder, jsonObj);
}

/**
* 设置请求参数
*
* @param httpPost
* @param jsonObj
* @param in
*/
private static void builderHttpRequestParams(HttpPost httpPost,MultipartEntityBuilder builder,JSONObject jsonObj)throws Exception{
if(jsonObj != null){
for(Object key : jsonObj.keySet()){
builder.addTextBody(key.toString(), jsonObj.getString(key.toString()));
}
}
HttpEntity entity = builder.build();
httpPost.setEntity(entity);
}


解决方案([b][color=red]不是所有环境都能用[/color][/b]):

public void processUpload(HttpServletRequest request, HttpServletResponse response){

//检测是不是存在上传文件
boolean isMultipart = ServletFileUpload.isMultipartContent(request);

if(isMultipart){
DiskFileItemFactory factory = new DiskFileItemFactory();

// Create a new file upload handler
ServletFileUpload upload = new ServletFileUpload(factory);

List<FileItem> items = null;

try {
// 解析request请求
items = upload.parseRequest(request);
} catch (FileUploadException e) {
e.printStackTrace();
}

if(items!=null){
//解析表单项目
Iterator<FileItem> iter = items.iterator();
while (iter.hasNext()) {
FileItem item = iter.next();

//如果是普通表单属性
if (item.isFormField()) {
//相当于input的name属性 <input type="text" name="content">
String name = item.getFieldName();

//input的value属性
String value = item.getString();

System.out.println("属性:" + name + " 属性值:" + value);
}
//如果是上传文件
else {
//属性名
String fieldName = item.getFieldName();

//上传文件路径
String fileName = item.getName();
fileName = fileName.substring(fileName.lastIndexOf("/") + 1);// 获得上传文件的文件名


}
}
}
}
}
<think>好的,我现在要解决的问题是用户询问如何让Java调用不在同一服务器的Flink作业。首先,我需要理解用户的具体需求。他们可能有一个Java应用程序运行在一个服务器上,而Flink集群部署在另一个服务器,用户希望Java应用能够触发或与Flink作业交互。 首先,我应该考虑Flink的常见部署模式,比如Standalone、YARN、Kubernetes等。不同的部署方式会影响调用方式。但不管哪种部署,核心思路应该是通过Flink的REST API或者客户端库来提交和管理作业。 接下来,用户提到Java调用,所以可能需要使用Flink的Java客户端。需要确认Flink是否提供了相关的API。Flink的JobClient或者通过REST API提交作业可能是可行的方法。 然后,考虑网络连接问题。不同服务器之间的通信需要确保网络可达,端口开放。比如,Flink的REST API默认端口是8081,需要检查防火墙设置,确保Java应用所在服务器可以访问Flink服务器的这个端口。 另外,作业提交的方式。用户可能需要将Flink作业打包成JAR文件,然后通过REST API或客户端提交。需要指导用户如何构建JAR,以及如何通过代码或HTTP请求发送这个JAR到Flink集群。 还要考虑安全性,比如是否需要认证,如果Flink集群开启了安全措施,可能需要传递Token或其他认证信息。 可能的步骤包括: 1. 打包Flink作业为JAR文件。 2.Java应用中通过REST API或Flink客户端提交JAR到集群。 3. 处理作业提交后的监控和管理,比如获取作业状态。 需要验证这些步骤是否正确,比如查阅Flink官方文档,确认REST API的端点和使用方法。例如,提交作业的REST API可能是POST /jars/upload上传JAR,然后POST /jars/{jarid}/run触发执行。 同,可能存在的错误点包括JAR文件路径问题,依赖冲突,序列化问题,或者网络配置错误。需要提醒用户注意这些方面,并提供排查建议,比如检查REST响应状态码、日志信息等。 总结来说,回答需要分步骤说明如何配置和调用,强调REST API和客户端库的使用,网络要求,以及常见问题的解决方法。确保用户能够按照步骤操作,并理解每一步的作用。</think>要让Java应用程序调用不在同一服务器的Apache Flink集群,可以通过以下步骤实现: 1. **Flink集群准备** - 确保目标Flink集群已启动且REST接口开放(默认端口8081) - 检查防火墙规则允许Java应用服务器访问Flink服务器的REST端口 2. **作业打包** ```bash mvn clean package # 生成包含Flink作业的JAR文件 ``` 3. **Java调用方案(二选一)** **方案一:通过REST API调用** ```java // 使用HttpClient上传JAR并提交作业 CloseableHttpClient client = HttpClients.createDefault(); String uploadUrl = "http://flink-server:8081/jars/upload"; File jarFile = new File("your-job.jar"); HttpPost uploadReq = new HttpPost(uploadUrl); MultipartEntityBuilder builder = MultipartEntityBuilder.create(); builder.addBinaryBody("jarfile", jarFile); uploadReq.setEntity(builder.build()); // 执行上传获取响应中的JAR ID HttpResponse response = client.execute(uploadReq); String jarId = parseJarIdFromResponse(response); // 需要解析响应获取JAR ID // 提交作业执行 String runUrl = "http://flink-server:8081/jars/" + jarId + "/run"; HttpPost runReq = new HttpPost(runUrl); StringEntity params = new StringEntity("{\"programArgs\":\"--input hdfs://...\"}"); runReq.setHeader("Content-Type", "application/json"); HttpResponse runResponse = client.execute(runReq); ``` **方案二:使用Flink Client API(需网络互通)** ```java EnvironmentSettings settings = EnvironmentSettings .newInstance() .useRemoteCluster("flink-server", 8081) .build(); StreamExecutionEnvironment env = StreamExecutionEnvironment .createRemoteEnvironment("flink-server", 8081, settings); // 构建你的Flink作业逻辑 DataStream<String> dataStream = env .addSource(new FlinkKafkaConsumer<>("topic", ...)); dataStream.print(); env.execute("Remote Flink Job"); ``` 4. **关键配置检查** - Flink服务器`flink-conf.yaml`需要配置: ```yaml rest.address: 0.0.0.0 # 允许远程访问 rest.port: 8081 ``` 5. **常见问题排查** - 网络连通性测试:使用`telnet flink-server 8081`验证端口可达性 - 检查作业依赖:确保JAR文件包含所有必需依赖(推荐使用`shaded`打包方式) - 查看Flink Web UI:通过`http://flink-server:8081`监控作业状态 **两种方案对比:** | 对比项 | REST API方案 | Client API方案 | |---------------|------------------------------|-----------------------------| | 耦合度 | 低 | 较高(需Flink客户端依赖) | | 适用场景 | 简单作业触发 | 需要动态生成作业逻辑 | | 部署要求 | 只需HTTP访问 | 需要开放JobManager端口(6123)| | 作业更新 | 需重新上传JAR | 可动态调整作业逻辑 | 实际选择: - 如果是固定作业定期执行,推荐使用REST API方案 - 如果需要动态生成处理逻辑,建议使用Client API方案 **注意事项:** 1. 生产环境建议启用HTTPS和认证机制 2. 作业参数需进行合法性校验 3. 建议添加重试机制处理网络波动 4. 推荐使用连接池管理HTTP客户端资源
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值