You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过局域网(WiFi)在两个Java应用间实现方法调用?

问题描述

我有两个通过局域网(WiFi网络)连接的Java应用,第一个为ServerApp.java,代码如下:

public class ServerApp {
    public static void zzz(){
        System.out.println("hi");
    }
    public static void main(String[] args) {
        try {
            ServerSocket ss=new ServerSocket(6666);
            Socket s=ss.accept();
            DataInputStream dis = new DataInputStream(s.getInputStream());
            String str =(String)dis.readUTF();
            System.out.print("message : "+str);
            ss.close();
        } catch (IOException e) {
            System.out.println(e);
        }
    }
}

现需实现从其中一个Java应用调用另一个应用中的方法,请问该如何实现?

解决方案

嘿,针对你的跨Java应用方法调用需求,我结合你现有的Socket代码,给你整理了几种实用的解决方案,你可以根据自己的场景来选:

1. 基于现有Socket手动封装调用协议

这是最贴近你现有代码的方式,不用额外加框架,自己定义一套简单的调用规则就行:

改造你的ServerApp

让它能识别客户端要调用的方法名,执行对应方法后还能返回结果:

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;

public class ServerApp {
    public static void zzz(){
        System.out.println("hi");
    }

    // 加个带参数和返回值的方法示例,方便你理解扩展
    public static String getGreeting(String name) {
        return "Hello, " + name + "!";
    }

    public static void main(String[] args) {
        try {
            ServerSocket ss = new ServerSocket(6666);
            System.out.println("服务器已启动,等待客户端连接...");
            Socket s = ss.accept();
            
            DataInputStream dis = new DataInputStream(s.getInputStream());
            DataOutputStream dos = new DataOutputStream(s.getOutputStream());
            
            // 读取客户端发来的调用指令,我们约定格式是「方法名:参数1,参数2...」
            String callCommand = dis.readUTF();
            System.out.println("收到调用指令: " + callCommand);
            
            // 解析指令,处理不同方法调用
            String[] parts = callCommand.split(":");
            String methodName = parts[0];
            String result = "";
            
            switch(methodName) {
                case "zzz":
                    zzz();
                    result = "zzz方法执行完成";
                    break;
                case "getGreeting":
                    if(parts.length > 1) {
                        result = getGreeting(parts[1]);
                    } else {
                        result = "getGreeting方法缺少参数";
                    }
                    break;
                default:
                    result = "未知方法: " + methodName;
            }
            
            // 把执行结果回传给客户端
            dos.writeUTF(result);
            
            // 记得关闭资源
            dis.close();
            dos.close();
            s.close();
            ss.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

写个ClientApp来调用

客户端负责发送方法调用请求,接收服务器返回的结果:

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;

public class ClientApp {
    public static void main(String[] args) {
        try {
            // 这里替换成服务器的局域网IP,比如你服务器电脑的IP是192.168.1.100就填这个
            Socket s = new Socket("192.168.1.100", 6666);
            DataOutputStream dos = new DataOutputStream(s.getOutputStream());
            DataInputStream dis = new DataInputStream(s.getInputStream());
            
            // 调用zzz方法
            dos.writeUTF("zzz");
            System.out.println("服务器返回: " + dis.readUTF());
            
            // 调用带参数的getGreeting方法
            dos.writeUTF("getGreeting:Mustafa");
            System.out.println("服务器返回: " + dis.readUTF());
            
            dos.close();
            dis.close();
            s.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

这种方式的好处是轻量,完全用JDK自带的API就能实现,但缺点是要自己处理参数解析、异常和方法扩展,适合简单的小场景。

2. 使用Java RMI(远程方法调用)

这是Java官方提供的远程调用方案,更规范,适合需要频繁调用多个方法的复杂场景:

步骤1:定义远程接口

首先要写一个继承Remote的接口,所有要远程调用的方法都要在这里声明,而且必须抛出RemoteException:

import java.rmi.Remote;
import java.rmi.RemoteException;

public interface RemoteService extends Remote {
    void zzz() throws RemoteException;
    String getGreeting(String name) throws RemoteException;
}

步骤2:实现服务器端的远程服务

写一个类实现上面的接口,继承UnicastRemoteObject:

import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;

public class RemoteServiceImpl extends UnicastRemoteObject implements RemoteService {
    protected RemoteServiceImpl() throws RemoteException {
        super();
    }

    @Override
    public void zzz() throws RemoteException {
        System.out.println("hi");
    }

    @Override
    public String getGreeting(String name) throws RemoteException {
        return "Hello, " + name + "!";
    }
}

步骤3:启动RMI服务器

把服务注册到RMI注册表中:

import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;

public class RMIServer {
    public static void main(String[] args) {
        try {
            RemoteService service = new RemoteServiceImpl();
            // 用默认的RMI端口1099创建注册表
            Registry registry = LocateRegistry.createRegistry(1099);
            // 把服务绑定到注册表,名字叫RemoteService
            registry.rebind("RemoteService", service);
            System.out.println("RMI服务器已启动,服务已注册");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

步骤4:客户端调用RMI服务

客户端连接到服务器的注册表,获取服务后直接调用方法:

import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;

public class RMIClient {
    public static void main(String[] args) {
        try {
            // 连接服务器的RMI注册表,替换成服务器的局域网IP
            Registry registry = LocateRegistry.getRegistry("192.168.1.100", 1099);
            RemoteService service = (RemoteService) registry.lookup("RemoteService");
            
            // 直接调用远程方法,跟调用本地方法一样
            service.zzz();
            String greeting = service.getGreeting("Mustafa");
            System.out.println(greeting);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

注意:运行RMI时,两端的远程接口类必须完全一致(包名、类名、方法签名都要一模一样),JDK9+可能需要加一些模块参数或者设置安全策略,具体可以根据报错调整。

3. 轻量级HTTP远程调用(比如Spring Boot)

如果你的应用是Spring Boot项目,用REST接口来实现会更通用,甚至支持跨语言调用:

服务器端(Spring Boot)

写一个Controller暴露方法为HTTP接口:

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class RemoteMethodController {
    @GetMapping("/zzz")
    public String zzz() {
        System.out.println("hi");
        return "zzz方法执行完成";
    }

    @GetMapping("/greet/{name}")
    public String getGreeting(@PathVariable String name) {
        return "Hello, " + name + "!";
    }
}

客户端调用

用Spring的RestTemplate来调用这些接口:

import org.springframework.web.client.RestTemplate;

public class HttpClient {
    public static void main(String[] args) {
        RestTemplate restTemplate = new RestTemplate();
        // 替换成服务器的局域网IP和Spring Boot的端口(默认8080)
        String zzzResponse = restTemplate.getForObject("http://192.168.1.100:8080/zzz", String.class);
        System.out.println(zzzResponse);
        
        String greeting = restTemplate.getForObject("http://192.168.1.100:8080/greet/Mustafa", String.class);
        System.out.println(greeting);
    }
}

这种方式的优势是通用性极强,任何支持HTTP的客户端都能调用,适合分布式场景,但需要引入Spring相关依赖。


内容的提问来源于stack exchange,提问作者mustafa-naeem

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.22 08:21:41