/
config.go
345 lines (285 loc) · 9.12 KB
/
config.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
package rest
import (
"encoding/json"
"flag"
"fmt"
"github.com/json-iterator/go"
"io/ioutil"
"time"
"unsafe"
"os"
"strconv"
)
const (
//用户身份的cookie字段名
COOKIE_AUTH_KEY = "_ak"
//数据库表前缀 tank100表示当前应用版本是tank:1.0.x版,数据库结构发生变化必然是中型升级
TABLE_PREFIX = "tank10_"
//当前版本
VERSION = "1.0.5"
)
/*
如果你需要在本地127.0.0.1创建默认的数据库和账号,使用以下语句。
create database tank;
grant all privileges on tank.* to tank identified by 'tank123';
flush privileges;
*/
/*
你也可以在运行时的参数中临时修改一些配置项:
-MysqlHost=127.0.0.1 -MysqlPort=3306 -MysqlSchema=tank -MysqlUsername=tank -MysqlPassword=tank123
*/
var (
CONFIG = &Config{
//以下内容是默认配置项。
//默认监听端口号
ServerPort: 6010,
//将日志输出到控制台。
LogToConsole: true,
//日志的保存路径,如果没有指定,默认在根目录下的log文件夹中
LogPath: "",
//上传的文件路径,如果没有指定,默认在根目录下的matter文件夹中
MatterPath: "",
//mysql相关配置。
//数据库端口
MysqlPort: 3306,
//数据库Host
MysqlHost: "127.0.0.1",
//数据库名字
MysqlSchema: "tank",
//用户名
MysqlUsername: "tank",
//密码
MysqlPassword: "tank123",
//数据库连接信息。这一项是上面几项组合而得,不可直接配置。
MysqlUrl: "%MysqlUsername:%MysqlPassword@tcp(%MysqlHost:%MysqlPort)/%MysqlSchema?charset=utf8&parseTime=True&loc=Local",
//超级管理员用户名,只能包含英文和数字
AdminUsername: "admin",
//超级管理员邮箱
AdminEmail: "admin@tank.eyeblue.cn",
//超级管理员密码
AdminPassword: "123456",
}
)
//依赖外部定义的变量。
type Config struct {
//默认监听端口号
ServerPort int
//将日志输出到控制台。
LogToConsole bool
//日志的保存路径,要求不以/结尾。如果没有指定,默认在根目录下的log文件夹中。eg: /var/log/tank
LogPath string
//上传的文件路径,要求不以/结尾。如果没有指定,默认在根目录下的matter文件夹中。eg: /var/www/matter
MatterPath string
//mysql相关配置。
//数据库端口
MysqlPort int
//数据库Host
MysqlHost string
//数据库名字
MysqlSchema string
//用户名
MysqlUsername string
//密码
MysqlPassword string
//数据库连接信息。
MysqlUrl string
//超级管理员用户名,只能包含英文和数字
AdminUsername string
//超级管理员邮箱
AdminEmail string
//超级管理员密码
AdminPassword string
}
//验证配置文件的正确性。
func (this *Config) validate() {
if this.ServerPort == 0 {
LogPanic("ServerPort 未配置")
}
if this.MysqlUsername == "" {
LogPanic("MysqlUsername 未配置")
}
if this.MysqlPassword == "" {
LogPanic("MysqlPassword 未配置")
}
if this.MysqlHost == "" {
LogPanic("MysqlHost 未配置")
}
if this.MysqlPort == 0 {
LogPanic("MysqlPort 未配置")
}
if this.MysqlSchema == "" {
LogPanic("MysqlSchema 未配置")
}
this.MysqlUrl = fmt.Sprintf("%s:%s@tcp(%s:%d)/%s?charset=utf8&parseTime=True&loc=Local", this.MysqlUsername, this.MysqlPassword, this.MysqlHost, this.MysqlPort, this.MysqlSchema)
}
//init方法只要这个包被引入了就一定会执行。
func init() {
//json中需要去特殊处理时间。
jsoniter.RegisterTypeDecoderFunc("time.Time", func(ptr unsafe.Pointer, iter *jsoniter.Iterator) {
//如果使用time.UTC,那么时间会相差8小时
t, err := time.ParseInLocation("2006-01-02 15:04:05", iter.ReadString(), time.Local)
if err != nil {
iter.Error = err
return
}
*((*time.Time)(ptr)) = t
})
jsoniter.RegisterTypeEncoderFunc("time.Time", func(ptr unsafe.Pointer, stream *jsoniter.Stream) {
t := *((*time.Time)(ptr))
//如果使用time.UTC,那么时间会相差8小时
stream.WriteString(t.Local().Format("2006-01-02 15:04:05"))
}, nil)
}
//第一级. 从配置文件conf/tank.json中读取配置项
func LoadConfigFromFile() {
//读取配置文件
filePath := GetConfPath() + "/tank.json"
content, err := ioutil.ReadFile(filePath)
if err != nil {
LogWarning(fmt.Sprintf("无法找到配置文件:%s,错误:%v\n将使用config.go中的默认配置项。", filePath, err))
} else {
// 用 json.Unmarshal
err := json.Unmarshal(content, CONFIG)
if err != nil {
LogPanic("配置文件格式错误!")
}
}
}
//第二级. 从环境变量中读取配置项
func LoadConfigFromEnvironment() {
tmpServerPort := os.Getenv("TANK_SERVER_PORT")
if tmpServerPort != "" {
i, e := strconv.Atoi(tmpServerPort)
if e == nil {
CONFIG.ServerPort = i
} else {
LogPanic(fmt.Sprintf("环境变量TANK_SERVER_PORT必须为整数!%v", tmpServerPort))
}
}
tmpLogPath := os.Getenv("TANK_LOG_PATH")
if tmpLogPath != "" {
CONFIG.LogPath = tmpLogPath
}
tmpMatterPath := os.Getenv("TANK_MATTER_PATH")
if tmpMatterPath != "" {
CONFIG.MatterPath = tmpMatterPath
}
tmpMysqlPort := os.Getenv("TANK_MYSQL_PORT")
if tmpMysqlPort != "" {
i, e := strconv.Atoi(tmpMysqlPort)
if e == nil {
CONFIG.MysqlPort = i
} else {
LogPanic(fmt.Sprintf("环境变量TANK_MYSQL_PORT必须为整数!%v", tmpMysqlPort))
}
}
tmpMysqlHost := os.Getenv("TANK_MYSQL_HOST")
if tmpMysqlHost != "" {
CONFIG.MysqlHost = tmpMysqlHost
}
tmpMysqlSchema := os.Getenv("TANK_MYSQL_SCHEMA")
if tmpMysqlSchema != "" {
CONFIG.MysqlSchema = tmpMysqlSchema
}
tmpMysqlUsername := os.Getenv("TANK_MYSQL_USERNAME")
if tmpMysqlUsername != "" {
CONFIG.MysqlUsername = tmpMysqlUsername
}
tmpMysqlPassword := os.Getenv("TANK_MYSQL_PASSWORD")
if tmpMysqlPassword != "" {
CONFIG.MysqlPassword = tmpMysqlPassword
}
tmpAdminUsername := os.Getenv("TANK_ADMIN_USERNAME")
if tmpAdminUsername != "" {
CONFIG.AdminUsername = tmpAdminUsername
}
tmpAdminEmail := os.Getenv("TANK_ADMIN_EMAIL")
if tmpAdminEmail != "" {
CONFIG.AdminEmail = tmpAdminEmail
}
tmpAdminPassword := os.Getenv("TANK_ADMIN_PASSWORD")
if tmpAdminPassword != "" {
CONFIG.AdminPassword = tmpAdminPassword
}
}
//第三级. 从程序参数中读取配置项
func LoadConfigFromArguments() {
//从运行时参数中读取,运行时参数具有更高优先级。
//系统端口号
ServerPortPtr := flag.Int("ServerPort", CONFIG.ServerPort, "server port")
//系统端口号
LogToConsolePtr := flag.Bool("LogToConsole", CONFIG.LogToConsole, "write log to console. for debug.")
//日志和上传文件的路径
LogPathPtr := flag.String("LogPath", CONFIG.LogPath, "log path")
MatterPathPtr := flag.String("MatterPath", CONFIG.MatterPath, "matter path")
//mysql相关配置。
MysqlPortPtr := flag.Int("MysqlPort", CONFIG.MysqlPort, "mysql port")
MysqlHostPtr := flag.String("MysqlHost", CONFIG.MysqlHost, "mysql host")
MysqlSchemaPtr := flag.String("MysqlSchema", CONFIG.MysqlSchema, "mysql schema")
MysqlUsernamePtr := flag.String("MysqlUsername", CONFIG.MysqlUsername, "mysql username")
MysqlPasswordPtr := flag.String("MysqlPassword", CONFIG.MysqlPassword, "mysql password")
//超级管理员信息
AdminUsernamePtr := flag.String("AdminUsername", CONFIG.AdminUsername, "administrator username")
AdminEmailPtr := flag.String("AdminEmail", CONFIG.AdminEmail, "administrator email")
AdminPasswordPtr := flag.String("AdminPassword", CONFIG.AdminPassword, "administrator password")
//flag.Parse()方法必须要在使用之前调用。
flag.Parse()
if *ServerPortPtr != CONFIG.ServerPort {
CONFIG.ServerPort = *ServerPortPtr
}
if *LogToConsolePtr != CONFIG.LogToConsole {
CONFIG.LogToConsole = *LogToConsolePtr
}
if *LogPathPtr != CONFIG.LogPath {
CONFIG.LogPath = *LogPathPtr
}
if *MatterPathPtr != CONFIG.MatterPath {
CONFIG.MatterPath = *MatterPathPtr
}
if *MysqlPortPtr != CONFIG.MysqlPort {
CONFIG.MysqlPort = *MysqlPortPtr
}
if *MysqlHostPtr != CONFIG.MysqlHost {
CONFIG.MysqlHost = *MysqlHostPtr
}
if *MysqlSchemaPtr != CONFIG.MysqlSchema {
CONFIG.MysqlSchema = *MysqlSchemaPtr
}
if *MysqlUsernamePtr != CONFIG.MysqlUsername {
CONFIG.MysqlUsername = *MysqlUsernamePtr
}
if *MysqlPasswordPtr != CONFIG.MysqlPassword {
CONFIG.MysqlPassword = *MysqlPasswordPtr
}
if *AdminUsernamePtr != CONFIG.AdminUsername {
CONFIG.AdminUsername = *AdminUsernamePtr
}
if *AdminEmailPtr != CONFIG.AdminEmail {
CONFIG.AdminEmail = *AdminEmailPtr
}
if *AdminPasswordPtr != CONFIG.AdminPassword {
CONFIG.AdminPassword = *AdminPasswordPtr
}
}
//三种方式指定配置项,后面的策略会覆盖前面的策略。
func PrepareConfigs() {
//第一级. 从配置文件conf/tank.json中读取配置项
LoadConfigFromFile()
//第二级. 从环境变量中读取配置项
LoadConfigFromEnvironment()
//第三级. 从程序参数中读取配置项
LoadConfigFromArguments()
//对于日志路径和文件路径还需要进行特殊处理
if CONFIG.LogPath == "" {
CONFIG.LogPath = GetHomePath() + "/log"
}
MakeDirAll(CONFIG.LogPath)
if CONFIG.MatterPath == "" {
CONFIG.MatterPath = GetHomePath() + "/matter"
}
MakeDirAll(CONFIG.MatterPath)
//验证配置项的正确性
CONFIG.validate()
//安装程序开始导入初始表和初始数据。
InstallDatabase()
}