Solon Rpc 应用开发 - 跑通第一次调用
2026年9月14日 上午5:09:42
Solon Rpc 应用通常拆成三部分:双方共享的服务接口、服务端实现、客户端消费方。体验与 Dubbo 相似。
1、 三个部分(模块)的职责
推荐把项目拆成:
user-api 共享接口和 DTO
user-provider Solon 服务端,实现接口
user-consumer Solon 客户端,调用接口
客户端只依赖 user-api 和 RPC 客户端依赖,不要把服务端数据库、Web 容器实现传递给客户端。
2、 共享接口和 DTO
package demo.api;
import java.io.Serializable;
public interface UserService {
User getById(long userId);
void add(User user);
}
public class User implements Serializable {
private long userId;
private String name;
private int level;
public long getUserId() { return userId; }
public void setUserId(long userId) { this.userId = userId; }
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public int getLevel() { return level; }
public void setLevel(int level) { this.level = level; }
}
Serializable 对多种序列化方案更稳妥;如果明确只使用 JSON,DTO 通常不要求实现它。示例不用 Lombok,避免读者还要额外寻找 Lombok 依赖。
3、 服务端
服务端依赖 org.noear:solon-web。当前仓库的 solon-web shortcut 默认组合用了 snack4 序列化插件。
package demo.provider;
import demo.api.User;
import demo.api.UserService;
import org.noear.solon.annotation.Mapping;
import org.noear.solon.annotation.Remoting;
@Remoting
@Mapping("/rpc/v1/user")
public class UserServiceImpl implements UserService {
@Override
public User getById(long userId) {
User user = new User();
user.setUserId(userId);
user.setName("demo");
user.setLevel(1);
return user;
}
@Override
public void add(User user) {
// 实际项目中在这里调用 service/repository
}
}
@Mapping 是远程入口路径;@Remoting 表明这是远程服务。
入口和配置:
import org.noear.solon.Solon;
public class ProviderApp {
public static void main(String[] args) {
Solon.start(ProviderApp.class, args);
}
}
# provider/src/main/resources/app.yml
server.port: 9001
solon.app:
group: demo
name: userapi
4、 客户端
客户端依赖共享接口,以及当前仓库中的 org.noear:nami、org.noear:nami-channel-http 和 org.noear:nami-coder-snack4。在 Solon Bean 中注入代理:
package demo.consumer;
import demo.api.User;
import demo.api.UserService;
import org.noear.nami.annotation.NamiClient;
import org.noear.nami.common.ContentTypes;
import org.noear.solon.annotation.Component;
@Component
public class UserCaller {
@NamiClient(url = "http://localhost:9001/rpc/v1/user", headers = ContentTypes.JSON)
private UserService userService;
public User load(long id) {
return userService.getById(id);
}
}
@NamiClient 支持标在接口和字段上;在 Solon 中标在字段上时由 Nami 插件注入代理。接口必须是 interface,Builder 最终也只为接口创建 JDK Proxy。
客户端如果也启动 Web 服务,使用不同端口:
server.port: 8081
solon.app:
group: demo
name: userconsumer
5、 验证调用链
- 启动 provider,确认
9001没有端口冲突。 - 启动 consumer。
- 调用
userService.getById(1)。 - 若失败,先把问题限定在固定 URL;不要马上加入注册中心。
一次调用的关键对应关系:
| 客户端 | 服务端 |
|---|---|
url 的 /rpc/v1/user | 类上的 @Mapping |
方法名 getById | 服务端接口实现方法 |
headers = ContentTypes.JSON | 服务端的 snack4/JSON 序列化支持 |
返回类型 User | 服务端返回的 DTO |