补充ioc
This commit is contained in:
parent
5b25cfefce
commit
c3a407ba0b
@ -318,4 +318,53 @@ curl --location 'http://127.0.0.1:8080/vblog/api/v1/tokens' \
|
||||
|
||||
### 问题
|
||||
|
||||
+ 手动管理: main, 自己组装对象, 业务越复杂,组装难度越高
|
||||
|
||||

|
||||
|
||||
+ ioc: 引入了一个中间层, 这个中间层负责对象的管理, 自己对象自己去ioc获取依赖,而不是我们开发者 把依赖传递给他,完成 对象的 依赖 由被动 变成主动, ioc, 依赖倒置
|
||||
|
||||

|
||||
|
||||
### 基于mcube ioc来改造
|
||||
|
||||

|
||||
|
||||
https://www.mcube.top/docs/framework/
|
||||
|
||||
1. 对象注册到ioc: 把我们的对象实现了1个IOC对象(符合Ioc接口定义的对象), 可以通过继承基础类,直接实现接口ObjectImpl
|
||||
+ 2 APIHandler: TokenApiHandler, BlogApiHandler
|
||||
+ 3 Controller: UserServiceImpl, TokenServiceImpl, BlogServiceImpl
|
||||
|
||||
对象注册
|
||||
```go
|
||||
func init() {
|
||||
ioc.Controller().Registry(&TokenServiceImpl{})
|
||||
}
|
||||
|
||||
// 定义一个struct, 用于实现 UserService就是刚才定义的接口
|
||||
// 怎么才能判断这个结构体没有实现这个接口
|
||||
type TokenServiceImpl struct {
|
||||
ioc.ObjectImpl
|
||||
|
||||
// user service
|
||||
user user.AdminService
|
||||
}
|
||||
|
||||
func (*TokenServiceImpl) Name() string {
|
||||
return token.AppName
|
||||
}
|
||||
|
||||
// 他需要自己去获取依赖,通过ioc
|
||||
func (i *TokenServiceImpl) Init() error {
|
||||
i.user = user.GetService()
|
||||
return nil
|
||||
}
|
||||
```
|
||||
|
||||
对象获取
|
||||
```go
|
||||
func GetService() Service {
|
||||
return ioc.Controller().Get(AppName).(Service)
|
||||
}
|
||||
```
|
7
vblog/apps/registry.go
Normal file
7
vblog/apps/registry.go
Normal file
@ -0,0 +1,7 @@
|
||||
package apps
|
||||
|
||||
import (
|
||||
_ "gitlab.com/go-course-project/go17/vblog/apps/blog/impl"
|
||||
_ "gitlab.com/go-course-project/go17/vblog/apps/token/impl"
|
||||
_ "gitlab.com/go-course-project/go17/vblog/apps/user/impl"
|
||||
)
|
@ -5,29 +5,35 @@ import (
|
||||
"fmt"
|
||||
|
||||
"github.com/infraboard/mcube/v2/exception"
|
||||
"github.com/infraboard/mcube/v2/ioc"
|
||||
"github.com/infraboard/mcube/v2/ioc/config/datasource"
|
||||
"gitlab.com/go-course-project/go17/vblog/apps/token"
|
||||
"gitlab.com/go-course-project/go17/vblog/apps/user"
|
||||
"gitlab.com/go-course-project/go17/vblog/apps/user/impl"
|
||||
)
|
||||
|
||||
var TokenService token.Service = &TokenServiceImpl{
|
||||
user: impl.UserService,
|
||||
}
|
||||
|
||||
func NewTokenService(user user.AdminService) token.Service {
|
||||
return &TokenServiceImpl{
|
||||
user: impl.UserService,
|
||||
}
|
||||
func init() {
|
||||
ioc.Controller().Registry(&TokenServiceImpl{})
|
||||
}
|
||||
|
||||
// 定义一个struct, 用于实现 UserService就是刚才定义的接口
|
||||
// 怎么才能判断这个结构体没有实现这个接口
|
||||
type TokenServiceImpl struct {
|
||||
ioc.ObjectImpl
|
||||
|
||||
// user service
|
||||
user user.AdminService
|
||||
}
|
||||
|
||||
func (*TokenServiceImpl) Name() string {
|
||||
return token.AppName
|
||||
}
|
||||
|
||||
// 他需要自己去获取依赖,通过ioc
|
||||
func (i *TokenServiceImpl) Init() error {
|
||||
i.user = user.GetService()
|
||||
return nil
|
||||
}
|
||||
|
||||
// IssueToken implements token.Service.
|
||||
func (t *TokenServiceImpl) IssueToken(ctx context.Context, in *token.IssueTokenRequest) (*token.Token, error) {
|
||||
if err := in.Validate(); err != nil {
|
||||
|
@ -5,7 +5,6 @@ import (
|
||||
"testing"
|
||||
|
||||
"gitlab.com/go-course-project/go17/vblog/apps/token"
|
||||
"gitlab.com/go-course-project/go17/vblog/apps/token/impl"
|
||||
)
|
||||
|
||||
var (
|
||||
@ -20,7 +19,7 @@ var (
|
||||
// https://gitee.com/infraboard/go-course/blob/master/day09/go-hash.md#bcrypt
|
||||
func TestIssueToken(t *testing.T) {
|
||||
req := token.NewIssueTokenRequest("admin", "123456")
|
||||
ins, err := impl.TokenService.IssueToken(ctx, req)
|
||||
ins, err := token.GetService().IssueToken(ctx, req)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@ -29,7 +28,7 @@ func TestIssueToken(t *testing.T) {
|
||||
|
||||
func TestValidateToken(t *testing.T) {
|
||||
req := token.NewValidateTokenRequest("51bf49f5-12a2-406a-baf8-3f99d985b41a")
|
||||
ins, err := impl.TokenService.ValidateToken(ctx, req)
|
||||
ins, err := token.GetService().ValidateToken(ctx, req)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@ -3,9 +3,18 @@ package token
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/infraboard/mcube/v2/ioc"
|
||||
"github.com/infraboard/mcube/v2/ioc/config/validator"
|
||||
)
|
||||
|
||||
const (
|
||||
AppName = "token"
|
||||
)
|
||||
|
||||
func GetService() Service {
|
||||
return ioc.Controller().Get(AppName).(Service)
|
||||
}
|
||||
|
||||
// 业务域
|
||||
type Service interface {
|
||||
UserService
|
||||
|
@ -3,16 +3,28 @@ package impl
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/infraboard/mcube/v2/ioc"
|
||||
"github.com/infraboard/mcube/v2/ioc/config/datasource"
|
||||
"gitlab.com/go-course-project/go17/vblog/apps/user"
|
||||
"golang.org/x/crypto/bcrypt"
|
||||
)
|
||||
|
||||
var UserService user.Service = &UserServiceImpl{}
|
||||
func init() {
|
||||
ioc.Controller().Registry(&UserServiceImpl{})
|
||||
}
|
||||
|
||||
// int(10) -> (int)(10)
|
||||
var _ user.Service = (*UserServiceImpl)(nil)
|
||||
|
||||
// 定义一个struct, 用于实现 UserService就是刚才定义的接口
|
||||
// 怎么才能判断这个结构体没有实现这个接口
|
||||
type UserServiceImpl struct {
|
||||
// 这个对象 就实现ioc Object接口, 他就能被放到ioc
|
||||
ioc.ObjectImpl
|
||||
}
|
||||
|
||||
func (i *UserServiceImpl) Name() string {
|
||||
return user.AppName
|
||||
}
|
||||
|
||||
// DescribeUser implements user.Service.
|
||||
|
@ -5,7 +5,6 @@ import (
|
||||
"testing"
|
||||
|
||||
"gitlab.com/go-course-project/go17/vblog/apps/user"
|
||||
"gitlab.com/go-course-project/go17/vblog/apps/user/impl"
|
||||
)
|
||||
|
||||
var (
|
||||
@ -22,7 +21,7 @@ func TestRegistry(t *testing.T) {
|
||||
req := user.NewRegistryRequest()
|
||||
req.Username = "test02"
|
||||
req.Password = "123456"
|
||||
ins, err := impl.UserService.Registry(ctx, req)
|
||||
ins, err := user.GetService().Registry(ctx, req)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@ -30,7 +29,7 @@ func TestRegistry(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestDescribeUser(t *testing.T) {
|
||||
ins, err := impl.UserService.DescribeUser(ctx, &user.DescribeUserRequest{
|
||||
ins, err := user.GetService().DescribeUser(ctx, &user.DescribeUserRequest{
|
||||
user.DESCRIBE_BY_USERNAME, "admin",
|
||||
})
|
||||
if err != nil {
|
||||
@ -38,5 +37,5 @@ func TestDescribeUser(t *testing.T) {
|
||||
}
|
||||
//
|
||||
// if ins.Password = in.Password
|
||||
t.Log(ins.CheckPassword("1234567"))
|
||||
t.Log(ins)
|
||||
}
|
||||
|
@ -1,6 +1,19 @@
|
||||
package user
|
||||
|
||||
import "context"
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/infraboard/mcube/v2/ioc"
|
||||
)
|
||||
|
||||
// 获取实现,从ioc
|
||||
func GetService() Service {
|
||||
return ioc.Controller().Get(AppName).(Service)
|
||||
}
|
||||
|
||||
const (
|
||||
AppName = "user"
|
||||
)
|
||||
|
||||
type Service interface {
|
||||
AdminService
|
||||
|
@ -4,6 +4,9 @@ import (
|
||||
"os"
|
||||
|
||||
"github.com/infraboard/mcube/v2/ioc"
|
||||
|
||||
// 导入程序所有的对
|
||||
_ "gitlab.com/go-course-project/go17/vblog/apps"
|
||||
)
|
||||
|
||||
func LoadConfig() {
|
||||
|
66
vblog/docs/ioc.drawio
Normal file
66
vblog/docs/ioc.drawio
Normal file
@ -0,0 +1,66 @@
|
||||
<mxfile host="65bd71144e">
|
||||
<diagram id="QJ9SYQZkHZ_Pkl1wdixx" name="第 1 页">
|
||||
<mxGraphModel dx="947" dy="479" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="827" pageHeight="1169" math="0" shadow="0">
|
||||
<root>
|
||||
<mxCell id="0"/>
|
||||
<mxCell id="1" parent="0"/>
|
||||
<mxCell id="19" style="edgeStyle=none;html=1;exitX=0.5;exitY=0;exitDx=0;exitDy=0;" edge="1" parent="1" source="18">
|
||||
<mxGeometry relative="1" as="geometry">
|
||||
<mxPoint x="423" y="280" as="targetPoint"/>
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="20" value="对象注册" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" vertex="1" connectable="0" parent="19">
|
||||
<mxGeometry x="0.1852" y="-4" relative="1" as="geometry">
|
||||
<mxPoint as="offset"/>
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="18" value="" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
|
||||
<mxGeometry x="30" y="350" width="785" height="130" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="2" value="" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
|
||||
<mxGeometry x="25" y="100" width="785" height="180" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="23" style="edgeStyle=orthogonalEdgeStyle;html=1;exitX=0.5;exitY=0;exitDx=0;exitDy=0;entryX=0.309;entryY=0.991;entryDx=0;entryDy=0;entryPerimeter=0;" edge="1" parent="1" source="4" target="2">
|
||||
<mxGeometry relative="1" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="24" value="get token service Impl" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" vertex="1" connectable="0" parent="23">
|
||||
<mxGeometry x="0.1968" y="-2" relative="1" as="geometry">
|
||||
<mxPoint as="offset"/>
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="4" value="<div style="color: rgb(248, 248, 242); background-color: rgb(39, 40, 34); font-family: &quot;Cascadia Code NF&quot;, Menlo, Monaco, &quot;Courier New&quot;, monospace, Menlo, Monaco, &quot;Courier New&quot;, monospace; line-height: 18px;"><span style="color: rgb(166, 226, 46); text-decoration-line: underline;">TokenApiHandler</span></div>" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
|
||||
<mxGeometry x="207.5" y="380" width="120" height="60" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="8" value="<div style="color: rgb(248, 248, 242); background-color: rgb(39, 40, 34); font-family: &quot;Cascadia Code NF&quot;, Menlo, Monaco, &quot;Courier New&quot;, monospace, Menlo, Monaco, &quot;Courier New&quot;, monospace; line-height: 18px;"><span style="color: rgb(166, 226, 46); text-decoration-line: underline;">BlogApiHandler</span></div>" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
|
||||
<mxGeometry x="517.5" y="380" width="120" height="60" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="25" style="edgeStyle=orthogonalEdgeStyle;html=1;exitX=0.75;exitY=0;exitDx=0;exitDy=0;entryX=0.551;entryY=0.997;entryDx=0;entryDy=0;entryPerimeter=0;" edge="1" parent="1" source="10" target="2">
|
||||
<mxGeometry relative="1" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="26" value="get user service impl" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" vertex="1" connectable="0" parent="25">
|
||||
<mxGeometry x="0.225" y="-1" relative="1" as="geometry">
|
||||
<mxPoint x="51" as="offset"/>
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="10" value="<div style="color: rgb(248, 248, 242); background-color: rgb(39, 40, 34); font-family: &quot;Cascadia Code NF&quot;, Menlo, Monaco, &quot;Courier New&quot;, monospace, Menlo, Monaco, &quot;Courier New&quot;, monospace; line-height: 18px;"><span style="color: rgb(166, 226, 46); text-decoration-line: underline;">TokenServiceImpl</span></div>" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
|
||||
<mxGeometry x="367.5" y="380" width="120" height="60" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="11" value="<div style="color: rgb(248, 248, 242); background-color: rgb(39, 40, 34); font-family: &quot;Cascadia Code NF&quot;, Menlo, Monaco, &quot;Courier New&quot;, monospace, Menlo, Monaco, &quot;Courier New&quot;, monospace; line-height: 18px;"><div style="line-height: 18px;"><span style="color: rgb(166, 226, 46); text-decoration-line: underline;">BlogServiceImpl</span></div></div>" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
|
||||
<mxGeometry x="667.5" y="380" width="120" height="60" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="12" value="<div style="color: rgb(248, 248, 242); background-color: rgb(39, 40, 34); font-family: &quot;Cascadia Code NF&quot;, Menlo, Monaco, &quot;Courier New&quot;, monospace, Menlo, Monaco, &quot;Courier New&quot;, monospace; line-height: 18px;"><span style="color: rgb(166, 226, 46); text-align: left; text-decoration-line: underline;">UserServiceImpl</span><br></div><div style="color: rgb(248, 248, 242); background-color: rgb(39, 40, 34); font-family: &quot;Cascadia Code NF&quot;, Menlo, Monaco, &quot;Courier New&quot;, monospace, Menlo, Monaco, &quot;Courier New&quot;, monospace; line-height: 18px;"><span style="color: rgb(166, 226, 46); text-align: left; text-decoration-line: underline;">name: user</span></div>" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
|
||||
<mxGeometry x="57.5" y="380" width="120" height="60" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="13" value="ioc:&nbsp;&nbsp;<span style="color: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 13px; text-align: start; background-color: rgb(255, 255, 255);">Inversion of Control,缩写为</span><span style="color: rgb(247, 49, 49); font-family: Arial, sans-serif; font-size: 13px; text-align: start; background-color: rgb(255, 255, 255);">IoC</span>" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" vertex="1" parent="1">
|
||||
<mxGeometry x="311.25" y="60" width="232.5" height="30" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="27" value="Text" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" vertex="1" parent="1">
|
||||
<mxGeometry x="400" y="400" width="60" height="30" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="29" value="<h1>对象生命周期</h1><p>1. 对象注册</p><p>2. 对象配置(通过配置文件读取)</p><p>3. 初始化(基础属性, 依然依赖)</p><p><br></p>" style="text;html=1;strokeColor=none;fillColor=none;spacing=5;spacingTop=-20;whiteSpace=wrap;overflow=hidden;rounded=0;" vertex="1" parent="1">
|
||||
<mxGeometry x="30" y="500" width="200" height="230" as="geometry"/>
|
||||
</mxCell>
|
||||
</root>
|
||||
</mxGraphModel>
|
||||
</diagram>
|
||||
</mxfile>
|
BIN
vblog/docs/ioc.png
Normal file
BIN
vblog/docs/ioc.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 34 KiB |
BIN
vblog/docs/oop.png
Normal file
BIN
vblog/docs/oop.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 96 KiB |
BIN
vblog/image.png
Normal file
BIN
vblog/image.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 133 KiB |
@ -5,9 +5,8 @@ import (
|
||||
|
||||
blogApi "gitlab.com/go-course-project/go17/vblog/apps/blog/api"
|
||||
blogImpl "gitlab.com/go-course-project/go17/vblog/apps/blog/impl"
|
||||
"gitlab.com/go-course-project/go17/vblog/apps/token"
|
||||
tokenApi "gitlab.com/go-course-project/go17/vblog/apps/token/api"
|
||||
tokenImpl "gitlab.com/go-course-project/go17/vblog/apps/token/impl"
|
||||
userImpl "gitlab.com/go-course-project/go17/vblog/apps/user/impl"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/infraboard/mcube/v2/ioc/config/http"
|
||||
@ -21,7 +20,7 @@ func main() {
|
||||
server := gin.Default()
|
||||
|
||||
// 注册业务模块的路有
|
||||
tokenApi.NewTokenApiHandler(tokenImpl.NewTokenService(&userImpl.UserServiceImpl{})).Registry(server)
|
||||
tokenApi.NewTokenApiHandler(token.GetService()).Registry(server)
|
||||
blogApi.NewBlogApiHandler(&blogImpl.BlogServiceImpl{}).Registry(server)
|
||||
// ... 50 个API
|
||||
//
|
||||
|
@ -9,8 +9,6 @@ import (
|
||||
"github.com/infraboard/mcube/v2/exception"
|
||||
"github.com/infraboard/mcube/v2/http/gin/response"
|
||||
"gitlab.com/go-course-project/go17/vblog/apps/token"
|
||||
"gitlab.com/go-course-project/go17/vblog/apps/token/impl"
|
||||
userImpl "gitlab.com/go-course-project/go17/vblog/apps/user/impl"
|
||||
)
|
||||
|
||||
// // HandlerFunc defines the handler used by gin middleware as return value.
|
||||
@ -30,7 +28,7 @@ func Auth(c *gin.Context) {
|
||||
accessToken = tkList[1]
|
||||
}
|
||||
// 2. 校验Token
|
||||
tk, err := impl.NewTokenService(&userImpl.UserServiceImpl{}).ValidateToken(c.Request.Context(), token.NewValidateTokenRequest(accessToken))
|
||||
tk, err := token.GetService().ValidateToken(c.Request.Context(), token.NewValidateTokenRequest(accessToken))
|
||||
if err != nil {
|
||||
response.Failed(c, exception.NewUnauthorized("令牌校验失败: %s", err))
|
||||
c.Abort()
|
||||
|
Loading…
x
Reference in New Issue
Block a user