golang-yitisheng-server/server/main.go

142 lines
3.6 KiB
Go

// Package main 应用程序入口
package main
import (
"context"
"log"
"net/http"
"os"
"os/signal"
"syscall"
"time"
"server/common"
"server/config"
_ "server/docs"
"server/middleware"
sysController "server/modules/system/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() {
// 初始化日志
common.InitLogger()
common.Info("========== 应用启动 ==========")
// 初始化数据库
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)
// 创建 HTTP 服务器
srv := &http.Server{
Addr: ":8080",
Handler: r,
}
// 启动服务器
go func() {
common.Info("服务器启动: http://localhost:8080")
common.Info("Swagger文档: http://localhost:8080/swagger/index.html")
log.Println("服务器启动: http://localhost:8080")
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)
}
}