golang-yitisheng-server/server/main.go

172 lines
4.6 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// 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)
}
}