文章目录
前情提要
本节目标
- 优化配置结构(因为配置项越来越多)
- 抽离 原
logging的File便于公用(logging、upload各保有一份并不合适) - 实现上传图片接口(需限制文件格式、大小)
- 修改文章接口(需支持封面地址参数)
- 增加
blog_article(文章)的数据库字段 - 实现
http.FileServer
优化配置结构
讲解
在先前章节中,我们通过读取KEY的方式读取配置项(建立setting模块)
本次需求中,需要增加图片的配置项,总体就有些冗余了
我们采用以下解决方法:
- 映射结构体:使用
MapTo来设置配置参数 - 配置统管:所有的配置项统管到
setting中
落实
修改配置文件
修改 conf/app.ini
增加了 5 个配置项用于上传图片的功能,4 个文件日志方面的配置项
[app]
PageSize = 10
JwtSecret = 233
RuntimeRootPath = runtime/
ImagePrefixUrl = http://127.0.0.1:8000
ImageSavePath = upload/images/
# MB
ImageMaxSize = 5
ImageAllowExts = .jpg,.jpeg,.png
LogSavePath = logs/
LogSaveName = log
LogFileExt = log
TimeFormat = 20060102
[server]
#debug or release
RunMode = debug
HttpPort = 8000
ReadTimeout = 60
WriteTimeout = 60
[database]
Type = mysql
User = root
Password = rootroot
Host = 127.0.0.1:3306
Name = blog
TablePrefix = blog_
优化配置读取及设置初始化顺序
第一步
将散落在其他文件里的配置都删掉,统一在 setting 中处理以及修改 init 函数为 Setup 方法
- 打开 pkg/setting/setting.go 文件,修改如下:
package models
import (
"fmt"
"log"
"time"
"github.com/jinzhu/gorm"
_ "github.com/jinzhu/gorm/dialects/mysql"
"github.com/kingsill/gin-example/pkg/setting"
)
// 定义一个全局的数据库连接变量
var db *gorm.DB
// Model 设定常用结构体,可以作为匿名结构体嵌入到别的表格对应的结构体
type Model struct {
ID int `gorm:"primary_key" json:"id"`
CreatedOn int `json:"created_on"`
ModifiedOn int `json:"modified_on"`
DeletedOn int `json:"deleted_on"`
}
func Setup() {
//配置文件加载
Cfg, err := ini.Load("conf/app.ini")
if err != nil {
log.Fatalf("Fail to parse 'conf/app.ini': %v", err)
}
//将app section 部分映射到AppSetting结构体上
err = Cfg.Section("app").MapTo(AppSetting)
if err != nil {
log.Fatalf("Cfg.MapTo AppSetting err: %v", err)
}
//将图片最大大小设置从5字节Byte转换为5兆字节MB
AppSetting.ImageMaxSize = AppSetting.ImageMaxSize * 1024 * 1024
err = Cfg.Section("server").MapTo(ServerSetting)
if err != nil {
log.Fatalf("Cfg.MapTo ServerSetting err: %v", err)
}
//将读取时自动转换的类型转换为时间间隔了,只不过是最小单位纳秒
ServerSetting.ReadTimeout = ServerSetting.ReadTimeout * time.Second
ServerSetting.WriteTimeout = ServerSetting.WriteTimeout * time.Second
err = Cfg.Section("database").MapTo(DatabaseSetting)
if err != nil {
log.Fatalf("Cfg.MapTo DatabaseSetting err: %v", err)
}
}
在这里,我们做了如下几件事:
- 编写与配置项保持一致的结构体(
App、Server、Database) - 使用 MapTo 将配置项映射到结构体上
- 对一些需特殊设置的配置项进行再赋值
- 修改models.go
将init函数改为Setup方法,将独立读取的DB配置项删除,改为统一读取setting
package models
import (
...
)
// 定义一个全局的数据库连接变量
var db *gorm.DB
// Model 设定常用结构体,可以作为匿名结构体嵌入到别的表格对应的结构体
type Model struct {
ID int `gorm:"primary_key" json:"id"`
CreatedOn int `json:"created_on"`
ModifiedOn int `json:"modified_on"`
DeletedOn int `json:"deleted_on"`
}
func Setup() {
var err error
//使用gorm框架初始化数据库连接
db, err = gorm.Open(setting.DatabaseSetting.Type, fmt.Sprintf("%s:%s@tcp(%s)/%s?charset=utf8&parseTime=True&loc=Local",
setting.DatabaseSetting.User,
setting.DatabaseSetting.Password,
setting.DatabaseSetting.Host,
setting.DatabaseSetting.Name))
if err != nil {
log.Println(err)
}
//自定义默认表的表名,使用匿名函数,在原默认表名的前面加上配置文件中定义的前缀
gorm.DefaultTableNameHandler = func(db *gorm.DB, defaultTableName string) string {
return setting.DatabaseSetting.TablePrefix + defaultTableName
}
//gorm默认使用复数映射,当前设置后即进行严格匹配
db.SingularTable(true)
//log记录打开
db.LogMode(true)
//进行连接池设置
db.DB().SetMaxIdleConns(10)
db.DB().SetMaxOpenConns(100)
//替换Create和Update回调函数
db.Callback().Create().Replace("gorm:update_time_stamp", updateTimeStampForCreateCallback)
db.Callback().Update().Replace("gorm:update_time_stamp", updateTimeStampForUpdateCallback)
//添加删除的回调CallBacks
db.Callback().Delete().Replace("gorm:delete", deleteCallback)
}
// CloseDB 与数据库断开连接函数
func CloseDB() {
defer db.Close()
}
// updateTimeStampForCreateCallback 在创建记录时设置 `CreatedOn`, `ModifiedOn`
func updateTimeStampForCreateCallback(scope *gorm.Scope) {
...
}
// updateTimeStampForUpdateCallback 在更新记录时设置 `ModifyOn`
func updateTimeStampForUpdateCallback(scope *gorm.Scope) {
...
}
// 设定delete操作的callback逻辑
func deleteCallback(scope *gorm.Scope) {
...
}
// 判断是否为空来进行空格插入,防止sql注入,保证安全性
func addExtraSpaceIfExist(str string) string {
...
}
- 修改log.go
init函数改为Setup方法
func Setup() {
//获取log文件目录
filePath := getLogFileFullPath()
//得到log文件句柄
F = openLogFile(filePath)
//创建一个新的日志记录器
logger = log.New(F, DefaultPrefix, log.LstdFlags)
}
-
修改pkg/logging/file.go
独立的
LOG配置项删除,改为统一读取setting,修改这两个函数即可
// 返回log文件的前缀路径,算是一个具有仪式感的函数
func getLogFilePath() string {
return fmt.Sprintf

最低0.47元/天 解锁文章

被折叠的 条评论
为什么被折叠?



