中间件使用
在联犀的rpc和api中有几个内置的中间件, 开发自己业务的时候可以快速接入使用
# api中间件
api中间件的使用需要先在api文件中进行定义,参考如下 官方参考 (opens new window)
syntax = "v1"
@server (
group: things/device/info
prefix: /api/v1/things/device/info
middleware: CheckTokenWare,InitCtxsWare //这里是中间件定义
)
service lightsvr {
@doc (
summary: "新增设备" //接口的描述
isNeedAuth: "true" //是否需要权限认证
authType: "admin" //默认只授权给管理员
)
@handler create
post /create
@doc (
summary: "更新设备" //不填为默认值,
)
@handler update
post /update
@doc (
summary: "删除设备"
isNeedAuth: "true"
authType: "admin"
)
@handler delete
post /delete
@doc (
summary: "设备控制"
businessType: "control" // 默认代码生成会将 结尾为修改为对应的操作类型组装到授权code中,如果需要特殊的则可以自定义 默认的如下 add:("create", "multi-create", "import") "modify":("update", "multi-update","send") "delete":("delete", "multi-delete") find:("index", "read", "count", "tree") 没有匹配到的则为other
)
@handler control
post /control
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
# token校验加上下文加入
这个中间件会进行token校验,记录操作日志,注入ctx(里面包含租户信息,用户信息,项目等权限信息),
# 定义位置
core/service/apisvr/exportMiddleware/middlewareCheckToken.go:47
# 初始化方式
- 配置初始化在配置文件中添加sysvr的配置信息,参考 连接联犀服务
- 中间件定义: 在
lightsvr/internal/svc/serviceContext.go
的 ServiceContext 添加 和api文件定义一致的中间件CheckTokenWare rest.Middleware
- 中间件初始化 参考代码:
package svc
import (
"gitee.com/unitedrhino/core/service/apisvr/exportMiddleware"
"gitee.com/unitedrhino/core/service/syssvr/client/log"
role "gitee.com/unitedrhino/core/service/syssvr/client/rolemanage"
tenant "gitee.com/unitedrhino/core/service/syssvr/client/tenantmanage"
user "gitee.com/unitedrhino/core/service/syssvr/client/usermanage"
"gitee.com/unitedrhino/share/ctxs"
"gitee.com/unitedrhino/share/eventBus"
"gitee.com/unitedrhino/share/utils"
"gitee.com/unitedrhino/things/service/dmsvr/client/deviceinteract"
"github.com/zeromicro/go-zero/core/logx"
"github.com/zeromicro/go-zero/core/stores/kv"
"github.com/zeromicro/go-zero/rest"
"github.com/zeromicro/go-zero/zrpc"
"lightsvr/internal/config"
)
type ServiceContext struct {
Config config.Config
InitCtxsWare rest.Middleware
CheckTokenWare rest.Middleware
DeviceInteract deviceinteract.DeviceInteract
FastEvent *eventBus.FastEvent
Store kv.Store
NodeID int64
}
func NewServiceContext(c config.Config) *ServiceContext {
var (
deviceInteract deviceinteract.DeviceInteract
checkTokenWare rest.Middleware
)
deviceInteract = deviceinteract.NewDeviceInteract(zrpc.MustNewClient(c.DmRpc.Conf))
nodeID := utils.GetNodeID(c.CacheRedis, c.Name)
fastEvent, err := eventBus.NewFastEvent(c.Event, c.Name, nodeID)
logx.Must(err)
ur := user.NewUserManage(zrpc.MustNewClient(c.SysRpc.Conf))
ro := role.NewRoleManage(zrpc.MustNewClient(c.SysRpc.Conf))
tm := tenant.NewTenantManage(zrpc.MustNewClient(c.SysRpc.Conf))
lo := log.NewLog(zrpc.MustNewClient(c.SysRpc.Conf))
//如果需要用到对应的服务,则使用这种方式
checkTokenWare = exportMiddleware.NewCheckTokenWareMiddleware(ur, ro, tm, lo).Handle
//如果不需要用户等rpc,则使用这种方式即可
checkTokenWare = exportMiddleware.NewCheckTokenWareMiddleware2(c.SysRpc).Handle
return &ServiceContext{
Config: c,
InitCtxsWare: ctxs.InitMiddleware,
CheckTokenWare: checkTokenWare,
FastEvent: fastEvent,
DeviceInteract: deviceInteract,
Store: kv.NewStore(c.CacheRedis),
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
# ctxs初始化中间件
无论对应的接口是否需要登录,默认都需要注入这个中间件,这个中间件会初始化ctx,在下面的业务中会使用到
# 定义位置
share/ctxs/ctx.go:121
# 使用方式
ServiceContext定义好后,直接以 InitCtxsWare: ctxs.InitMiddleware
的方式初始化即可
# rpc 中间件
# 使用方式
在rpc初始化的地方调用AddUnaryInterceptors
注入即可
参考代码:
c := svcCtx.Config
s := zrpc.MustNewServer(c.RpcServerConf, func(grpcServer *grpc.Server) {
dm.RegisterProtocolManageServer(grpcServer, protocolmanage.NewProtocolManageServer(svcCtx))
dm.RegisterDeviceManageServer(grpcServer, devicemanage.NewDeviceManageServer(svcCtx))
dm.RegisterProductManageServer(grpcServer, productmanage.NewProductManageServer(svcCtx))
dm.RegisterRemoteConfigServer(grpcServer, remoteconfig.NewRemoteConfigServer(svcCtx))
dm.RegisterDeviceGroupServer(grpcServer, devicegroup.NewDeviceGroupServer(svcCtx))
dm.RegisterDeviceInteractServer(grpcServer, deviceinteract.NewDeviceInteractServer(svcCtx))
dm.RegisterDeviceMsgServer(grpcServer, devicemsg.NewDeviceMsgServer(svcCtx))
dm.RegisterOtaManageServer(grpcServer, otamanage.NewOtaManageServer(svcCtx))
if c.Mode == service.DevMode || c.Mode == service.TestMode {
reflection.Register(grpcServer)
}
})
defer s.Stop()
s.AddUnaryInterceptors(interceptors.Ctxs, interceptors.Error) //将中间件直接加到这里即可
fmt.Printf("Starting rpc server at %s...\n", c.ListenOn)
s.Start()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 上下文转换
在rpc调用中存在一个api调用rpc的时候需要将ctx传给rpc,rpc才可以进行权限的校验及记录,联犀提供了上下文转换中间件来进行自动的转换
# 定义位置
share/interceptors/interceptor.go:34
# 错误处理
- 每次rpc调用的时候会把错误封装成grpc类型的错误,在api中可以使用errors统一进行判断处理,无需额外处理
- 操作错误的时候也会记录日志,方便排查问题
# 定义位置
share/interceptors/interceptor.go:15
上次更新: 2024/10/30, 15:33:51