1、go接入gin(完成)

2、go接入gorm(完成)
3、环境yaml配置(完成)
4、多库支持(完成)
5、接入日志(完成)
6、接入redis(完成)
7、自定义路由(完成)
8、接入jwt(完成)
This commit is contained in:
TianJun
2021-04-28 15:03:48 +08:00
parent 6b21987033
commit 1a8707eee6
21 changed files with 1400 additions and 0 deletions
+129
View File
@@ -0,0 +1,129 @@
package config
import (
"fmt"
"gopkg.in/yaml.v2"
"io/ioutil"
"os"
"strings"
)
// 配置文件
type AppConfig struct {
// 环境
Env string `yaml:"env"`
// 运行模式
Mode string `yaml:"mode"`
// 应用名称
Name string `yaml:"name"`
}
type ServerConfig struct {
// 服务端口
Port int `yaml:"port"`
}
type LogConfig struct {
// 日志文件配置
File LogFileConfig `yaml:"file"`
// 日志级别(debug, info, warn, error)
Level string `yaml:"level"`
}
type LogFileConfig struct {
// 日志路径
Path string `yaml:"path"`
// 日志名称
Name string `yaml:"name"`
}
type RedisConfig struct {
// 连接地址
Addr string `yaml:"addr"`
// 密码
Passwd string `yaml:"passwd"`
// 库索引
Database int `yaml:"database"`
}
type DataBaseConfig struct {
// 数据库方言
Dialect string `yaml:"dialect"`
// 数据源
DataSources DataSourceConfig `yaml:"datasources"`
}
type DataSourceConfig struct {
MySQL DataSourceMySQLConfig `yaml:"mysql"`
SQLite3 DataSourceSQLite3Config `yaml:"sqlite3"`
}
type DataSourceMySQLConfig struct {
// 连接地址
Addr string `yaml:"addr"`
// 用户名
Username string `yaml:"username"`
// 密码
Password string `yaml:"password"`
// 数据库名称
Database string `yaml:"database"`
}
type DataSourceSQLite3Config struct {
// 数据库文件
DBFile string `yaml:"dbfile"`
}
type JWTConfig struct {
// 加密盐
Secret string `yaml:"secret"`
// 过期时间
Expiry int `yaml:"expiry"`
}
type ApplicationProperties struct {
// 应用配置
App AppConfig `yaml:"app"`
// Gin服务配置
Server ServerConfig `yaml:"server"`
// 日志配置
Log LogConfig `yaml:"log"`
// redis配置
Redis RedisConfig `yaml:"redis"`
// 数据库配置
DataBase DataBaseConfig `yaml:"database"`
// jwt配置
Jwt JWTConfig `yaml:"jwt"`
}
// 根据路径读取yaml文件
func readYaml(path string) ApplicationProperties {
var result ApplicationProperties
data, err := ioutil.ReadFile(path)
if err != nil {
Logger.Error("File reading error, application.yml not exist!" + err.Error())
panic(err)
}
err = yaml.Unmarshal(data, &result)
if err != nil {
Logger.Errorf("cannot unmarshal data: %v", err)
panic(err)
}
return result
}
// 根据环境配置取配置明细
func (v *ApplicationProperties) Init() {
result := readYaml(fmt.Sprintf("%s/application.yml", GetCurrentPath()))
// 判断环境
if strings.Compare(result.App.Env, "dev") == 0 {
AppProps = readYaml(fmt.Sprintf("%s/application-%s.yml", GetCurrentPath(), "dev"))
}
}
// 获取当前路径,比如:d:/abc
func GetCurrentPath() string {
dir, err := os.Getwd()
if err != nil {
Logger.Error(err)
panic(err)
}
return strings.Replace(dir, "\\", "/", -1)
}
+9
View File
@@ -0,0 +1,9 @@
package config
import "github.com/gin-gonic/gin"
// 应用配置
var AppProps ApplicationProperties
// jwt拦截器
var JwtHandle gin.HandlerFunc
+59
View File
@@ -0,0 +1,59 @@
package config
import (
"fmt"
"github.com/jinzhu/gorm"
_ "github.com/jinzhu/gorm/dialects/mssql"
_ "github.com/jinzhu/gorm/dialects/mysql"
_ "github.com/jinzhu/gorm/dialects/postgres"
//_ "github.com/jinzhu/gorm/dialects/sqlite"
"lingye-gin/src/entity"
"strings"
)
var SqlExcutor *gorm.DB
type DataSourcePool struct{}
func (v DataSourcePool) Connect() DataSourcePool {
if strings.Compare(AppProps.DataBase.Dialect, "") == 0 {
panic("yaml file dialect property is nil")
}
var err error
if strings.Compare(AppProps.DataBase.Dialect, "mysql") == 0 {
connectStr := fmt.Sprintf("%s:%s@tcp(%s)/%s?charset=utf8&parseTime=True&loc=Local",
AppProps.DataBase.DataSources.MySQL.Username,
AppProps.DataBase.DataSources.MySQL.Password,
AppProps.DataBase.DataSources.MySQL.Addr,
AppProps.DataBase.DataSources.MySQL.Database)
SqlExcutor, err = gorm.Open(AppProps.DataBase.Dialect, connectStr)
// 创建表时添加表后缀
if SqlExcutor != nil {
SqlExcutor.Set("gorm:table_options", "ENGINE=InnoDB")
}
} else if strings.Compare(AppProps.DataBase.Dialect, "sqlite3") == 0 {
// windows上会报'cgo: exec gcc: exec'异常, 注掉吧
// SqlExcutor, err = gorm.Open(AppProps.DataBase.Dialect, AppProps.DataBase.DataSources.SQLite3.DBFile)
}
if err != nil {
Logger.Error("db connect error: " + err.Error())
panic(err)
}
if SqlExcutor != nil {
// 全局禁用表名复数
// 如果设置为true,`User`的默认表名为`user`,使用`TableName`设置的表名不受影响
SqlExcutor.SingularTable(true)
// 设置为true之后控制台会输出对应的SQL语句
SqlExcutor.LogMode(true)
}
return v
}
// 统一在这里注册数据表
func (DataSourcePool) LoadEntity() {
// 自动迁移模式
if SqlExcutor != nil {
SqlExcutor.AutoMigrate(&entity.User{})
}
}
+118
View File
@@ -0,0 +1,118 @@
package config
import (
"fmt"
"github.com/gin-gonic/gin"
rotatelogs "github.com/lestrrat-go/file-rotatelogs"
"github.com/rifflock/lfshook"
"github.com/sirupsen/logrus"
"os"
"path"
"strings"
"time"
)
// 实例化
var Logger = logrus.New()
// 日志记录到文件
func LoggerToFile() gin.HandlerFunc {
logFilePath := AppProps.Log.File.Path
logFileName := AppProps.Log.File.Name
// 日志文件
fileName := path.Join(logFilePath, logFileName)
//禁止logrus的输出
src, err := os.OpenFile(os.DevNull, os.O_APPEND|os.O_WRONLY, os.ModeAppend)
if err != nil {
panic(fmt.Sprintf("err: %v", err))
}
// 设置输出
Logger.Out = src
// 设置日志级别
if strings.Compare(AppProps.Log.Level, "debug") == 0 {
Logger.SetLevel(logrus.DebugLevel)
} else if strings.Compare(AppProps.Log.Level, "info") == 0 {
Logger.SetLevel(logrus.InfoLevel)
} else if strings.Compare(AppProps.Log.Level, "warn") == 0 {
Logger.SetLevel(logrus.WarnLevel)
} else if strings.Compare(AppProps.Log.Level, "error") == 0 {
Logger.SetLevel(logrus.ErrorLevel)
}
// 设置 rotatelogs
logWriter, err := rotatelogs.New(
// 分割后的文件名称
fileName+".%Y%m%d.log",
// 生成软链,指向最新日志文件
rotatelogs.WithLinkName(fileName),
// 设置最大保存时间(7天)
rotatelogs.WithMaxAge(7*24*time.Hour),
// 设置日志切割时间间隔(1天)
rotatelogs.WithRotationTime(24*time.Hour),
)
writeMap := lfshook.WriterMap{
logrus.InfoLevel: logWriter,
logrus.FatalLevel: logWriter,
logrus.DebugLevel: logWriter,
logrus.WarnLevel: logWriter,
logrus.ErrorLevel: logWriter,
logrus.PanicLevel: logWriter,
}
// 新增钩子
Logger.AddHook(lfshook.NewHook(writeMap, &logrus.JSONFormatter{
// 这个日期是真的牛皮, yyyy-MM-dd hh:mm:ss它不香吗
TimestampFormat: "2006-01-02 15:04:05",
}))
return func(c *gin.Context) {
// 开始时间
startTime := time.Now()
// 处理请求
c.Next()
// 结束时间
endTime := time.Now()
// 执行时间
latencyTime := endTime.Sub(startTime)
// 请求方式
reqMethod := c.Request.Method
// 请求路由
reqUri := c.Request.RequestURI
// 状态码
statusCode := c.Writer.Status()
// 请求IP
clientIP := c.ClientIP()
// 日志格式
Logger.WithFields(logrus.Fields{
"status_code": statusCode,
"latency_time": latencyTime,
"client_ip": clientIP,
"req_method": reqMethod,
"req_uri": reqUri,
}).Info()
}
}
// 日志记录到 MongoDB
func LoggerToMongo() gin.HandlerFunc {
return func(c *gin.Context) {
}
}
// 日志记录到 ES
func LoggerToES() gin.HandlerFunc {
return func(c *gin.Context) {
}
}
// 日志记录到 MQ
func LoggerToMQ() gin.HandlerFunc {
return func(c *gin.Context) {
}
}