应用访问流程
应用访问流程
本篇说明有后端服务的微应用,从前端到 Go 服务再返回的完整访问链路。
先记住这一点
前端只调用 $gm.request(),不直接连接 Unix Socket;/api/call/{组织名}/{应用名}/{方法名} 是桌面平台提供的统一入口,Go 后端只负责监听 Socket 并注册 RPC 方法。
概述
调试应用创建完成、后端服务启动后,极目桌面平台会自动进行健康检查:平台每隔 5 秒调用后端注册的 ping 方法,收到 pong 后认为服务存活。

提示
ping 是应用必需的内置心跳接口,请保留、不要删除,也不要在其中加入耗时逻辑。
后端服务示例
有后端服务的微应用采用 simplejrpc-go、Unix Socket 和 JSON-RPC 2.0。平台负责把统一入口的请求转发到后端 Socket,后端不需要自行监听 HTTP 端口。
1. 程序入口(backend/main.go)
func main() {
sock := common.DefaultSockPath()
// 创建 RPC Server 并注册服务
server := rpc.NewServer()
// 启动服务(阻塞,收到 SIGINT/SIGTERM 优雅退出)
if err := server.Start(sock); err != nil {
core.Container.Log().Error(fmt.Sprintf("启动RPC服务器失败: %v", err))
return
}
}2. 注册方法(internal/handler/rpc/server.go)
后端对外提供的每一个方法,都需要先注册方法名:
func (s *Server) RegisterHandles(ds interface {
RegisterHandle(name string, handler func(*gsock.Request) (any, error), middlewares ...gsock.RPCMiddleware)
}) {
// 基础接口(ping 为平台健康检查接口,禁止删除或修改)
ds.RegisterHandle("ping", s.Ping)
// 示例模块
ds.RegisterHandle("hello", s.Hello)
}3. 实现方法(internal/handler/rpc/example_handler.go)
Handler 只做三件事:解析参数 → 调用 Service → 返回结果:
// Hello 示例接口:问候
// Method: hello
// Params: lang(可选,语言标识)、name(必填,姓名)
// Result: "hello {name}"
func (s *Server) Hello(req *gsock.Request) (any, error) {
// 1. 解析参数(自动设置 i18n 语言)
var args dto.HelloReq
if err := rpcutil.ParseParams(req, &args); err != nil {
return nil, err
}
// 2. 参数校验
if args.Name == "" {
return nil, fmt.Errorf("%s", gi18n.Instance().T("NameRequired"))
}
// 3. 调用 Service 并返回(响应结构由 RPC 服务自动包装)
return exampleService().Hello(args)
}对应 Service 的实现:
// Hello 示例接口:返回问候语
func (s *ExampleService) Hello(args dto.HelloReq) (string, error) {
return fmt.Sprintf("hello %s", args.Name), nil
}方法说明
| 方法 | 用途 |
|---|---|
ping | 平台健康检查心跳,必须保留,返回 pong。 |
hello | 业务示例方法,演示参数解析、校验和 Service 调用。 |
接口测试
开发阶段可以通过平台提供的统一入口测试后端方法。下面以 hello 方法的调用为例:

请求格式
以 POST 调用,请求体为标准 JSON。下面的 version 和 transport 是示例值;实际前端代码从桌面注入的 $gm 对象读取它们,不应在业务代码中写死。
{
"version": "1.0.0",
"transport": "socket",
"params": {
"lang": "zh-CN",
"name": "world"
}
}参数说明
| 字段 | 类型 | 是否必填 | 说明 |
|---|---|---|---|
version | string | 是 | 平台与应用之间的请求版本。前端从 window.$gm.version 读取,不要固定写成某个版本号。 |
transport | string | 是 | 平台使用的传输类型。前端从 window.$gm.communicationType 读取,Socket 类型的示例值为 socket。 |
params | object | 按方法决定 | 业务参数对象。它会被转发为 JSON-RPC 的参数,并由 Handler 解析到对应的 DTO;hello 方法要求 name。 |
响应格式
simplejrpc-go 会把 Handler 的返回值包装为统一响应。完整结构包含 meta:
{
"code": 200,
"data": "hello world",
"msg": "OK",
"meta": {
"endpoint": "hello",
"close": 0
}
}注意
code是后端 RPC 响应中的状态码,200表示成功;Handler 返回错误时会得到非200的响应。meta.endpoint是后端实际处理的方法名,meta.close表示 Socket 连接是否保持。
关于认证
页面通过 $gm.request() 调用后端,不需要手动拼接 Token。若你从外部工具直接请求桌面服务,需要遵循桌面服务自身的认证要求;这不属于 Go Socket RPC 的参数格式。
URL 访问规范
在 $gm.request() 中传入相对路径:
/api/call/{组织名}/{应用名}/{方法名}如果使用外部 HTTP 客户端,才需要在前面拼接桌面服务地址:
http://{桌面服务地址}/api/call/{组织名}/{应用名}/{方法名}例如调用 hello 方法:
/api/call/official/example/helloURL 组成说明:
official/example:应用标识(组织名/应用名),需与后端constant.go中的AppName一致;此处示例值为official/example。hello:后端通过RegisterHandle("hello", s.Hello)注册的 RPC 方法名。
提示
确保应用标识与创建调试应用时填写的名称完全一致,区分大小写。
前端访问后端服务
前置要求
在前端访问后端接口前,需要确保:
- 后端服务已经启动并监听 Socket;
- 有后端服务的应用已调用
$gm.init(),等待初始化请求完成后再调用业务接口。
初始化示例位于 web/index.html,默认被注释,需要根据应用是否包含后端服务决定是否启用。
访问效果

代码示例
前端调用后端 hello 方法可以按以下方式实现:
<button class="button12">发送请求</button>
<script>
document.querySelector('.button12').addEventListener('click', function () {
$gm.request('/api/call/official/example/hello', {
method: 'post',
data: {
"version": window?.$gm?.version,
"transport": window?.$gm?.communicationType,
"params": {
"lang": "zh-CN",
"name": "world"
}
}
}).then(res => {
console.log(res)
$gm.message.success(res.data.data); // hello world
})
})
</script>核心说明
- 统一入口:前端始终通过
/api/call/{组织名}/{应用名}/{方法名}调用后端,无需关心 Socket 路径与端口; - 动态参数:
version与transport从桌面注入的window.$gm中读取; - 业务参数:
params中的字段与后端 DTO 的jsontag 对应; - 两层响应:平台请求返回值通常通过
$gm.request()的res.data暴露,后端业务值位于res.data.data,不要把外层 HTTP 响应和内层 RPC 响应混为一层。
访问流程图
应用的访问流程如下:
流程说明
- 前端发起请求:用户操作触发
$gm.request(),路径中携带应用标识和方法名; - 平台统一入口接收请求:平台根据
official/example找到目标应用; - 转发到 Socket:平台将业务请求转发到应用的 Unix Socket,后端 RPC 方法名为
hello; - Handler 解析参数:
rpcutil.ParseParams()将params解析为 DTO,并根据lang设置 i18n; - Service 执行业务:Handler 调用 Service,得到
hello world; - 统一包装并返回:
simplejrpc-go生成{code, data, msg, meta},平台再把结果返回给$gm.request(); - 前端读取业务值:前端从
res.data.data读取hello world并显示提示。
Socket 路径
安装布局下,后端可执行文件位于 app/bin/main,Socket 位于同一应用包根目录下的 tmp/app.sock;本地执行 go run 时,Socket 回退到当前目录的 tmp/app.sock。前端不需要知道这个路径。
