boot.go 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. package boot
  2. import (
  3. "context"
  4. "github.com/dgrijalva/jwt-go"
  5. redisLib "github.com/go-redis/redis/v8"
  6. "github.com/gogf/gf/frame/g"
  7. "github.com/gogf/gf/net/ghttp"
  8. "go.uber.org/dig"
  9. "gorm.io/gorm"
  10. "gxt-api-frame/app/bll/impl"
  11. "gxt-api-frame/app/errors"
  12. "gxt-api-frame/library/auth"
  13. "gxt-api-frame/library/gplus"
  14. "gxt-api-frame/library/logger"
  15. "gxt-api-frame/library/middleware"
  16. "gxt-api-frame/library/redis"
  17. "gxt-api-frame/library/utils"
  18. "gxt-api-frame/router"
  19. "os"
  20. )
  21. // VERSION 定义应用版本号
  22. const VERSION = "1.0.0"
  23. func init() {
  24. // 初始化logger
  25. logger.Init(g.Cfg().GetString("common.run_mode"))
  26. logger.SetVersion(VERSION)
  27. logger.SetTraceIdFunc(utils.NewTraceID)
  28. ctx := logger.NewTraceIDContext(context.Background(), utils.NewTraceID())
  29. Init(ctx)
  30. }
  31. // 初始化App,
  32. // TODO: 返回释放回调,暂时没调用
  33. func Init(ctx context.Context) func() {
  34. logger.Printf(ctx, "服务启动,运行模式:%s,版本号:%s,进程号:%d", g.Cfg().Get("common.run_mode"), VERSION, os.Getpid())
  35. // 初始化依赖注入容器
  36. container, call := buildContainer(ctx)
  37. // 初始化路由注册
  38. s := g.Server()
  39. // 每个请求生成新的追踪Id,如果上下文件中没有trace-id
  40. s.Use(middleware.TraceIdMiddleware())
  41. if g.Cfg().GetBool("prometheus.enable") {
  42. p := middleware.NewPrometheus("ghttp")
  43. p.Use(s)
  44. }
  45. // 统一处理内部错误
  46. s.Use(func(r *ghttp.Request) {
  47. r.Middleware.Next()
  48. if err := r.GetError(); err != nil {
  49. gplus.ResError(r, err)
  50. }
  51. })
  52. _ = initJwtAuth(ctx, container)
  53. router.InitRouters(s, container)
  54. return func() {
  55. if call != nil {
  56. call()
  57. }
  58. }
  59. }
  60. // 初始化jwt认证,可以把相关配置放到config.toml中
  61. func initJwtAuth(ctx context.Context, container *dig.Container) error {
  62. var opts []auth.Option
  63. opts = append(opts, auth.SetExpired(g.Cfg().GetInt("jwt.expired")))
  64. opts = append(opts, auth.SetSigningKey([]byte(g.Cfg().GetString("jwt.signing_key"))))
  65. opts = append(opts, auth.SetKeyfunc(func(t *jwt.Token) (interface{}, error) {
  66. if _, ok := t.Method.(*jwt.SigningMethodHMAC); !ok {
  67. return nil, errors.ErrInvalidToken
  68. }
  69. return []byte(g.Cfg().GetString("jwt.signing_key")), nil
  70. }))
  71. switch g.Cfg().GetString("jwt.signing_method") {
  72. case "HS256":
  73. opts = append(opts, auth.SetSigningMethod(jwt.SigningMethodHS256))
  74. case "HS384":
  75. opts = append(opts, auth.SetSigningMethod(jwt.SigningMethodHS384))
  76. case "HS512":
  77. opts = append(opts, auth.SetSigningMethod(jwt.SigningMethodHS512))
  78. }
  79. return container.Provide(func() auth.Auther { return auth.New(opts...) })
  80. }
  81. // 初始化redis
  82. func initRedis(ctx context.Context, container *dig.Container) func() {
  83. addr := g.Cfg().GetString("redis.addr")
  84. password := g.Cfg().GetString("redis.password")
  85. db := g.Cfg().GetInt("redis.db")
  86. redisCli := redis.Init(ctx, addr, password, db)
  87. logger.Printf(ctx, "REDIS初始化成功,当前服务器[%s]", addr)
  88. // 注入redis client
  89. _ = container.Provide(func() *redisLib.Client {
  90. return redisCli
  91. })
  92. return func() {
  93. _ = redisCli.Close()
  94. }
  95. }
  96. // 初始化存储,目前只初始化gorm
  97. func initStore(ctx context.Context, container *dig.Container) (func(), error) {
  98. var storeCall func()
  99. db, err := initGorm()
  100. if err != nil {
  101. return storeCall, err
  102. }
  103. // 如果自动映射数据表
  104. if g.Cfg().GetBool("gorm.enable_auto_migrate") {
  105. err = autoMigrate(db)
  106. if err != nil {
  107. return storeCall, err
  108. }
  109. }
  110. // 注入DB
  111. _ = container.Provide(func() *gorm.DB { return db })
  112. // 注入model接口
  113. _ = InjectModel(container)
  114. storeCall = func() {
  115. sqlDb, _ := db.DB()
  116. _ = sqlDb.Close()
  117. }
  118. logger.Printf(ctx, "MYSQL初始化成功, 服务器[%s], 数据库[%s]",
  119. g.Cfg().GetString("mysql.host"),
  120. g.Cfg().GetString("mysql.db_name"))
  121. return storeCall, nil
  122. }
  123. // 构建依赖注入容器
  124. func buildContainer(ctx context.Context) (*dig.Container, func()) {
  125. container := dig.New()
  126. // 初始化存储模块
  127. storeCall, err := initStore(ctx, container)
  128. if err != nil {
  129. panic(err)
  130. }
  131. // 初始化redis模块
  132. var redisCall func()
  133. if g.Cfg().GetBool("redis.enable") {
  134. redisCall = initRedis(ctx, container)
  135. }
  136. // 注入bll
  137. impl.Inject(container)
  138. return container, func() {
  139. if storeCall != nil {
  140. storeCall()
  141. }
  142. if redisCall != nil {
  143. redisCall()
  144. }
  145. }
  146. }