167 lines
4.5 KiB
Go
167 lines
4.5 KiB
Go
package main
|
||
|
||
import (
|
||
"fmt"
|
||
"log"
|
||
"os"
|
||
|
||
"github.com/gin-gonic/gin"
|
||
"github.com/monitor/backend/config"
|
||
"github.com/monitor/backend/internal/db"
|
||
"github.com/monitor/backend/internal/device"
|
||
"github.com/monitor/backend/internal/handler"
|
||
"github.com/monitor/backend/internal/storage"
|
||
)
|
||
|
||
// 检查配置文件是否存在
|
||
func configFileExists() bool {
|
||
configFile := os.Getenv("SERVER_CONFIG_FILE")
|
||
if configFile == "" {
|
||
configFile = "./config.json"
|
||
}
|
||
_, err := os.Stat(configFile)
|
||
return err == nil
|
||
}
|
||
|
||
// 检查数据库配置是否为默认值
|
||
func isDefaultDBConfig(cfg *config.Config) bool {
|
||
return cfg.DB.Host == "localhost" &&
|
||
cfg.DB.Port == 3306 &&
|
||
cfg.DB.Username == "root" &&
|
||
cfg.DB.Password == "" &&
|
||
cfg.DB.Database == "monitor"
|
||
}
|
||
|
||
// main 函数启动服务器
|
||
func main() {
|
||
// 配置日志:只输出必要的信息,禁用调试日志
|
||
log.SetFlags(log.Ldate | log.Ltime | log.Lshortfile)
|
||
log.SetOutput(os.Stdout)
|
||
|
||
// 加载配置
|
||
cfg, err := config.LoadConfig()
|
||
if err != nil {
|
||
log.Fatalf("Failed to load config: %v", err)
|
||
}
|
||
|
||
// 检查配置文件是否存在
|
||
if !configFileExists() {
|
||
// 生成配置文件
|
||
if err := config.SaveConfig(cfg); err != nil {
|
||
log.Fatalf("Failed to generate config file: %v", err)
|
||
}
|
||
|
||
// 退出并提示用户配置
|
||
fmt.Println("配置文件已生成, 请进行配置然后启动服务.")
|
||
os.Exit(0)
|
||
}
|
||
|
||
// 检查数据库配置是否为默认值
|
||
if isDefaultDBConfig(cfg) {
|
||
// 退出并提示用户配置
|
||
fmt.Println("检测到数据库为默认配置, 请进行配置然后启动服务.")
|
||
os.Exit(0)
|
||
}
|
||
|
||
// 创建存储实例
|
||
store := storage.NewStorage(cfg)
|
||
defer store.Close()
|
||
|
||
// 初始化数据库连接(内部使用,不对外暴露)
|
||
dbConfig := db.Config{
|
||
Type: cfg.DB.Type,
|
||
Host: cfg.DB.Host,
|
||
Port: cfg.DB.Port,
|
||
Username: cfg.DB.Username,
|
||
Password: cfg.DB.Password,
|
||
Database: cfg.DB.Database,
|
||
SSLMode: cfg.DB.SSLMode,
|
||
Charset: cfg.DB.Charset,
|
||
}
|
||
|
||
// 尝试连接数据库,如果连接失败,只记录警告,不影响服务器启动
|
||
database, err := db.NewDB(dbConfig)
|
||
if err != nil {
|
||
log.Printf("Warning: Failed to connect to database: %v", err)
|
||
log.Printf("Server will continue without database connection")
|
||
} else {
|
||
defer database.Close()
|
||
log.Printf("Database connection initialized successfully")
|
||
// 这里可以将database传递给需要使用的组件
|
||
// 例如:handler.SetDB(database)
|
||
}
|
||
|
||
// 创建Gin引擎,禁用调试模式
|
||
gin.SetMode(gin.ReleaseMode)
|
||
r := gin.New()
|
||
// 添加必要的中间件
|
||
r.Use(gin.Recovery())
|
||
// 禁用Gin的默认日志
|
||
r.Use(gin.LoggerWithWriter(gin.DefaultWriter, "/health"))
|
||
|
||
// 设置CORS
|
||
r.Use(func(c *gin.Context) {
|
||
c.Writer.Header().Set("Access-Control-Allow-Origin", "*")
|
||
c.Writer.Header().Set("Access-Control-Allow-Credentials", "true")
|
||
c.Writer.Header().Set("Access-Control-Allow-Headers", "Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token, Authorization, accept, origin, Cache-Control, X-Requested-With")
|
||
c.Writer.Header().Set("Access-Control-Allow-Methods", "POST, OPTIONS, GET, PUT, DELETE")
|
||
|
||
if c.Request.Method == "OPTIONS" {
|
||
c.AbortWithStatus(204)
|
||
return
|
||
}
|
||
|
||
c.Next()
|
||
})
|
||
|
||
// 设置全局存储实例
|
||
handler.SetStorage(store)
|
||
|
||
// 初始化设备存储实例
|
||
var deviceStore device.Storage
|
||
if database != nil {
|
||
// 使用MySQL存储
|
||
mysqlStore, err := device.NewMySQLStorage(database.GetDB())
|
||
if err != nil {
|
||
log.Printf("Warning: Failed to create MySQL device storage: %v", err)
|
||
// 回退到内存存储
|
||
deviceStore = device.NewMemoryStorage()
|
||
} else {
|
||
log.Printf("MySQL device storage initialized successfully")
|
||
deviceStore = mysqlStore
|
||
}
|
||
} else {
|
||
// 使用内存存储
|
||
deviceStore = device.NewMemoryStorage()
|
||
log.Printf("Using in-memory device storage")
|
||
}
|
||
handler.SetDeviceStorage(deviceStore)
|
||
|
||
// 配置静态文件服务
|
||
// 从backend/static目录提供静态文件
|
||
// 先注册API路由,再处理静态文件,避免路由冲突
|
||
|
||
// 注册API路由
|
||
handler.RegisterRoutes(r)
|
||
|
||
// 处理所有未匹配的路由,返回静态文件或index.html
|
||
r.NoRoute(func(c *gin.Context) {
|
||
// 尝试提供静态文件
|
||
file := c.Request.URL.Path
|
||
if file == "/" {
|
||
file = "/index.html"
|
||
}
|
||
|
||
// 从static目录提供文件
|
||
c.File("./static" + file)
|
||
})
|
||
|
||
// 启动服务器
|
||
addr := fmt.Sprintf(":%d", cfg.Server.Port)
|
||
log.Printf("Server starting on %s", addr)
|
||
log.Printf("Static files served from ./static")
|
||
if err := r.Run(addr); err != nil {
|
||
log.Fatalf("Failed to start server: %v", err)
|
||
}
|
||
}
|