Finish the Abstract of Config.

This commit is contained in:
zicla 2019-04-28 01:25:31 +08:00
parent cd3b487fa8
commit aaf7578290
24 changed files with 371 additions and 339 deletions

27
code/core/config.go Normal file
View File

@ -0,0 +1,27 @@
package core
const (
//用户身份的cookie字段名
COOKIE_AUTH_KEY = "_ak"
//数据库表前缀 tank200表示当前应用版本是tank:2.0.x版数据库结构发生变化必然是中型升级
TABLE_PREFIX = "tank20_"
//当前版本
VERSION = "2.0.0"
)
type Config interface {
//是否已经安装
IsInstalled() bool
//启动端口
GetServerPort() int
//获取mysql链接
GetMysqlUrl() string
//文件存放路径
GetMatterPath() string
//完成安装过程,主要是要将配置写入到文件中
FinishInstall(mysqlPort int, mysqlHost string, mysqlSchema string, mysqlUsername string, mysqlPassword string)
}

View File

@ -7,6 +7,9 @@ import (
) )
type Context interface { type Context interface {
//具备响应http请求的能力
http.Handler
//获取数据库链接 //获取数据库链接
GetDB() *gorm.DB GetDB() *gorm.DB
@ -19,9 +22,6 @@ type Context interface {
//获取全局的ControllerMap //获取全局的ControllerMap
GetControllerMap() map[string]IController GetControllerMap() map[string]IController
//响应http的能力
ServeHTTP(writer http.ResponseWriter, request *http.Request)
//系统安装成功 //系统安装成功
InstallOk() InstallOk()

View File

@ -6,5 +6,8 @@ package core
//全局唯一的日志对象(在main函数中初始化) //全局唯一的日志对象(在main函数中初始化)
var LOGGER Logger var LOGGER Logger
//全局唯一配置
var CONFIG Config
//全局唯一的上下文(在main函数中初始化) //全局唯一的上下文(在main函数中初始化)
var CONTEXT Context var CONTEXT Context

View File

@ -1,7 +1,7 @@
package rest package rest
import ( import (
"github.com/eyebluecn/tank/code/config" "github.com/eyebluecn/tank/code/core"
"math" "math"
"reflect" "reflect"
"time" "time"
@ -40,7 +40,7 @@ func (this *Base) Map() map[string]interface{} {
} }
func (this *Base) TableName() string { func (this *Base) TableName() string {
return config.TABLE_PREFIX + "base" return core.TABLE_PREFIX + "base"
} }
//分页类 //分页类

View File

@ -1,7 +1,6 @@
package rest package rest
import ( import (
"github.com/eyebluecn/tank/code/config"
"github.com/eyebluecn/tank/code/core" "github.com/eyebluecn/tank/code/core"
"github.com/eyebluecn/tank/code/tool/result" "github.com/eyebluecn/tank/code/tool/result"
"github.com/eyebluecn/tank/code/tool/util" "github.com/eyebluecn/tank/code/tool/util"
@ -35,7 +34,7 @@ func (this *Bean) findUser(writer http.ResponseWriter, request *http.Request) *U
//验证用户是否已经登录。 //验证用户是否已经登录。
//登录身份有效期以数据库中记录的为准 //登录身份有效期以数据库中记录的为准
sessionId := util.GetSessionUuidFromRequest(request, config.COOKIE_AUTH_KEY) sessionId := util.GetSessionUuidFromRequest(request, core.COOKIE_AUTH_KEY)
if sessionId == "" { if sessionId == "" {
return nil return nil
} }

View File

@ -1,220 +0,0 @@
package rest
import (
"fmt"
"github.com/eyebluecn/tank/code/config"
"github.com/eyebluecn/tank/code/core"
"github.com/eyebluecn/tank/code/tool/cache"
"github.com/jinzhu/gorm"
"net/http"
"reflect"
)
//上下文管理数据库连接管理所有路由请求管理所有的单例component.
type Context struct {
//数据库连接
db *gorm.DB
//session缓存
SessionCache *cache.Table
//各类的Bean Map。这里面是包含ControllerMap中所有元素
BeanMap map[string]core.IBean
//只包含了Controller的map
ControllerMap map[string]core.IController
//处理所有路由请求
Router *Router
}
//初始化上下文
func (this *Context) Init() {
//创建一个用于存储session的缓存。
this.SessionCache = cache.NewTable()
//初始化Map
this.BeanMap = make(map[string]core.IBean)
this.ControllerMap = make(map[string]core.IController)
//注册各类Beans.在这个方法里面顺便把Controller装入ControllerMap中去。
this.registerBeans()
//初始化每个bean.
this.initBeans()
//初始化Router. 这个方法要在Bean注册好了之后才能。
this.Router = NewRouter()
//如果数据库信息配置好了,就直接打开数据库连接 同时执行Bean的ConfigPost方法
this.InstallOk()
}
//获取数据库对象
func (this *Context) GetDB() *gorm.DB {
return this.db
}
func (this *Context) GetSessionCache() *cache.Table {
return this.SessionCache
}
func (this *Context) GetControllerMap() map[string]core.IController {
return this.ControllerMap
}
func (this *Context) Cleanup() {
for _, bean := range this.BeanMap {
bean.Cleanup()
}
}
//响应http的能力
func (this *Context) ServeHTTP(writer http.ResponseWriter, request *http.Request) {
this.Router.ServeHTTP(writer, request)
}
func (this *Context) OpenDb() {
var err error = nil
this.db, err = gorm.Open("mysql", config.CONFIG.MysqlUrl)
if err != nil {
core.LOGGER.Panic("failed to connect mysql database")
}
//是否打开sql日志(在调试阶段可以打开以方便查看执行的SQL)
this.db.LogMode(false)
}
func (this *Context) CloseDb() {
if this.db != nil {
err := this.db.Close()
if err != nil {
core.LOGGER.Error("关闭数据库连接出错 %s", err.Error())
}
}
}
//注册一个Bean
func (this *Context) registerBean(bean core.IBean) {
typeOf := reflect.TypeOf(bean)
typeName := typeOf.String()
if element, ok := bean.(core.IBean); ok {
err := fmt.Sprintf("【%s】已经被注册了跳过。", typeName)
if _, ok := this.BeanMap[typeName]; ok {
core.LOGGER.Error(fmt.Sprintf(err))
} else {
this.BeanMap[typeName] = element
//看看是不是controller类型如果是那么单独放在ControllerMap中。
if controller, ok1 := bean.(core.IController); ok1 {
this.ControllerMap[typeName] = controller
}
}
} else {
core.LOGGER.Panic("注册的【%s】不是Bean类型。", typeName)
}
}
//注册各个Beans
func (this *Context) registerBeans() {
//alien
this.registerBean(new(AlienController))
this.registerBean(new(AlienService))
//dashboard
this.registerBean(new(DashboardController))
this.registerBean(new(DashboardDao))
this.registerBean(new(DashboardService))
//downloadToken
this.registerBean(new(DownloadTokenDao))
//imageCache
this.registerBean(new(ImageCacheController))
this.registerBean(new(ImageCacheDao))
this.registerBean(new(ImageCacheService))
//install
this.registerBean(new(InstallController))
//matter
this.registerBean(new(MatterController))
this.registerBean(new(MatterDao))
this.registerBean(new(MatterService))
//preference
this.registerBean(new(PreferenceController))
this.registerBean(new(PreferenceDao))
this.registerBean(new(PreferenceService))
//footprint
this.registerBean(new(FootprintController))
this.registerBean(new(FootprintDao))
this.registerBean(new(FootprintService))
//session
this.registerBean(new(SessionDao))
this.registerBean(new(SessionService))
//uploadToken
this.registerBean(new(UploadTokenDao))
//user
this.registerBean(new(UserController))
this.registerBean(new(UserDao))
this.registerBean(new(UserService))
//webdav
this.registerBean(new(DavController))
this.registerBean(new(DavService))
}
//从Map中获取某个Bean.
func (this *Context) GetBean(bean core.IBean) core.IBean {
typeOf := reflect.TypeOf(bean)
typeName := typeOf.String()
if val, ok := this.BeanMap[typeName]; ok {
return val
} else {
core.LOGGER.Panic("【%s】没有注册。", typeName)
return nil
}
}
//初始化每个Bean
func (this *Context) initBeans() {
for key, bean := range this.BeanMap {
core.LOGGER.Info("init %s", key)
bean.Init()
}
}
//系统如果安装好了就调用这个方法。
func (this *Context) InstallOk() {
if config.CONFIG.Installed {
this.OpenDb()
for _, bean := range this.BeanMap {
bean.Bootstrap()
}
}
}
//销毁的方法
func (this *Context) Destroy() {
this.CloseDb()
}

View File

@ -1,6 +1,6 @@
package rest package rest
import "github.com/eyebluecn/tank/code/config" import "github.com/eyebluecn/tank/code/core"
/** /**
* 系统的所有访问记录均记录在此 * 系统的所有访问记录均记录在此
@ -21,7 +21,7 @@ type Dashboard struct {
// set File's table name to be `profiles` // set File's table name to be `profiles`
func (this *Dashboard) TableName() string { func (this *Dashboard) TableName() string {
return config.TABLE_PREFIX + "dashboard" return core.TABLE_PREFIX + "dashboard"
} }
/** /**

View File

@ -1,7 +1,7 @@
package rest package rest
import ( import (
"github.com/eyebluecn/tank/code/config" "github.com/eyebluecn/tank/code/core"
"time" "time"
) )
@ -14,5 +14,5 @@ type DownloadToken struct {
} }
func (this *DownloadToken) TableName() string { func (this *DownloadToken) TableName() string {
return config.TABLE_PREFIX + "download_token" return core.TABLE_PREFIX + "download_token"
} }

View File

@ -1,6 +1,6 @@
package rest package rest
import "github.com/eyebluecn/tank/code/config" import "github.com/eyebluecn/tank/code/core"
/** /**
* 系统的所有访问记录均记录在此 * 系统的所有访问记录均记录在此
@ -18,5 +18,5 @@ type Footprint struct {
// set File's table name to be `profiles` // set File's table name to be `profiles`
func (this *Footprint) TableName() string { func (this *Footprint) TableName() string {
return config.TABLE_PREFIX + "footprint" return core.TABLE_PREFIX + "footprint"
} }

View File

@ -2,7 +2,7 @@ package rest
import ( import (
"encoding/json" "encoding/json"
"github.com/eyebluecn/tank/code/config"
"github.com/eyebluecn/tank/code/core" "github.com/eyebluecn/tank/code/core"
"github.com/eyebluecn/tank/code/tool/util" "github.com/eyebluecn/tank/code/tool/util"
"github.com/robfig/cron" "github.com/robfig/cron"
@ -76,7 +76,7 @@ func (this *FootprintService) Trace(writer http.ResponseWriter, request *http.Re
} }
//有可能DB尚且没有配置 直接打印出内容,并且退出 //有可能DB尚且没有配置 直接打印出内容,并且退出
if config.CONFIG.Installed { if core.CONFIG.IsInstalled() {
user := this.findUser(writer, request) user := this.findUser(writer, request)
userUuid := "" userUuid := ""
if user != nil { if user != nil {

View File

@ -1,7 +1,7 @@
package rest package rest
import ( import (
"github.com/eyebluecn/tank/code/config" "github.com/eyebluecn/tank/code/core"
) )
/** /**
@ -23,7 +23,7 @@ type ImageCache struct {
// set File's table name to be `profiles` // set File's table name to be `profiles`
func (this *ImageCache) TableName() string { func (this *ImageCache) TableName() string {
return config.TABLE_PREFIX + "image_cache" return core.TABLE_PREFIX + "image_cache"
} }
// 获取该ImageCache的绝对路径。path代表的是相对路径。 // 获取该ImageCache的绝对路径。path代表的是相对路径。

View File

@ -2,18 +2,16 @@ package rest
import ( import (
"fmt" "fmt"
"github.com/eyebluecn/tank/code/config"
"github.com/eyebluecn/tank/code/core" "github.com/eyebluecn/tank/code/core"
"github.com/eyebluecn/tank/code/tool/builder" "github.com/eyebluecn/tank/code/tool/builder"
"github.com/eyebluecn/tank/code/tool/result" "github.com/eyebluecn/tank/code/tool/result"
"github.com/eyebluecn/tank/code/tool/util" "github.com/eyebluecn/tank/code/tool/util"
"github.com/jinzhu/gorm" "github.com/jinzhu/gorm"
"github.com/json-iterator/go"
"github.com/nu7hatch/gouuid" "github.com/nu7hatch/gouuid"
"go/build" "go/build"
"io/ioutil" "io/ioutil"
"net/http" "net/http"
"os"
"regexp" "regexp"
"strconv" "strconv"
"time" "time"
@ -427,38 +425,8 @@ func (this *InstallController) Finish(writer http.ResponseWriter, request *http.
panic(result.BadRequest(`请至少配置一名管理员`)) panic(result.BadRequest(`请至少配置一名管理员`))
} }
var configItem = &config.ConfigItem{
//默认监听端口号
ServerPort: config.CONFIG.ServerPort,
//上传的文件路径,要求不以/结尾。如果没有指定默认在根目录下的matter文件夹中。eg: /var/www/matter
MatterPath: config.CONFIG.MatterPath,
//mysql相关配置。
//数据库端口
MysqlPort: mysqlPort,
//数据库Host
MysqlHost: mysqlHost,
//数据库名字
MysqlSchema: mysqlSchema,
//用户名
MysqlUsername: mysqlUsername,
//密码
MysqlPassword: mysqlPassword,
}
//用json的方式输出返回值。为了让格式更好看。
jsonStr, _ := jsoniter.ConfigCompatibleWithStandardLibrary.MarshalIndent(configItem, "", " ")
//写入到配置文件中不能使用os.O_APPEND 否则会追加)
filePath := util.GetConfPath() + "/tank.json"
f, err := os.OpenFile(filePath, os.O_RDWR|os.O_CREATE, 0777)
this.PanicError(err)
_, err = f.Write(jsonStr)
this.PanicError(err)
err = f.Close()
this.PanicError(err)
//通知配置文件安装完毕。 //通知配置文件安装完毕。
config.CONFIG.InstallOk() core.CONFIG.FinishInstall(mysqlPort, mysqlHost, mysqlSchema, mysqlUsername, mysqlPassword)
//通知全局上下文,说系统安装好了 //通知全局上下文,说系统安装好了
core.CONTEXT.InstallOk() core.CONTEXT.InstallOk()

View File

@ -1,7 +1,6 @@
package rest package rest
import ( import (
"github.com/eyebluecn/tank/code/config"
"github.com/eyebluecn/tank/code/core" "github.com/eyebluecn/tank/code/core"
"github.com/eyebluecn/tank/code/tool/builder" "github.com/eyebluecn/tank/code/tool/builder"
"github.com/eyebluecn/tank/code/tool/result" "github.com/eyebluecn/tank/code/tool/result"
@ -367,7 +366,7 @@ func (this *MatterDao) Cleanup() {
db := core.CONTEXT.GetDB().Where("uuid is not null").Delete(Matter{}) db := core.CONTEXT.GetDB().Where("uuid is not null").Delete(Matter{})
this.PanicError(db.Error) this.PanicError(db.Error)
err := os.RemoveAll(config.CONFIG.MatterPath) err := os.RemoveAll(core.CONFIG.GetMatterPath())
this.PanicError(err) this.PanicError(err)
} }

View File

@ -2,7 +2,8 @@ package rest
import ( import (
"fmt" "fmt"
"github.com/eyebluecn/tank/code/config" "github.com/eyebluecn/tank/code/core"
"github.com/eyebluecn/tank/code/tool/util" "github.com/eyebluecn/tank/code/tool/util"
) )
@ -37,7 +38,7 @@ type Matter struct {
// set File's table name to be `profiles` // set File's table name to be `profiles`
func (Matter) TableName() string { func (Matter) TableName() string {
return config.TABLE_PREFIX + "matter" return core.TABLE_PREFIX + "matter"
} }
// 获取该Matter的绝对路径。path代表的是相对路径。 // 获取该Matter的绝对路径。path代表的是相对路径。
@ -67,7 +68,7 @@ func NewRootMatter(user *User) *Matter {
//获取到用户文件的根目录。 //获取到用户文件的根目录。
func GetUserFileRootDir(username string) (rootDirPath string) { func GetUserFileRootDir(username string) (rootDirPath string) {
rootDirPath = fmt.Sprintf("%s/%s/%s", config.CONFIG.MatterPath, username, MATTER_ROOT) rootDirPath = fmt.Sprintf("%s/%s/%s", core.CONFIG.GetMatterPath(), username, MATTER_ROOT)
return rootDirPath return rootDirPath
} }
@ -75,7 +76,7 @@ func GetUserFileRootDir(username string) (rootDirPath string) {
//获取到用户缓存的根目录。 //获取到用户缓存的根目录。
func GetUserCacheRootDir(username string) (rootDirPath string) { func GetUserCacheRootDir(username string) (rootDirPath string) {
rootDirPath = fmt.Sprintf("%s/%s/%s", config.CONFIG.MatterPath, username, MATTER_CACHE) rootDirPath = fmt.Sprintf("%s/%s/%s", core.CONFIG.GetMatterPath(), username, MATTER_CACHE)
return rootDirPath return rootDirPath
} }

View File

@ -1,6 +1,6 @@
package rest package rest
import "github.com/eyebluecn/tank/code/config" import "github.com/eyebluecn/tank/code/core"
type Preference struct { type Preference struct {
Base Base
@ -14,5 +14,5 @@ type Preference struct {
// set File's table name to be `profiles` // set File's table name to be `profiles`
func (this *Preference) TableName() string { func (this *Preference) TableName() string {
return config.TABLE_PREFIX + "preference" return core.TABLE_PREFIX + "preference"
} }

View File

@ -1,7 +1,7 @@
package rest package rest
import ( import (
"github.com/eyebluecn/tank/code/config" "github.com/eyebluecn/tank/code/core"
"time" "time"
) )
@ -14,5 +14,5 @@ type Session struct {
// set User's table name to be `profiles` // set User's table name to be `profiles`
func (this *Session) TableName() string { func (this *Session) TableName() string {
return config.TABLE_PREFIX + "session" return core.TABLE_PREFIX + "session"
} }

View File

@ -1,7 +1,7 @@
package rest package rest
import ( import (
"github.com/eyebluecn/tank/code/config" "github.com/eyebluecn/tank/code/core"
"time" "time"
) )
@ -18,5 +18,5 @@ type UploadToken struct {
} }
func (this *UploadToken) TableName() string { func (this *UploadToken) TableName() string {
return config.TABLE_PREFIX + "upload_token" return core.TABLE_PREFIX + "upload_token"
} }

View File

@ -1,7 +1,6 @@
package rest package rest
import ( import (
"github.com/eyebluecn/tank/code/config"
"github.com/eyebluecn/tank/code/core" "github.com/eyebluecn/tank/code/core"
"github.com/eyebluecn/tank/code/tool/builder" "github.com/eyebluecn/tank/code/tool/builder"
"github.com/eyebluecn/tank/code/tool/result" "github.com/eyebluecn/tank/code/tool/result"
@ -83,7 +82,7 @@ func (this *UserController) Login(writer http.ResponseWriter, request *http.Requ
//设置用户的cookie. //设置用户的cookie.
cookie := http.Cookie{ cookie := http.Cookie{
Name: config.COOKIE_AUTH_KEY, Name: core.COOKIE_AUTH_KEY,
Path: "/", Path: "/",
Value: session.Uuid, Value: session.Uuid,
Expires: expiration} Expires: expiration}
@ -218,7 +217,7 @@ func (this *UserController) Detail(writer http.ResponseWriter, request *http.Req
func (this *UserController) Logout(writer http.ResponseWriter, request *http.Request) *result.WebResult { func (this *UserController) Logout(writer http.ResponseWriter, request *http.Request) *result.WebResult {
//session置为过期 //session置为过期
sessionCookie, err := request.Cookie(config.COOKIE_AUTH_KEY) sessionCookie, err := request.Cookie(core.COOKIE_AUTH_KEY)
if err != nil { if err != nil {
return this.Success("已经退出登录了!") return this.Success("已经退出登录了!")
} }
@ -241,7 +240,7 @@ func (this *UserController) Logout(writer http.ResponseWriter, request *http.Req
expiration := time.Now() expiration := time.Now()
expiration = expiration.AddDate(-1, 0, 0) expiration = expiration.AddDate(-1, 0, 0)
cookie := http.Cookie{ cookie := http.Cookie{
Name: config.COOKIE_AUTH_KEY, Name: core.COOKIE_AUTH_KEY,
Path: "/", Path: "/",
Value: sessionId, Value: sessionId,
Expires: expiration} Expires: expiration}

View File

@ -1,7 +1,7 @@
package rest package rest
import ( import (
"github.com/eyebluecn/tank/code/config" "github.com/eyebluecn/tank/code/core"
"time" "time"
) )
@ -45,7 +45,7 @@ type User struct {
// set User's table name to be `profiles` // set User's table name to be `profiles`
func (this *User) TableName() string { func (this *User) TableName() string {
return config.TABLE_PREFIX + "user" return core.TABLE_PREFIX + "user"
} }
//通过一个字符串获取性别 //通过一个字符串获取性别

View File

@ -1,7 +1,6 @@
package rest package rest
import ( import (
"github.com/eyebluecn/tank/code/config"
"github.com/eyebluecn/tank/code/core" "github.com/eyebluecn/tank/code/core"
"github.com/eyebluecn/tank/code/tool/cache" "github.com/eyebluecn/tank/code/tool/cache"
"github.com/eyebluecn/tank/code/tool/result" "github.com/eyebluecn/tank/code/tool/result"
@ -72,12 +71,12 @@ func (this *UserService) MatterUnlock(userUuid string) {
//装载session信息如果session没有了根据cookie去装填用户信息。 //装载session信息如果session没有了根据cookie去装填用户信息。
//在所有的路由最初会调用这个方法 //在所有的路由最初会调用这个方法
func (this *UserService) preHandle(writer http.ResponseWriter, request *http.Request) { func (this *UserService) PreHandle(writer http.ResponseWriter, request *http.Request) {
//登录身份有效期以数据库中记录的为准 //登录身份有效期以数据库中记录的为准
//验证用户是否已经登录。 //验证用户是否已经登录。
sessionCookie, err := request.Cookie(config.COOKIE_AUTH_KEY) sessionCookie, err := request.Cookie(core.COOKIE_AUTH_KEY)
if err != nil { if err != nil {
return return
} }

View File

@ -1,35 +1,24 @@
package config package support
import ( import (
"github.com/eyebluecn/tank/code/core" "github.com/eyebluecn/tank/code/core"
"github.com/eyebluecn/tank/code/tool/util" "github.com/eyebluecn/tank/code/tool/util"
"github.com/json-iterator/go" "github.com/json-iterator/go"
"io/ioutil" "io/ioutil"
"os"
"time" "time"
"unsafe" "unsafe"
) )
const (
//用户身份的cookie字段名
COOKIE_AUTH_KEY = "_ak"
//数据库表前缀 tank200表示当前应用版本是tank:2.0.x版数据库结构发生变化必然是中型升级
TABLE_PREFIX = "tank20_"
//当前版本
VERSION = "2.0.0"
)
/* /*
如果你需要在本地127.0.0.1创建默认的数据库和账号使用以下语句 如果你需要在本地127.0.0.1创建默认的数据库和账号使用以下语句
create database tank; create database tank;
grant all privileges on tank.* to tank identified by 'tank123'; grant all privileges on tank.* to tank identified by 'tank123';
flush privileges; flush privileges;
*/ */
var CONFIG = &Config{}
//依赖外部定义的变量。 //依赖外部定义的变量。
type Config struct { type TankConfig struct {
//默认监听端口号 //默认监听端口号
ServerPort int ServerPort int
//网站是否已经完成安装 //网站是否已经完成安装
@ -67,9 +56,6 @@ func (this *ConfigItem) validate() bool {
if this.ServerPort == 0 { if this.ServerPort == 0 {
core.LOGGER.Error("ServerPort 未配置") core.LOGGER.Error("ServerPort 未配置")
return false return false
} else {
//只要配置文件中有配置端口,就使用。
CONFIG.ServerPort = this.ServerPort
} }
if this.MysqlUsername == "" { if this.MysqlUsername == "" {
@ -102,7 +88,7 @@ func (this *ConfigItem) validate() bool {
} }
//验证配置文件是否完好 //验证配置文件是否完好
func (this *Config) Init() { func (this *TankConfig) Init() {
//JSON初始化 //JSON初始化
jsoniter.RegisterTypeDecoderFunc("time.Time", func(ptr unsafe.Pointer, iter *jsoniter.Iterator) { jsoniter.RegisterTypeDecoderFunc("time.Time", func(ptr unsafe.Pointer, iter *jsoniter.Iterator) {
@ -129,7 +115,7 @@ func (this *Config) Init() {
} }
//系统如果安装好了就调用这个方法。 //系统如果安装好了就调用这个方法。
func (this *Config) ReadFromConfigFile() { func (this *TankConfig) ReadFromConfigFile() {
//读取配置文件 //读取配置文件
filePath := util.GetConfPath() + "/tank.json" filePath := util.GetConfPath() + "/tank.json"
@ -161,7 +147,7 @@ func (this *Config) ReadFromConfigFile() {
} else { } else {
this.MatterPath = this.Item.MatterPath this.MatterPath = this.Item.MatterPath
} }
util.MakeDirAll(CONFIG.MatterPath) util.MakeDirAll(this.MatterPath)
//使用配置项中的端口 //使用配置项中的端口
if this.Item.ServerPort != 0 { if this.Item.ServerPort != 0 {
@ -176,8 +162,59 @@ func (this *Config) ReadFromConfigFile() {
} }
} }
//系统如果安装好了就调用这个方法。 //是否已经安装
func (this *Config) InstallOk() { func (this *TankConfig) IsInstalled() bool {
return this.Installed
}
//启动端口
func (this *TankConfig) GetServerPort() int {
return this.ServerPort
}
//获取mysql链接
func (this *TankConfig) GetMysqlUrl() string {
return this.MysqlUrl
}
//文件存放路径
func (this *TankConfig) GetMatterPath() string {
return this.MatterPath
}
//完成安装过程,主要是要将配置写入到文件中
func (this *TankConfig) FinishInstall(mysqlPort int, mysqlHost string, mysqlSchema string, mysqlUsername string, mysqlPassword string) {
var configItem = &ConfigItem{
//默认监听端口号
ServerPort: core.CONFIG.GetServerPort(),
//上传的文件路径,要求不以/结尾。如果没有指定默认在根目录下的matter文件夹中。eg: /var/www/matter
MatterPath: core.CONFIG.GetMatterPath(),
//mysql相关配置。
//数据库端口
MysqlPort: mysqlPort,
//数据库Host
MysqlHost: mysqlHost,
//数据库名字
MysqlSchema: mysqlSchema,
//用户名
MysqlUsername: mysqlUsername,
//密码
MysqlPassword: mysqlPassword,
}
//用json的方式输出返回值。为了让格式更好看。
jsonStr, _ := jsoniter.ConfigCompatibleWithStandardLibrary.MarshalIndent(configItem, "", " ")
//写入到配置文件中不能使用os.O_APPEND 否则会追加)
filePath := util.GetConfPath() + "/tank.json"
f, err := os.OpenFile(filePath, os.O_RDWR|os.O_CREATE, 0777)
util.PanicError(err)
_, err = f.Write(jsonStr)
util.PanicError(err)
err = f.Close()
util.PanicError(err)
this.ReadFromConfigFile() this.ReadFromConfigFile()
} }

View File

@ -1 +1,220 @@
package support package support
import (
"fmt"
"github.com/eyebluecn/tank/code/core"
"github.com/eyebluecn/tank/code/rest"
"github.com/eyebluecn/tank/code/tool/cache"
"github.com/jinzhu/gorm"
"net/http"
"reflect"
)
//上下文管理数据库连接管理所有路由请求管理所有的单例component.
type TankContext struct {
//数据库连接
db *gorm.DB
//session缓存
SessionCache *cache.Table
//各类的Bean Map。这里面是包含ControllerMap中所有元素
BeanMap map[string]core.IBean
//只包含了Controller的map
ControllerMap map[string]core.IController
//处理所有路由请求
Router *TankRouter
}
//初始化上下文
func (this *TankContext) Init() {
//创建一个用于存储session的缓存。
this.SessionCache = cache.NewTable()
//初始化Map
this.BeanMap = make(map[string]core.IBean)
this.ControllerMap = make(map[string]core.IController)
//注册各类Beans.在这个方法里面顺便把Controller装入ControllerMap中去。
this.registerBeans()
//初始化每个bean.
this.initBeans()
//初始化Router. 这个方法要在Bean注册好了之后才能。
this.Router = NewRouter()
//如果数据库信息配置好了,就直接打开数据库连接 同时执行Bean的ConfigPost方法
this.InstallOk()
}
//获取数据库对象
func (this *TankContext) GetDB() *gorm.DB {
return this.db
}
func (this *TankContext) GetSessionCache() *cache.Table {
return this.SessionCache
}
func (this *TankContext) GetControllerMap() map[string]core.IController {
return this.ControllerMap
}
func (this *TankContext) Cleanup() {
for _, bean := range this.BeanMap {
bean.Cleanup()
}
}
//响应http的能力
func (this *TankContext) ServeHTTP(writer http.ResponseWriter, request *http.Request) {
this.Router.ServeHTTP(writer, request)
}
func (this *TankContext) OpenDb() {
var err error = nil
this.db, err = gorm.Open("mysql", core.CONFIG.GetMysqlUrl())
if err != nil {
core.LOGGER.Panic("failed to connect mysql database")
}
//是否打开sql日志(在调试阶段可以打开以方便查看执行的SQL)
this.db.LogMode(false)
}
func (this *TankContext) CloseDb() {
if this.db != nil {
err := this.db.Close()
if err != nil {
core.LOGGER.Error("关闭数据库连接出错 %s", err.Error())
}
}
}
//注册一个Bean
func (this *TankContext) registerBean(bean core.IBean) {
typeOf := reflect.TypeOf(bean)
typeName := typeOf.String()
if element, ok := bean.(core.IBean); ok {
err := fmt.Sprintf("【%s】已经被注册了跳过。", typeName)
if _, ok := this.BeanMap[typeName]; ok {
core.LOGGER.Error(fmt.Sprintf(err))
} else {
this.BeanMap[typeName] = element
//看看是不是controller类型如果是那么单独放在ControllerMap中。
if controller, ok1 := bean.(core.IController); ok1 {
this.ControllerMap[typeName] = controller
}
}
} else {
core.LOGGER.Panic("注册的【%s】不是Bean类型。", typeName)
}
}
//注册各个Beans
func (this *TankContext) registerBeans() {
//alien
this.registerBean(new(rest.AlienController))
this.registerBean(new(rest.AlienService))
//dashboard
this.registerBean(new(rest.DashboardController))
this.registerBean(new(rest.DashboardDao))
this.registerBean(new(rest.DashboardService))
//downloadToken
this.registerBean(new(rest.DownloadTokenDao))
//imageCache
this.registerBean(new(rest.ImageCacheController))
this.registerBean(new(rest.ImageCacheDao))
this.registerBean(new(rest.ImageCacheService))
//install
this.registerBean(new(rest.InstallController))
//matter
this.registerBean(new(rest.MatterController))
this.registerBean(new(rest.MatterDao))
this.registerBean(new(rest.MatterService))
//preference
this.registerBean(new(rest.PreferenceController))
this.registerBean(new(rest.PreferenceDao))
this.registerBean(new(rest.PreferenceService))
//footprint
this.registerBean(new(rest.FootprintController))
this.registerBean(new(rest.FootprintDao))
this.registerBean(new(rest.FootprintService))
//session
this.registerBean(new(rest.SessionDao))
this.registerBean(new(rest.SessionService))
//uploadToken
this.registerBean(new(rest.UploadTokenDao))
//user
this.registerBean(new(rest.UserController))
this.registerBean(new(rest.UserDao))
this.registerBean(new(rest.UserService))
//webdav
this.registerBean(new(rest.DavController))
this.registerBean(new(rest.DavService))
}
//从Map中获取某个Bean.
func (this *TankContext) GetBean(bean core.IBean) core.IBean {
typeOf := reflect.TypeOf(bean)
typeName := typeOf.String()
if val, ok := this.BeanMap[typeName]; ok {
return val
} else {
core.LOGGER.Panic("【%s】没有注册。", typeName)
return nil
}
}
//初始化每个Bean
func (this *TankContext) initBeans() {
for _, bean := range this.BeanMap {
bean.Init()
}
}
//系统如果安装好了就调用这个方法。
func (this *TankContext) InstallOk() {
if core.CONFIG.IsInstalled() {
this.OpenDb()
for _, bean := range this.BeanMap {
bean.Bootstrap()
}
}
}
//销毁的方法
func (this *TankContext) Destroy() {
this.CloseDb()
}

View File

@ -1,9 +1,10 @@
package rest package support
import ( import (
"fmt" "fmt"
"github.com/eyebluecn/tank/code/config"
"github.com/eyebluecn/tank/code/core" "github.com/eyebluecn/tank/code/core"
"github.com/eyebluecn/tank/code/rest"
"github.com/eyebluecn/tank/code/tool/result" "github.com/eyebluecn/tank/code/tool/result"
"github.com/eyebluecn/tank/code/tool/util" "github.com/eyebluecn/tank/code/tool/util"
"github.com/json-iterator/go" "github.com/json-iterator/go"
@ -15,36 +16,36 @@ import (
) )
//用于处理所有前来的请求 //用于处理所有前来的请求
type Router struct { type TankRouter struct {
installController *InstallController installController *rest.InstallController
footprintService *FootprintService footprintService *rest.FootprintService
userService *UserService userService *rest.UserService
routeMap map[string]func(writer http.ResponseWriter, request *http.Request) routeMap map[string]func(writer http.ResponseWriter, request *http.Request)
installRouteMap map[string]func(writer http.ResponseWriter, request *http.Request) installRouteMap map[string]func(writer http.ResponseWriter, request *http.Request)
} }
//构造方法 //构造方法
func NewRouter() *Router { func NewRouter() *TankRouter {
router := &Router{ router := &TankRouter{
routeMap: make(map[string]func(writer http.ResponseWriter, request *http.Request)), routeMap: make(map[string]func(writer http.ResponseWriter, request *http.Request)),
installRouteMap: make(map[string]func(writer http.ResponseWriter, request *http.Request)), installRouteMap: make(map[string]func(writer http.ResponseWriter, request *http.Request)),
} }
//installController. //installController.
b := core.CONTEXT.GetBean(router.installController) b := core.CONTEXT.GetBean(router.installController)
if b, ok := b.(*InstallController); ok { if b, ok := b.(*rest.InstallController); ok {
router.installController = b router.installController = b
} }
//装载userService. //装载userService.
b = core.CONTEXT.GetBean(router.userService) b = core.CONTEXT.GetBean(router.userService)
if b, ok := b.(*UserService); ok { if b, ok := b.(*rest.UserService); ok {
router.userService = b router.userService = b
} }
//装载footprintService //装载footprintService
b = core.CONTEXT.GetBean(router.footprintService) b = core.CONTEXT.GetBean(router.footprintService)
if b, ok := b.(*FootprintService); ok { if b, ok := b.(*rest.FootprintService); ok {
router.footprintService = b router.footprintService = b
} }
@ -69,7 +70,7 @@ func NewRouter() *Router {
} }
//全局的异常捕获 //全局的异常捕获
func (this *Router) GlobalPanicHandler(writer http.ResponseWriter, request *http.Request, startTime time.Time) { func (this *TankRouter) GlobalPanicHandler(writer http.ResponseWriter, request *http.Request, startTime time.Time) {
if err := recover(); err != nil { if err := recover(); err != nil {
core.LOGGER.Error("错误: %v", err) core.LOGGER.Error("错误: %v", err)
@ -115,7 +116,7 @@ func (this *Router) GlobalPanicHandler(writer http.ResponseWriter, request *http
} }
//让Router具有处理请求的功能。 //让Router具有处理请求的功能。
func (this *Router) ServeHTTP(writer http.ResponseWriter, request *http.Request) { func (this *TankRouter) ServeHTTP(writer http.ResponseWriter, request *http.Request) {
startTime := time.Now() startTime := time.Now()
@ -131,11 +132,11 @@ func (this *Router) ServeHTTP(writer http.ResponseWriter, request *http.Request)
writer.Header().Set("Cache-Control", "no-cache") writer.Header().Set("Cache-Control", "no-cache")
writer.Header().Set("Expires", "0") writer.Header().Set("Expires", "0")
if config.CONFIG.Installed { if core.CONFIG.IsInstalled() {
//已安装的模式 //已安装的模式
//统一处理用户的身份信息。 //统一处理用户的身份信息。
this.userService.preHandle(writer, request) this.userService.PreHandle(writer, request)
if handler, ok := this.routeMap[path]; ok { if handler, ok := this.routeMap[path]; ok {
handler(writer, request) handler(writer, request)

20
main.go
View File

@ -2,9 +2,7 @@ package main
import ( import (
"fmt" "fmt"
"github.com/eyebluecn/tank/code/config"
"github.com/eyebluecn/tank/code/core" "github.com/eyebluecn/tank/code/core"
"github.com/eyebluecn/tank/code/rest"
"github.com/eyebluecn/tank/code/support" "github.com/eyebluecn/tank/code/support"
_ "github.com/go-sql-driver/mysql" _ "github.com/go-sql-driver/mysql"
"log" "log"
@ -13,26 +11,28 @@ import (
func main() { func main() {
//日志第一优先级保障 //第一步。日志
tankLogger := &support.TankLogger{} tankLogger := &support.TankLogger{}
core.LOGGER = tankLogger core.LOGGER = tankLogger
tankLogger.Init() tankLogger.Init()
defer tankLogger.Destroy() defer tankLogger.Destroy()
//装载配置文件,这个决定了是否需要执行安装过程 //第二步。配置
config.CONFIG.Init() tankConfig := &support.TankConfig{}
core.CONFIG = tankConfig
tankConfig.Init()
//全局运行的上下文 //第三步。全局运行的上下文
tankContext := &rest.Context{} tankContext := &support.TankContext{}
core.CONTEXT = tankContext core.CONTEXT = tankContext
tankContext.Init() tankContext.Init()
defer tankContext.Destroy() defer tankContext.Destroy()
//第四步。启动http服务
http.Handle("/", core.CONTEXT) http.Handle("/", core.CONTEXT)
core.LOGGER.Info("App started at http://localhost:%v", core.CONFIG.GetServerPort())
core.LOGGER.Info("App started at http://localhost:%v", config.CONFIG.ServerPort) dotPort := fmt.Sprintf(":%v", core.CONFIG.GetServerPort())
dotPort := fmt.Sprintf(":%v", config.CONFIG.ServerPort)
err1 := http.ListenAndServe(dotPort, nil) err1 := http.ListenAndServe(dotPort, nil)
if err1 != nil { if err1 != nil {
log.Fatal("ListenAndServe: ", err1) log.Fatal("ListenAndServe: ", err1)