Finish all the i18n things of code.
This commit is contained in:
@ -17,39 +17,37 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
//启动web服务,默认是这种方式
|
||||
//start web. This is the default mode.
|
||||
MODE_WEB = "web"
|
||||
//映射本地文件到云盘中
|
||||
//mirror local files to EyeblueTank.
|
||||
MODE_MIRROR = "mirror"
|
||||
//将远程的一个文件爬取到蓝眼云盘中
|
||||
//crawl remote file to EyeblueTank
|
||||
MODE_CRAWL = "crawl"
|
||||
//TODO: 查看当前蓝眼云盘版本
|
||||
//Current version.
|
||||
MODE_VERSION = "version"
|
||||
)
|
||||
|
||||
//命令行输入相关的对象
|
||||
type TankApplication struct {
|
||||
//模式
|
||||
//mode
|
||||
mode string
|
||||
|
||||
//蓝眼云盘的主机,需要带上协议和端口号。默认: http://127.0.0.1:core.DEFAULT_SERVER_PORT
|
||||
//EyeblueTank host and port default: http://127.0.0.1:core.DEFAULT_SERVER_PORT
|
||||
host string
|
||||
//用户名
|
||||
//username
|
||||
username string
|
||||
//密码
|
||||
//password
|
||||
password string
|
||||
|
||||
//源文件/文件夹,本地绝对路径/远程资源url
|
||||
//source file/directory different mode has different usage.
|
||||
src string
|
||||
//目标(表示的是文件夹)路径,蓝眼云盘中的路径。相对于root的路径。
|
||||
//destination directory path(relative to root) in EyeblueTank
|
||||
dest string
|
||||
//同名文件或文件夹是否直接替换 true 全部替换; false 跳过
|
||||
//true: overwrite, false:skip
|
||||
overwrite bool
|
||||
//拉取文件存储的名称
|
||||
filename string
|
||||
filename string
|
||||
}
|
||||
|
||||
//启动应用。可能是web形式,也可能是命令行工具。
|
||||
//Start the application.
|
||||
func (this *TankApplication) Start() {
|
||||
|
||||
defer func() {
|
||||
@ -58,7 +56,6 @@ func (this *TankApplication) Start() {
|
||||
}
|
||||
}()
|
||||
|
||||
//超级管理员信息
|
||||
modePtr := flag.String("mode", this.mode, "cli mode web/mirror/crawl")
|
||||
hostPtr := flag.String("host", this.username, "tank host")
|
||||
usernamePtr := flag.String("username", this.username, "username")
|
||||
@ -68,7 +65,7 @@ func (this *TankApplication) Start() {
|
||||
overwritePtr := flag.Bool("overwrite", this.overwrite, "whether same file overwrite")
|
||||
filenamePtr := flag.String("filename", this.filename, "filename when crawl")
|
||||
|
||||
//flag.Parse()方法必须要在使用之前调用。
|
||||
//flag.Parse() must invoke before use.
|
||||
flag.Parse()
|
||||
|
||||
this.mode = *modePtr
|
||||
@ -80,36 +77,30 @@ func (this *TankApplication) Start() {
|
||||
this.overwrite = *overwritePtr
|
||||
this.filename = *filenamePtr
|
||||
|
||||
//默认采用web的形式启动
|
||||
//default start as web.
|
||||
if this.mode == "" || strings.ToLower(this.mode) == MODE_WEB {
|
||||
|
||||
//直接web启动
|
||||
this.HandleWeb()
|
||||
|
||||
} else if strings.ToLower(this.mode) == MODE_VERSION {
|
||||
|
||||
//直接web启动
|
||||
this.HandleVersion()
|
||||
|
||||
} else {
|
||||
|
||||
//准备蓝眼云盘地址
|
||||
//default host.
|
||||
if this.host == "" {
|
||||
this.host = fmt.Sprintf("http://127.0.0.1:%d", core.DEFAULT_SERVER_PORT)
|
||||
}
|
||||
|
||||
//准备用户名
|
||||
if this.username == "" {
|
||||
panic(result.BadRequest("%s模式下,用户名必填", this.mode))
|
||||
panic(result.BadRequest("in mode %s, username is required", this.mode))
|
||||
}
|
||||
|
||||
//准备密码
|
||||
if this.password == "" {
|
||||
|
||||
if util.EnvDevelopment() {
|
||||
|
||||
panic(result.BadRequest("IDE中请运行请直接使用 -password yourPassword 的形式输入密码"))
|
||||
|
||||
panic(result.BadRequest("If run in IDE, use -password yourPassword to input password"))
|
||||
} else {
|
||||
|
||||
fmt.Print("Enter Password:")
|
||||
@ -125,42 +116,39 @@ func (this *TankApplication) Start() {
|
||||
|
||||
if strings.ToLower(this.mode) == MODE_MIRROR {
|
||||
|
||||
//映射本地文件到蓝眼云盘
|
||||
this.HandleMirror()
|
||||
|
||||
} else if strings.ToLower(this.mode) == MODE_CRAWL {
|
||||
|
||||
//将远程文件拉取到蓝眼云盘中
|
||||
this.HandleCrawl()
|
||||
|
||||
} else {
|
||||
panic(result.BadRequest("不能处理命名行模式: %s \r\n", this.mode))
|
||||
panic(result.BadRequest("cannot handle mode %s \r\n", this.mode))
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//采用Web的方式启动应用
|
||||
func (this *TankApplication) HandleWeb() {
|
||||
|
||||
//第1步。日志
|
||||
//Step 1. Logger
|
||||
tankLogger := &TankLogger{}
|
||||
core.LOGGER = tankLogger
|
||||
tankLogger.Init()
|
||||
defer tankLogger.Destroy()
|
||||
|
||||
//第2步。配置
|
||||
//Step 2. Configuration
|
||||
tankConfig := &TankConfig{}
|
||||
core.CONFIG = tankConfig
|
||||
tankConfig.Init()
|
||||
|
||||
//第3步。全局运行的上下文
|
||||
//Step 3. Global Context
|
||||
tankContext := &TankContext{}
|
||||
core.CONTEXT = tankContext
|
||||
tankContext.Init()
|
||||
defer tankContext.Destroy()
|
||||
|
||||
//第4步。启动http服务
|
||||
//Step 4. Start http
|
||||
http.Handle("/", core.CONTEXT)
|
||||
core.LOGGER.Info("App started at http://localhost:%v", core.CONFIG.ServerPort())
|
||||
|
||||
@ -172,17 +160,16 @@ func (this *TankApplication) HandleWeb() {
|
||||
|
||||
}
|
||||
|
||||
//处理本地映射的情形
|
||||
func (this *TankApplication) HandleMirror() {
|
||||
|
||||
if this.src == "" {
|
||||
panic("src 必填")
|
||||
panic("src is required")
|
||||
}
|
||||
if this.dest == "" {
|
||||
panic("dest 必填")
|
||||
panic("dest is required")
|
||||
}
|
||||
|
||||
fmt.Printf("开始映射本地文件 %s 到蓝眼云盘 %s\r\n", this.src, this.dest)
|
||||
fmt.Printf("start mirror %s to EyeblueTank %s\r\n", this.src, this.dest)
|
||||
|
||||
urlString := fmt.Sprintf("%s/api/matter/mirror", this.host)
|
||||
|
||||
@ -203,7 +190,7 @@ func (this *TankApplication) HandleMirror() {
|
||||
|
||||
err = jsoniter.ConfigCompatibleWithStandardLibrary.Unmarshal(bodyBytes, webResult)
|
||||
if err != nil {
|
||||
fmt.Printf("返回格式错误!%s \r\n", err.Error())
|
||||
fmt.Printf("error response format %s \r\n", err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
@ -215,21 +202,20 @@ func (this *TankApplication) HandleMirror() {
|
||||
|
||||
}
|
||||
|
||||
//拉取远程文件到本地。
|
||||
func (this *TankApplication) HandleCrawl() {
|
||||
|
||||
if this.src == "" {
|
||||
panic("src 必填")
|
||||
panic("src is required")
|
||||
}
|
||||
if this.dest == "" {
|
||||
panic("dest 必填")
|
||||
panic("dest is required")
|
||||
}
|
||||
|
||||
if this.filename == "" {
|
||||
panic("filename 必填")
|
||||
panic("filename is required")
|
||||
}
|
||||
|
||||
fmt.Printf("开始映射拉取远程文件 %s 到蓝眼云盘 %s\r\n", this.src, this.dest)
|
||||
fmt.Printf("crawl %s to EyeblueTank %s\r\n", this.src, this.dest)
|
||||
|
||||
urlString := fmt.Sprintf("%s/api/matter/crawl", this.host)
|
||||
|
||||
@ -250,7 +236,7 @@ func (this *TankApplication) HandleCrawl() {
|
||||
|
||||
err = jsoniter.ConfigCompatibleWithStandardLibrary.Unmarshal(bodyBytes, webResult)
|
||||
if err != nil {
|
||||
fmt.Printf("返回格式错误!%s \r\n", err.Error())
|
||||
fmt.Printf("Error response format %s \r\n", err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -10,76 +10,68 @@ import (
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
/*
|
||||
如果你需要在本地127.0.0.1创建默认的数据库和账号,使用以下语句。
|
||||
create database tank;
|
||||
grant all privileges on tank.* to tank identified by 'tank123';
|
||||
flush privileges;
|
||||
*/
|
||||
|
||||
//依赖外部定义的变量。
|
||||
type TankConfig struct {
|
||||
//默认监听端口号
|
||||
//server port
|
||||
serverPort int
|
||||
//网站是否已经完成安装
|
||||
//whether installed
|
||||
installed bool
|
||||
//上传的文件路径,要求不以/结尾。如果没有指定,默认在根目录下的matter文件夹中。eg: /var/www/matter
|
||||
//file storage location. eg./var/www/matter
|
||||
matterPath string
|
||||
//数据库连接信息。
|
||||
//mysql url.
|
||||
mysqlUrl string
|
||||
//配置文件中的项
|
||||
//configs in tank.json
|
||||
item *ConfigItem
|
||||
}
|
||||
|
||||
//和tank.json文件中的键值一一对应。
|
||||
//tank.json config items.
|
||||
type ConfigItem struct {
|
||||
//默认监听端口号
|
||||
//server port
|
||||
ServerPort int
|
||||
//上传的文件路径,要求不以/结尾。如果没有指定,默认在根目录下的matter文件夹中。eg: /var/www/matter
|
||||
//file storage location. eg./var/www/matter
|
||||
MatterPath string
|
||||
//mysql相关配置。
|
||||
//数据库端口
|
||||
//mysql configurations.
|
||||
//mysql port
|
||||
MysqlPort int
|
||||
//数据库Host
|
||||
//mysql host
|
||||
MysqlHost string
|
||||
//数据库名字
|
||||
//mysql schema
|
||||
MysqlSchema string
|
||||
//用户名
|
||||
//mysql username
|
||||
MysqlUsername string
|
||||
//密码
|
||||
//mysql password
|
||||
MysqlPassword string
|
||||
}
|
||||
|
||||
//验证配置文件的正确性。
|
||||
//validate whether the config file is ok
|
||||
func (this *ConfigItem) validate() bool {
|
||||
|
||||
if this.ServerPort == 0 {
|
||||
core.LOGGER.Error("ServerPort 未配置")
|
||||
core.LOGGER.Error("ServerPort is not configured")
|
||||
return false
|
||||
}
|
||||
|
||||
if this.MysqlUsername == "" {
|
||||
core.LOGGER.Error("MysqlUsername 未配置")
|
||||
core.LOGGER.Error("MysqlUsername is not configured")
|
||||
return false
|
||||
}
|
||||
|
||||
if this.MysqlPassword == "" {
|
||||
core.LOGGER.Error("MysqlPassword 未配置")
|
||||
core.LOGGER.Error("MysqlPassword is not configured")
|
||||
return false
|
||||
}
|
||||
|
||||
if this.MysqlHost == "" {
|
||||
core.LOGGER.Error("MysqlHost 未配置")
|
||||
core.LOGGER.Error("MysqlHost is not configured")
|
||||
return false
|
||||
}
|
||||
|
||||
if this.MysqlPort == 0 {
|
||||
core.LOGGER.Error("MysqlPort 未配置")
|
||||
core.LOGGER.Error("MysqlPort is not configured")
|
||||
return false
|
||||
}
|
||||
|
||||
if this.MysqlSchema == "" {
|
||||
core.LOGGER.Error("MysqlSchema 未配置")
|
||||
core.LOGGER.Error("MysqlSchema is not configured")
|
||||
return false
|
||||
}
|
||||
|
||||
@ -87,12 +79,11 @@ func (this *ConfigItem) validate() bool {
|
||||
|
||||
}
|
||||
|
||||
//验证配置文件是否完好
|
||||
func (this *TankConfig) Init() {
|
||||
|
||||
//JSON初始化
|
||||
//JSON init.
|
||||
jsoniter.RegisterTypeDecoderFunc("time.Time", func(ptr unsafe.Pointer, iter *jsoniter.Iterator) {
|
||||
//如果使用time.UTC,那么时间会相差8小时
|
||||
//if use time.UTC there will be 8 hours gap.
|
||||
t, err := time.ParseInLocation("2006-01-02 15:04:05", iter.ReadString(), time.Local)
|
||||
if err != nil {
|
||||
iter.Error = err
|
||||
@ -103,45 +94,44 @@ func (this *TankConfig) Init() {
|
||||
|
||||
jsoniter.RegisterTypeEncoderFunc("time.Time", func(ptr unsafe.Pointer, stream *jsoniter.Stream) {
|
||||
t := *((*time.Time)(ptr))
|
||||
//如果使用time.UTC,那么时间会相差8小时
|
||||
//if use time.UTC there will be 8 hours gap.
|
||||
stream.WriteString(t.Local().Format("2006-01-02 15:04:05"))
|
||||
}, nil)
|
||||
|
||||
//默认从core.DEFAULT_SERVER_PORT端口启动
|
||||
//default server port.
|
||||
this.serverPort = core.DEFAULT_SERVER_PORT
|
||||
|
||||
this.ReadFromConfigFile()
|
||||
|
||||
}
|
||||
|
||||
//系统如果安装好了就调用这个方法。
|
||||
func (this *TankConfig) ReadFromConfigFile() {
|
||||
|
||||
//读取配置文件
|
||||
//read from tank.json
|
||||
filePath := util.GetConfPath() + "/tank.json"
|
||||
content, err := ioutil.ReadFile(filePath)
|
||||
if err != nil {
|
||||
core.LOGGER.Warn("无法找到配置文件:%s 即将进入安装过程!", filePath)
|
||||
core.LOGGER.Warn("cannot find config file %s, installation will start!", filePath)
|
||||
this.installed = false
|
||||
} else {
|
||||
this.item = &ConfigItem{}
|
||||
core.LOGGER.Warn("读取配置文件:%s", filePath)
|
||||
core.LOGGER.Warn("read config file %s", filePath)
|
||||
err := jsoniter.ConfigCompatibleWithStandardLibrary.Unmarshal(content, this.item)
|
||||
if err != nil {
|
||||
core.LOGGER.Error("配置文件格式错误! 即将进入安装过程!")
|
||||
core.LOGGER.Error("config file error, installation will start!")
|
||||
this.installed = false
|
||||
return
|
||||
}
|
||||
|
||||
//验证项是否齐全
|
||||
//check the integrity
|
||||
itemValidate := this.item.validate()
|
||||
if !itemValidate {
|
||||
core.LOGGER.Error("配置文件信息不齐全! 即将进入安装过程!")
|
||||
core.LOGGER.Error("config file not integrity, installation will start!")
|
||||
this.installed = false
|
||||
return
|
||||
}
|
||||
|
||||
//使用配置项中的文件路径
|
||||
//use default file location.
|
||||
if this.item.MatterPath == "" {
|
||||
this.matterPath = util.GetHomePath() + "/matter"
|
||||
} else {
|
||||
@ -149,7 +139,7 @@ func (this *TankConfig) ReadFromConfigFile() {
|
||||
}
|
||||
util.MakeDirAll(this.matterPath)
|
||||
|
||||
//使用配置项中的端口
|
||||
//use default server port
|
||||
if this.item.ServerPort != 0 {
|
||||
this.serverPort = this.item.ServerPort
|
||||
}
|
||||
@ -157,57 +147,50 @@ func (this *TankConfig) ReadFromConfigFile() {
|
||||
this.mysqlUrl = util.GetMysqlUrl(this.item.MysqlPort, this.item.MysqlHost, this.item.MysqlSchema, this.item.MysqlUsername, this.item.MysqlPassword)
|
||||
this.installed = true
|
||||
|
||||
core.LOGGER.Info("使用配置文件:%s", filePath)
|
||||
core.LOGGER.Info("上传文件存放路径:%s", this.matterPath)
|
||||
core.LOGGER.Info("use config file: %s", filePath)
|
||||
core.LOGGER.Info("file storage location: %s", this.matterPath)
|
||||
}
|
||||
}
|
||||
|
||||
//是否已经安装
|
||||
//whether installed.
|
||||
func (this *TankConfig) Installed() bool {
|
||||
return this.installed
|
||||
}
|
||||
|
||||
//启动端口
|
||||
//server port
|
||||
func (this *TankConfig) ServerPort() int {
|
||||
return this.serverPort
|
||||
}
|
||||
|
||||
//获取mysql链接
|
||||
//mysql url
|
||||
func (this *TankConfig) MysqlUrl() string {
|
||||
return this.mysqlUrl
|
||||
}
|
||||
|
||||
//文件存放路径
|
||||
//matter path
|
||||
func (this *TankConfig) MatterPath() string {
|
||||
|
||||
return this.matterPath
|
||||
}
|
||||
|
||||
//完成安装过程,主要是要将配置写入到文件中
|
||||
//Finish the installation. Write config to tank.json
|
||||
func (this *TankConfig) FinishInstall(mysqlPort int, mysqlHost string, mysqlSchema string, mysqlUsername string, mysqlPassword string) {
|
||||
|
||||
var configItem = &ConfigItem{
|
||||
//默认监听端口号
|
||||
//server port
|
||||
ServerPort: core.CONFIG.ServerPort(),
|
||||
//上传的文件路径,要求不以/结尾。如果没有指定,默认在根目录下的matter文件夹中。eg: /var/www/matter
|
||||
MatterPath: core.CONFIG.MatterPath(),
|
||||
//mysql相关配置。
|
||||
//数据库端口
|
||||
MysqlPort: mysqlPort,
|
||||
//数据库Host
|
||||
MysqlHost: mysqlHost,
|
||||
//数据库名字
|
||||
MysqlSchema: mysqlSchema,
|
||||
//用户名
|
||||
//file storage location. eg./var/www/matter
|
||||
MatterPath: core.CONFIG.MatterPath(),
|
||||
MysqlPort: mysqlPort,
|
||||
MysqlHost: mysqlHost,
|
||||
MysqlSchema: mysqlSchema,
|
||||
MysqlUsername: mysqlUsername,
|
||||
//密码
|
||||
MysqlPassword: mysqlPassword,
|
||||
}
|
||||
|
||||
//用json的方式输出返回值。为了让格式更好看。
|
||||
//pretty json.
|
||||
jsonStr, _ := jsoniter.ConfigCompatibleWithStandardLibrary.MarshalIndent(configItem, "", " ")
|
||||
|
||||
//写入到配置文件中(不能使用os.O_APPEND 否则会追加)
|
||||
//Write to tank.json (cannot use os.O_APPEND or append)
|
||||
filePath := util.GetConfPath() + "/tank.json"
|
||||
f, err := os.OpenFile(filePath, os.O_RDWR|os.O_CREATE, 0777)
|
||||
core.PanicError(err)
|
||||
|
@ -1,8 +1,6 @@
|
||||
package support
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/eyebluecn/tank/code/core"
|
||||
"github.com/eyebluecn/tank/code/rest"
|
||||
"github.com/eyebluecn/tank/code/tool/cache"
|
||||
@ -11,45 +9,42 @@ import (
|
||||
"reflect"
|
||||
)
|
||||
|
||||
//上下文,管理数据库连接,管理所有路由请求,管理所有的单例component.
|
||||
type TankContext struct {
|
||||
//数据库连接
|
||||
//db connection
|
||||
db *gorm.DB
|
||||
//session缓存
|
||||
//session cache
|
||||
SessionCache *cache.Table
|
||||
//各类的Bean Map。这里面是包含ControllerMap中所有元素
|
||||
//bean map.
|
||||
BeanMap map[string]core.Bean
|
||||
//只包含了Controller的map
|
||||
//controller map
|
||||
ControllerMap map[string]core.Controller
|
||||
//处理所有路由请求
|
||||
//router
|
||||
Router *TankRouter
|
||||
}
|
||||
|
||||
//初始化上下文
|
||||
func (this *TankContext) Init() {
|
||||
|
||||
//创建一个用于存储session的缓存。
|
||||
//create session cache
|
||||
this.SessionCache = cache.NewTable()
|
||||
|
||||
//初始化Map
|
||||
//init map
|
||||
this.BeanMap = make(map[string]core.Bean)
|
||||
this.ControllerMap = make(map[string]core.Controller)
|
||||
|
||||
//注册各类Beans.在这个方法里面顺便把Controller装入ControllerMap中去。
|
||||
//register beans. This method will put Controllers to ControllerMap.
|
||||
this.registerBeans()
|
||||
|
||||
//初始化每个bean.
|
||||
//init every bean.
|
||||
this.initBeans()
|
||||
|
||||
//初始化Router. 这个方法要在Bean注册好了之后才能。
|
||||
//create and init router.
|
||||
this.Router = NewRouter()
|
||||
|
||||
//如果数据库信息配置好了,就直接打开数据库连接 同时执行Bean的ConfigPost方法
|
||||
//if the application is installed. Bean's Bootstrap method will be invoked.
|
||||
this.InstallOk()
|
||||
|
||||
}
|
||||
|
||||
//获取数据库对象
|
||||
func (this *TankContext) GetDB() *gorm.DB {
|
||||
return this.db
|
||||
}
|
||||
@ -68,7 +63,7 @@ func (this *TankContext) Cleanup() {
|
||||
}
|
||||
}
|
||||
|
||||
//响应http的能力
|
||||
//can serve as http server.
|
||||
func (this *TankContext) ServeHTTP(writer http.ResponseWriter, request *http.Request) {
|
||||
this.Router.ServeHTTP(writer, request)
|
||||
}
|
||||
@ -82,7 +77,7 @@ func (this *TankContext) OpenDb() {
|
||||
core.LOGGER.Panic("failed to connect mysql database")
|
||||
}
|
||||
|
||||
//是否打开sql日志(在调试阶段可以打开,以方便查看执行的SQL)
|
||||
//whether open the db log. (only true when debug)
|
||||
this.db.LogMode(false)
|
||||
}
|
||||
|
||||
@ -91,12 +86,11 @@ func (this *TankContext) CloseDb() {
|
||||
if this.db != nil {
|
||||
err := this.db.Close()
|
||||
if err != nil {
|
||||
core.LOGGER.Error("关闭数据库连接出错 %s", err.Error())
|
||||
core.LOGGER.Error("occur error when closing db %s", err.Error())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//注册一个Bean
|
||||
func (this *TankContext) registerBean(bean core.Bean) {
|
||||
|
||||
typeOf := reflect.TypeOf(bean)
|
||||
@ -104,13 +98,12 @@ func (this *TankContext) registerBean(bean core.Bean) {
|
||||
|
||||
if element, ok := bean.(core.Bean); ok {
|
||||
|
||||
err := fmt.Sprintf("【%s】已经被注册了,跳过。", typeName)
|
||||
if _, ok := this.BeanMap[typeName]; ok {
|
||||
core.LOGGER.Error(fmt.Sprintf(err))
|
||||
core.LOGGER.Error("%s has been registerd, skip", typeName)
|
||||
} else {
|
||||
this.BeanMap[typeName] = element
|
||||
|
||||
//看看是不是controller类型,如果是,那么单独放在ControllerMap中。
|
||||
//if is controller type, put into ControllerMap
|
||||
if controller, ok1 := bean.(core.Controller); ok1 {
|
||||
this.ControllerMap[typeName] = controller
|
||||
}
|
||||
@ -118,12 +111,11 @@ func (this *TankContext) registerBean(bean core.Bean) {
|
||||
}
|
||||
|
||||
} else {
|
||||
core.LOGGER.Panic("注册的【%s】不是Bean类型。", typeName)
|
||||
core.LOGGER.Panic("%s is not the Bean type", typeName)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//注册各个Beans
|
||||
func (this *TankContext) registerBeans() {
|
||||
|
||||
//alien
|
||||
@ -188,7 +180,6 @@ func (this *TankContext) registerBeans() {
|
||||
|
||||
}
|
||||
|
||||
//从Map中获取某个Bean.
|
||||
func (this *TankContext) GetBean(bean core.Bean) core.Bean {
|
||||
|
||||
typeOf := reflect.TypeOf(bean)
|
||||
@ -197,12 +188,11 @@ func (this *TankContext) GetBean(bean core.Bean) core.Bean {
|
||||
if val, ok := this.BeanMap[typeName]; ok {
|
||||
return val
|
||||
} else {
|
||||
core.LOGGER.Panic("【%s】没有注册。", typeName)
|
||||
core.LOGGER.Panic("%s not registered", typeName)
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
//初始化每个Bean
|
||||
func (this *TankContext) initBeans() {
|
||||
|
||||
for _, bean := range this.BeanMap {
|
||||
@ -210,7 +200,7 @@ func (this *TankContext) initBeans() {
|
||||
}
|
||||
}
|
||||
|
||||
//系统如果安装好了就调用这个方法。
|
||||
//if application installed. invoke this method.
|
||||
func (this *TankContext) InstallOk() {
|
||||
|
||||
if core.CONFIG.Installed() {
|
||||
@ -223,7 +213,6 @@ func (this *TankContext) InstallOk() {
|
||||
|
||||
}
|
||||
|
||||
//销毁的方法
|
||||
func (this *TankContext) Destroy() {
|
||||
this.CloseDb()
|
||||
}
|
||||
|
@ -12,14 +12,12 @@ import (
|
||||
"time"
|
||||
)
|
||||
|
||||
//在Logger的基础上包装一个全新的Logger.
|
||||
type TankLogger struct {
|
||||
//加锁,在维护日志期间,禁止写入日志。
|
||||
//lock. when maintaining, cannot write
|
||||
sync.RWMutex
|
||||
|
||||
//继承logger
|
||||
//extend logger
|
||||
goLogger *log.Logger
|
||||
//日志记录所在的文件
|
||||
//log file.
|
||||
file *os.File
|
||||
}
|
||||
|
||||
@ -27,13 +25,12 @@ func (this *TankLogger) Init() {
|
||||
|
||||
this.openFile()
|
||||
|
||||
//每日00:00整理日志。
|
||||
this.Info("[cron job] Every day 00:00 maintain log file.")
|
||||
expression := "0 0 0 * * ?"
|
||||
cronJob := cron.New()
|
||||
err := cronJob.AddFunc(expression, this.maintain)
|
||||
core.PanicError(err)
|
||||
cronJob.Start()
|
||||
this.Info("[cron job] 每日00:00维护日志")
|
||||
|
||||
}
|
||||
|
||||
@ -41,12 +38,12 @@ func (this *TankLogger) Destroy() {
|
||||
this.closeFile()
|
||||
}
|
||||
|
||||
//处理日志的统一方法。
|
||||
//uniform log method
|
||||
func (this *TankLogger) Log(prefix string, format string, v ...interface{}) {
|
||||
|
||||
content := fmt.Sprintf(format+"\r\n", v...)
|
||||
|
||||
//控制台中打印日志,记录行号。
|
||||
//print to console with line number
|
||||
_, file, line, ok := runtime.Caller(2)
|
||||
if !ok {
|
||||
file = "???"
|
||||
@ -58,14 +55,12 @@ func (this *TankLogger) Log(prefix string, format string, v ...interface{}) {
|
||||
|
||||
this.goLogger.SetPrefix(prefix)
|
||||
|
||||
//每一行我们加上换行符
|
||||
err := this.goLogger.Output(3, content)
|
||||
if err != nil {
|
||||
fmt.Printf("occur error while logging %s \r\n", err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
//处理日志的统一方法。
|
||||
func (this *TankLogger) Debug(format string, v ...interface{}) {
|
||||
this.Log("[DEBUG]", format, v...)
|
||||
}
|
||||
@ -88,59 +83,59 @@ func (this *TankLogger) Panic(format string, v ...interface{}) {
|
||||
}
|
||||
|
||||
//将日志写入到今天的日期中(该方法内必须使用异步方法记录日志,否则会引发死锁)
|
||||
//rename log file.
|
||||
func (this *TankLogger) maintain() {
|
||||
|
||||
this.Info("每日维护日志")
|
||||
this.Info("maintain log")
|
||||
|
||||
this.Lock()
|
||||
defer this.Unlock()
|
||||
|
||||
//首先关闭文件。
|
||||
this.closeFile()
|
||||
|
||||
//日志归类到昨天
|
||||
//archive to yesterday
|
||||
destPath := util.GetLogPath() + "/tank-" + util.ConvertTimeToDateString(util.Yesterday()) + ".log"
|
||||
|
||||
//直接重命名文件
|
||||
//rename the log file.
|
||||
err := os.Rename(this.fileName(), destPath)
|
||||
if err != nil {
|
||||
this.Error("重命名文件出错", err.Error())
|
||||
this.Error("occur error while renaming log file %s %s", destPath, err.Error())
|
||||
}
|
||||
|
||||
//再次打开文件
|
||||
//reopen
|
||||
this.openFile()
|
||||
|
||||
//删除一个月之前的日志文件。
|
||||
//delete log files a month ago
|
||||
monthAgo := time.Now()
|
||||
monthAgo = monthAgo.AddDate(0, -1, 0)
|
||||
oldDestPath := util.GetLogPath() + "/tank-" + util.ConvertTimeToDateString(monthAgo) + ".log"
|
||||
this.Log("删除日志文件 %s", oldDestPath)
|
||||
this.Log("try to delete log file %s", oldDestPath)
|
||||
|
||||
//删除文件
|
||||
//delete log file
|
||||
exists := util.PathExists(oldDestPath)
|
||||
if exists {
|
||||
err = os.Remove(oldDestPath)
|
||||
if err != nil {
|
||||
this.Error("删除磁盘上的文件%s 出错 %s", oldDestPath, err.Error())
|
||||
this.Error("occur error while deleting log file %s %s", oldDestPath, err.Error())
|
||||
}
|
||||
} else {
|
||||
this.Error("日志文件 %s 不存在,无需删除", oldDestPath)
|
||||
this.Error("log file %s not exist, skip", oldDestPath)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//日志名称
|
||||
//log file name
|
||||
func (this *TankLogger) fileName() string {
|
||||
return util.GetLogPath() + "/tank.log"
|
||||
}
|
||||
|
||||
//打开日志文件
|
||||
//open log file
|
||||
func (this *TankLogger) openFile() {
|
||||
//日志输出到文件中 文件打开后暂时不关闭
|
||||
fmt.Printf("使用日志文件 %s\r\n", this.fileName())
|
||||
// not close log file immediately
|
||||
fmt.Printf("use log file %s\r\n", this.fileName())
|
||||
f, err := os.OpenFile(this.fileName(), os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)
|
||||
if err != nil {
|
||||
panic("日志文件无法正常打开: " + err.Error())
|
||||
panic("cannot open log file " + err.Error())
|
||||
}
|
||||
|
||||
this.goLogger = log.New(f, "", log.Ltime|log.Lshortfile)
|
||||
@ -152,12 +147,12 @@ func (this *TankLogger) openFile() {
|
||||
this.file = f
|
||||
}
|
||||
|
||||
//关闭日志文件
|
||||
//close log file.
|
||||
func (this *TankLogger) closeFile() {
|
||||
if this.file != nil {
|
||||
err := this.file.Close()
|
||||
if err != nil {
|
||||
panic("尝试关闭日志时出错: " + err.Error())
|
||||
panic("occur error while closing log file: " + err.Error())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -15,7 +15,6 @@ import (
|
||||
"time"
|
||||
)
|
||||
|
||||
//用于处理所有前来的请求
|
||||
type TankRouter struct {
|
||||
installController *rest.InstallController
|
||||
footprintService *rest.FootprintService
|
||||
@ -24,7 +23,6 @@ type TankRouter struct {
|
||||
installRouteMap map[string]func(writer http.ResponseWriter, request *http.Request)
|
||||
}
|
||||
|
||||
//构造方法
|
||||
func NewRouter() *TankRouter {
|
||||
router := &TankRouter{
|
||||
routeMap: make(map[string]func(writer http.ResponseWriter, request *http.Request)),
|
||||
@ -37,19 +35,19 @@ func NewRouter() *TankRouter {
|
||||
router.installController = b
|
||||
}
|
||||
|
||||
//装载userService.
|
||||
//load userService
|
||||
b = core.CONTEXT.GetBean(router.userService)
|
||||
if b, ok := b.(*rest.UserService); ok {
|
||||
router.userService = b
|
||||
}
|
||||
|
||||
//装载footprintService
|
||||
//load footprintService
|
||||
b = core.CONTEXT.GetBean(router.footprintService)
|
||||
if b, ok := b.(*rest.FootprintService); ok {
|
||||
router.footprintService = b
|
||||
}
|
||||
|
||||
//将Controller中的路由规则装载进来,InstallController中的除外
|
||||
//load Controllers except InstallController
|
||||
for _, controller := range core.CONTEXT.GetControllerMap() {
|
||||
|
||||
if controller == router.installController {
|
||||
@ -69,18 +67,18 @@ func NewRouter() *TankRouter {
|
||||
|
||||
}
|
||||
|
||||
//全局的异常捕获
|
||||
//catch global panic.
|
||||
func (this *TankRouter) GlobalPanicHandler(writer http.ResponseWriter, request *http.Request, startTime time.Time) {
|
||||
if err := recover(); err != nil {
|
||||
|
||||
//控制台中打印日志,记录行号。
|
||||
//get panic file and line number.
|
||||
_, file, line, ok := runtime.Caller(2)
|
||||
if !ok {
|
||||
file = "???"
|
||||
line = 0
|
||||
}
|
||||
|
||||
//全局未知异常
|
||||
//unkown panic
|
||||
if strings.HasSuffix(file, "runtime/panic.go") {
|
||||
_, file, line, ok = runtime.Caller(4)
|
||||
if !ok {
|
||||
@ -88,7 +86,7 @@ func (this *TankRouter) GlobalPanicHandler(writer http.ResponseWriter, request *
|
||||
line = 0
|
||||
}
|
||||
}
|
||||
//全局方便的异常拦截
|
||||
//async panic
|
||||
if strings.HasSuffix(file, "core/handler.go") {
|
||||
_, file, line, ok = runtime.Caller(4)
|
||||
if !ok {
|
||||
@ -101,71 +99,69 @@ func (this *TankRouter) GlobalPanicHandler(writer http.ResponseWriter, request *
|
||||
|
||||
var webResult *result.WebResult = nil
|
||||
if value, ok := err.(string); ok {
|
||||
//一个字符串,默认是请求错误。
|
||||
//string, default as BadRequest.
|
||||
webResult = result.CustomWebResult(result.BAD_REQUEST, value)
|
||||
} else if value, ok := err.(*result.WebResult); ok {
|
||||
//一个WebResult对象
|
||||
//*result.WebResult
|
||||
webResult = value
|
||||
} else if value, ok := err.(*result.CodeWrapper); ok {
|
||||
//一个WebResult对象
|
||||
//*result.CodeWrapper
|
||||
webResult = result.ConstWebResult(value)
|
||||
} else if value, ok := err.(error); ok {
|
||||
//一个普通的错误对象
|
||||
//normal error
|
||||
webResult = result.CustomWebResult(result.UNKNOWN, value.Error())
|
||||
} else {
|
||||
//其他不能识别的内容
|
||||
//other error
|
||||
webResult = result.ConstWebResult(result.UNKNOWN)
|
||||
}
|
||||
|
||||
//修改http code码
|
||||
//change the http status.
|
||||
writer.WriteHeader(result.FetchHttpStatus(webResult.Code))
|
||||
|
||||
//输出的是json格式 返回的内容申明是json,utf-8
|
||||
//if json, set the Content-Type to json.
|
||||
writer.Header().Set("Content-Type", "application/json;charset=UTF-8")
|
||||
|
||||
//用json的方式输出返回值。
|
||||
//write the response.
|
||||
b, _ := jsoniter.ConfigCompatibleWithStandardLibrary.Marshal(webResult)
|
||||
|
||||
//写到输出流中
|
||||
//write to writer.
|
||||
_, err := fmt.Fprintf(writer, string(b))
|
||||
if err != nil {
|
||||
fmt.Printf("输出结果时出错了\n")
|
||||
fmt.Printf("occur error while write response %s\r\n", err.Error())
|
||||
}
|
||||
|
||||
//错误情况记录。
|
||||
//log error.
|
||||
go core.RunWithRecovery(func() {
|
||||
this.footprintService.Trace(request, time.Now().Sub(startTime), false)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
//让Router具有处理请求的功能。
|
||||
func (this *TankRouter) ServeHTTP(writer http.ResponseWriter, request *http.Request) {
|
||||
|
||||
startTime := time.Now()
|
||||
|
||||
//每个请求的入口在这里
|
||||
//全局异常处理。
|
||||
//global panic handler
|
||||
defer this.GlobalPanicHandler(writer, request, startTime)
|
||||
|
||||
path := request.URL.Path
|
||||
if strings.HasPrefix(path, "/api") {
|
||||
|
||||
//对于IE浏览器,会自动缓存,因此设置不缓存Header.
|
||||
writer.Header().Set("Pragma", "No-cache")
|
||||
writer.Header().Set("Cache-Control", "no-cache")
|
||||
writer.Header().Set("Expires", "0")
|
||||
//IE browser will cache automatically. disable the cache.
|
||||
util.DisableCache(writer)
|
||||
|
||||
if core.CONFIG.Installed() {
|
||||
//已安装的模式
|
||||
|
||||
//统一处理用户的身份信息。
|
||||
//if installed.
|
||||
|
||||
//handler user's auth info.
|
||||
this.userService.PreHandle(writer, request)
|
||||
|
||||
if handler, ok := this.routeMap[path]; ok {
|
||||
handler(writer, request)
|
||||
} else {
|
||||
//直接将请求扔给每个controller,看看他们能不能处理,如果都不能处理,那就抛出找不到的错误
|
||||
|
||||
//dispatch the request to controller's handler.
|
||||
canHandle := false
|
||||
for _, controller := range core.CONTEXT.GetControllerMap() {
|
||||
if handler, exist := controller.HandleRoutes(writer, request); exist {
|
||||
@ -176,17 +172,17 @@ func (this *TankRouter) ServeHTTP(writer http.ResponseWriter, request *http.Requ
|
||||
}
|
||||
|
||||
if !canHandle {
|
||||
panic(result.CustomWebResult(result.NOT_FOUND, fmt.Sprintf("没有找到能够处理%s的方法", path)))
|
||||
panic(result.CustomWebResult(result.NOT_FOUND, fmt.Sprintf("cannot handle %s", path)))
|
||||
}
|
||||
}
|
||||
|
||||
//正常的访问记录会落到这里。
|
||||
//log the request
|
||||
go core.RunWithRecovery(func() {
|
||||
this.footprintService.Trace(request, time.Now().Sub(startTime), true)
|
||||
})
|
||||
|
||||
} else {
|
||||
//未安装模式
|
||||
//if not installed. try to install.
|
||||
if handler, ok := this.installRouteMap[path]; ok {
|
||||
handler(writer, request)
|
||||
} else {
|
||||
@ -196,7 +192,7 @@ func (this *TankRouter) ServeHTTP(writer http.ResponseWriter, request *http.Requ
|
||||
|
||||
} else {
|
||||
|
||||
//当作静态资源处理。默认从当前文件下面的static文件夹中取东西。
|
||||
//static file.
|
||||
dir := util.GetHtmlPath()
|
||||
|
||||
requestURI := request.RequestURI
|
||||
|
Reference in New Issue
Block a user