Java中如何实现Restful API与Socket服务端对接
Java Socket服务端调用REST API连接失败问题解决方案
方案合理性说明
- 用JDK原生
HttpURLConnection从Socket服务端发起HTTP请求调用已有的MySQL RESTful API是完全可行的,不需要更换技术栈。连接失败不是技术选型错误,是代码逻辑和资源处理存在问题。 - 单独新建Maven项目存放
Server.java和Client.java不是必需操作。HttpURLConnection是JDK内置类,不需要额外引入依赖,只要在原有Socket项目中保证JDK版本正常即可运行,不需要拆分独立项目。如果后续需要做两个服务的进程级部署隔离,再拆分项目也不晚。
现有代码的核心问题
- 代码执行顺序错误:HTTP请求逻辑写在了
socket = server.accept()之后。accept()是阻塞方法,在没有Socket客户端连接到5000端口之前,程序会一直卡在这一行,根本不会执行后续的HTTP请求代码,表现出来就是“始终连接失败”。 - 资源释放不规范:HTTP请求的输出流没有手动关闭,部分内嵌的HTTP服务器(比如Spring Boot的Tomcat)会因为没有收到完整的请求终止标识,一直等待客户端发送数据导致请求超时。
- 异常和超时配置缺失:没有设置连接、读取超时,异常只做统一打印,无法定位是端口不通、路径错误还是请求格式不匹配的问题。
修正后的参考代码
把HTTP请求逻辑抽成独立方法,根据业务需要选择触发时机:如果需要Socket服务启动就调用API,就把调用逻辑放在accept()之前;如果需要收到Socket客户端消息时触发,就把调用逻辑放到消息读取的循环内。
import java.io.BufferedInputStream; import java.io.DataInputStream; import java.io.IOException; import java.io.OutputStream; import java.net.HttpURLConnection; import java.net.ServerSocket; import java.net.Socket; import java.net.URL; import java.nio.charset.StandardCharsets; public class Server { private Socket socket = null; private ServerSocket server = null; private DataInputStream in = null; public Server(int port) { try { server = new ServerSocket(port); System.out.println("Socket服务已启动,监听端口:" + port); // 服务启动即调用REST API的场景放开下面这行 // callRestApi(); System.out.println("等待Socket客户端连接..."); socket = server.accept(); System.out.println("客户端已连接"); in = new DataInputStream(new BufferedInputStream(socket.getInputStream())); String line = ""; while (!line.equals("Stop")) { try { line = in.readUTF(); System.out.println("收到客户端消息:" + line); // 收到特定消息触发API调用的场景在这里调用 // if ("update_db".equals(line)) { // callRestApi(); // } } catch (IOException i) { System.out.println("读取Socket消息出错:" + i.getMessage()); break; } } System.out.println("关闭连接"); } catch (IOException i) { System.out.println("服务运行出错:" + i.getMessage()); } finally { // 统一释放资源避免泄漏 try { if (in != null) in.close(); if (socket != null) socket.close(); if (server != null) server.close(); } catch (IOException e) { System.out.println("释放资源出错:" + e.getMessage()); } } } private void callRestApi() throws IOException { URL url = new URL("http://localhost:8080/update/3"); HttpURLConnection http = (HttpURLConnection) url.openConnection(); http.setRequestMethod("PUT"); http.setRequestProperty("Content-Type", "application/json"); http.setDoOutput(true); // 配置超时避免无限阻塞 http.setConnectTimeout(3000); http.setReadTimeout(3000); String requestBody = "{\n \"firstName\":\"Can\",\n \"lastName\":\"Doe\",\n \"occupation\":\"xxx\"\n}"; byte[] bodyBytes = requestBody.getBytes(StandardCharsets.UTF_8); // try-with-resources自动关闭输出流,保证请求完整发送 try (OutputStream os = http.getOutputStream()) { os.write(bodyBytes); } int code = http.getResponseCode(); String msg = http.getResponseMessage(); System.out.println("REST接口返回:" + code + " " + msg); http.disconnect(); } public static void main(String args[]) { new Server(5000); } }
连接失败排查清单
如果调整代码后还是连接失败,按以下顺序排查:
- 先单独验证REST接口可用性:用curl/Postman直接发起PUT请求到
http://localhost:8080/update/3,确认接口本身能正常返回,没有报错 - 检查端口占用:确认你的REST服务确实监听在8080端口,没有被其他程序占用
- 检查接口路径:如果REST项目配置了上下文路径(比如Spring Boot设置了
server.servlet.context-path),实际请求路径要加上对应前缀 - 根据控制台错误码定位问题:
Connection refused代表REST服务没启动/端口错误;404代表请求路径不对;405代表请求方法不匹配(比如接口定义的是POST不是PUT);400代表提交的JSON格式和接口要求的参数结构不匹配。
内容的提问来源于stack exchange,提问作者Sunny
相关产品推荐
相关产品推荐

