172 lines
4.6 KiB
Go
172 lines
4.6 KiB
Go
// Package main 应用程序入口
|
||
package main
|
||
|
||
import (
|
||
"context"
|
||
"fmt"
|
||
"log"
|
||
"net/http"
|
||
"os"
|
||
"os/signal"
|
||
"syscall"
|
||
"time"
|
||
|
||
"server/common"
|
||
"server/config"
|
||
_ "server/docs"
|
||
"server/middleware"
|
||
sysController "server/modules/system/controller"
|
||
userController "server/modules/user/controller"
|
||
yxController "server/modules/yx/controller"
|
||
|
||
"github.com/gin-gonic/gin"
|
||
swaggerFiles "github.com/swaggo/files"
|
||
ginSwagger "github.com/swaggo/gin-swagger"
|
||
)
|
||
|
||
// @title 艺考招生管理系统 API
|
||
// @version 2.0
|
||
// @description 提供用户认证、院校专业、历年招生、计算专业的管理接口
|
||
// @host localhost:8080
|
||
// @BasePath /api
|
||
// @securityDefinitions.apikey Bearer
|
||
// @in header
|
||
// @name Authorization
|
||
|
||
func main() {
|
||
// 加载配置
|
||
config.LoadConfig()
|
||
|
||
// 初始化日志
|
||
common.InitLogger()
|
||
common.Info("========== 应用启动 ==========")
|
||
|
||
// 初始化雪花算法ID生成器(从配置获取workerID,默认为1)
|
||
workerID := int64(config.AppConfig.Server.WorkerID)
|
||
if workerID <= 0 {
|
||
workerID = 1 // 默认workerID
|
||
}
|
||
datacenterID := int64(config.AppConfig.Server.DatacenterID)
|
||
if datacenterID < 0 {
|
||
datacenterID = 0 // 默认datacenterID
|
||
}
|
||
if err := common.InitGenerator(workerID, datacenterID); err != nil {
|
||
common.LogError("雪花算法初始化失败: %v", err)
|
||
log.Fatalf("雪花算法初始化失败: %v\n", err)
|
||
}
|
||
common.Info("雪花算法ID生成器初始化完成 (WorkerID: %d)", workerID)
|
||
|
||
// 初始化数据库
|
||
config.InitDB()
|
||
common.Info("数据库初始化完成")
|
||
|
||
// 初始化Redis
|
||
config.InitRedis()
|
||
common.Info("Redis初始化完成")
|
||
|
||
// 创建 Gin 引擎
|
||
gin.SetMode(gin.ReleaseMode)
|
||
r := gin.New()
|
||
r.Use(gin.Recovery())
|
||
|
||
// 请求日志中间件
|
||
r.Use(requestLogMiddleware())
|
||
|
||
// 跨域中间件
|
||
r.Use(middleware.CorsMiddleware())
|
||
|
||
// Swagger 文档 (需要Basic Auth验证)
|
||
authorized := r.Group("/swagger", gin.BasicAuth(gin.Accounts{
|
||
config.AppConfig.Swagger.User: config.AppConfig.Swagger.Password,
|
||
}))
|
||
authorized.GET("/*any", ginSwagger.WrapHandler(swaggerFiles.Handler))
|
||
|
||
// API 路由组
|
||
api := r.Group("/api")
|
||
|
||
// 中间件顺序: 安全校验 -> 限流 -> 登录鉴权
|
||
api.Use(middleware.SecurityMiddleware())
|
||
api.Use(middleware.RateLimitMiddleware())
|
||
api.Use(middleware.AuthMiddleware())
|
||
|
||
// 注册 System 模块路由
|
||
sysController.NewAuthController().RegisterRoutes(api)
|
||
sysController.NewSysUserController().RegisterRoutes(api)
|
||
|
||
// 注册 YX 模块路由
|
||
yxController.NewYxSchoolMajorController().RegisterRoutes(api)
|
||
yxController.NewYxHistoryMajorEnrollController().RegisterRoutes(api)
|
||
yxController.NewYxCalculationMajorController().RegisterRoutes(api)
|
||
yxController.NewYxUserScoreController().RegisterRoutes(api)
|
||
yxController.NewYxVolunteerController().RegisterRoutes(api)
|
||
yxController.NewYxVolunteerRecordController().RegisterRoutes(api)
|
||
|
||
// 注册 User 模块路由
|
||
userController.NewUserScoreController().RegisterRoutes(api)
|
||
userController.NewAuthController().RegisterRoutes(api)
|
||
userController.NewUserMajorController().RegisterRoutes(api)
|
||
userController.NewUserVolunteerController().RegisterRoutes(api)
|
||
|
||
// 创建 HTTP 服务器
|
||
port := config.AppConfig.Server.Port
|
||
if port == 0 {
|
||
port = 8080 // 默认端口
|
||
}
|
||
srv := &http.Server{
|
||
Addr: fmt.Sprintf(":%d", port),
|
||
Handler: r,
|
||
}
|
||
|
||
// 启动服务器
|
||
go func() {
|
||
common.Info("服务器启动: http://localhost:%d", port)
|
||
common.Info("Swagger文档: http://localhost:%d/swagger/index.html", port)
|
||
log.Printf("服务器启动: http://localhost:%d\n", port)
|
||
if err := srv.ListenAndServe(); err != nil && err != http.ErrServerClosed {
|
||
common.LogError("启动失败: %s", err)
|
||
log.Fatalf("启动失败: %s\n", err)
|
||
}
|
||
}()
|
||
|
||
// 优雅关闭
|
||
quit := make(chan os.Signal, 1)
|
||
signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)
|
||
<-quit
|
||
|
||
common.Info("正在关闭服务器...")
|
||
log.Println("正在关闭服务器...")
|
||
|
||
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
|
||
defer cancel()
|
||
|
||
if err := srv.Shutdown(ctx); err != nil {
|
||
common.LogError("服务器关闭异常: %v", err)
|
||
log.Fatal("服务器关闭异常:", err)
|
||
}
|
||
|
||
// 关闭资源
|
||
config.CloseDB()
|
||
config.CloseRedis()
|
||
common.Info("========== 应用关闭 ==========")
|
||
common.CloseLogger()
|
||
|
||
log.Println("服务器已退出")
|
||
}
|
||
|
||
// requestLogMiddleware 请求日志中间件
|
||
func requestLogMiddleware() gin.HandlerFunc {
|
||
return func(c *gin.Context) {
|
||
start := time.Now()
|
||
path := c.Request.URL.Path
|
||
method := c.Request.Method
|
||
|
||
c.Next()
|
||
|
||
latency := time.Since(start)
|
||
status := c.Writer.Status()
|
||
clientIP := c.ClientIP()
|
||
|
||
common.Info("%s %s %d %v %s", method, path, status, latency, clientIP)
|
||
}
|
||
}
|