use logrus to project default log tools

This commit is contained in:
hoteas 2021-05-25 05:08:17 +08:00
parent 9bc930750d
commit df07afb744
15 changed files with 491 additions and 457 deletions

32
LICENSE
View File

@ -10,7 +10,7 @@ AND DISTRIBUTION
"License" shall mean the terms and conditions for use, reproduction, and distribution
as defined by Sections 1 through 9 of this document.
as defined by Sections 1 through 9 of that document.
@ -21,7 +21,7 @@ owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all other entities
that control, are controlled by, or are under common control with that entity.
For the purposes of this definition, "control" means (i) the power, direct
For the purposes of that definition, "control" means (i) the power, direct
or indirect, to cause the direction or management of such entity, whether
by contract or otherwise, or (ii) ownership of fifty percent (50%) or more
of the outstanding shares, or (iii) beneficial ownership of such entity.
@ -29,7 +29,7 @@ of the outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity exercising permissions
granted by this License.
granted by that License.
@ -55,7 +55,7 @@ below).
"Derivative Works" shall mean any work, whether in Source or Object form,
that is based on (or derived from) the Work and for which the editorial revisions,
annotations, elaborations, or other modifications represent, as a whole, an
original work of authorship. For the purposes of this License, Derivative
original work of authorship. For the purposes of that License, Derivative
Works shall not include works that remain separable from, or merely link (or
bind by name) to the interfaces of, the Work and Derivative Works thereof.
@ -65,7 +65,7 @@ bind by name) to the interfaces of, the Work and Derivative Works thereof.
of the Work and any modifications or additions to that Work or Derivative
Works thereof, that is intentionally submitted to Licensor for inclusion in
the Work by the copyright owner or by an individual or Legal Entity authorized
to submit on behalf of the copyright owner. For the purposes of this definition,
to submit on behalf of the copyright owner. For the purposes of that definition,
"submitted" means any form of electronic, verbal, or written communication
sent to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems, and
@ -80,15 +80,15 @@ owner as "Not a Contribution."
of whom a Contribution has been received by Licensor and subsequently incorporated
within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of this
2. Grant of Copyright License. Subject to the terms and conditions of that
License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive,
no-charge, royalty-free, irrevocable copyright license to reproduce, prepare
Derivative Works of, publicly display, publicly perform, sublicense, and distribute
the Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of this License,
3. Grant of Patent License. Subject to the terms and conditions of that License,
each Contributor hereby grants to You a perpetual, worldwide, non-exclusive,
no-charge, royalty-free, irrevocable (except as stated in this section) patent
no-charge, royalty-free, irrevocable (except as stated in that section) patent
license to make, have made, use, offer to sell, sell, import, and otherwise
transfer the Work, where such license applies only to those patent claims
licensable by such Contributor that are necessarily infringed by their Contribution(s)
@ -97,7 +97,7 @@ Contribution(s) was submitted. If You institute patent litigation against
any entity (including a cross-claim or counterclaim in a lawsuit) alleging
that the Work or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses granted to You
under this License for that Work shall terminate as of the date such litigation
under that License for that Work shall terminate as of the date such litigation
is filed.
4. Redistribution. You may reproduce and distribute copies of the Work or
@ -105,7 +105,7 @@ Derivative Works thereof in any medium, with or without modifications, and
in Source or Object form, provided that You meet the following conditions:
(a) You must give any other recipients of the Work or Derivative Works a copy
of this License; and
of that License; and
(b) You must cause any modified files to carry prominent notices stating that
You changed the files; and
@ -133,11 +133,11 @@ You may add Your own copyright statement to Your modifications and may provide
additional or different license terms and conditions for use, reproduction,
or distribution of Your modifications, or for any such Derivative Works as
a whole, provided Your use, reproduction, and distribution of the Work otherwise
complies with the conditions stated in this License.
complies with the conditions stated in that License.
5. Submission of Contributions. Unless You explicitly state otherwise, any
Contribution intentionally submitted for inclusion in the Work by You to the
Licensor shall be under the terms and conditions of this License, without
Licensor shall be under the terms and conditions of that License, without
any additional terms or conditions. Notwithstanding the above, nothing herein
shall supersede or modify the terms of any separate license agreement you
may have executed with Licensor regarding such Contributions.
@ -154,14 +154,14 @@ KIND, either express or implied, including, without limitation, any warranties
or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR
A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness
of using or redistributing the Work and assume any risks associated with Your
exercise of permissions under this License.
exercise of permissions under that License.
8. Limitation of Liability. In no event and under no legal theory, whether
in tort (including negligence), contract, or otherwise, unless required by
applicable law (such as deliberate and grossly negligent acts) or agreed to
in writing, shall any Contributor be liable to You for damages, including
any direct, indirect, special, incidental, or consequential damages of any
character arising as a result of this License or out of the use or inability
character arising as a result of that License or out of the use or inability
to use the Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all other commercial
damages or losses), even if such Contributor has been advised of the possibility
@ -170,7 +170,7 @@ of such damages.
9. Accepting Warranty or Additional Liability. While redistributing the Work
or Derivative Works thereof, You may choose to offer, and charge a fee for,
acceptance of support, warranty, indemnity, or other liability obligations
and/or rights consistent with this License. However, in accepting such obligations,
and/or rights consistent with that License. However, in accepting such obligations,
You may act only on Your own behalf and on Your sole responsibility, not on
behalf of any other Contributor, and only if You agree to indemnify, defend,
and hold each Contributor harmless for any liability incurred by, or claims
@ -191,7 +191,7 @@ Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
you may not use that file except in compliance with the License.
You may obtain a copy of the License at

View File

@ -4,6 +4,7 @@ import (
. "./cache"
. "./common"
. "./db"
. "./log"
"bytes"
"database/sql"
"encoding/json"
@ -21,7 +22,8 @@ type Application struct {
MethodRouter
Router
ContextBase
Log logrus.Logger
Log *logrus.Logger
WebConnectLog *logrus.Logger
Port string //端口号
TLSPort string //ssl访问端口号
connectListener []func(this *Context) bool //所有的访问监听,true按原计划继续使用false表示有监听器处理
@ -29,44 +31,44 @@ type Application struct {
configPath string
Config Map
Db HoTimeDB
Server *http.Server
*http.Server
CacheIns
sessionLong CacheIns
sessionShort CacheIns
http.Handler
}
func (this *Application) ServeHTTP(w http.ResponseWriter, req *http.Request) {
this.handler(w, req)
func (that *Application) ServeHTTP(w http.ResponseWriter, req *http.Request) {
that.handler(w, req)
}
//启动实例
func (this *Application) Run(router Router) {
// Run 启动实例
func (that *Application) Run(router Router) {
//如果没有设置配置自动生成配置
if this.configPath == "" || len(this.Config) == 0 {
this.SetConfig()
if that.configPath == "" || len(that.Config) == 0 {
that.SetConfig()
}
//防止手动设置缓存误伤
if this.CacheIns == nil {
this.SetCache(CacheIns(&CacheMemory{}))
if that.CacheIns == nil {
that.SetCache(CacheIns(&CacheMemory{}))
}
//防止手动设置session误伤
//if this.sessionShort == nil && this.sessionLong == nil {
// if this.connectDbFunc == nil {
// this.SetSession(CacheIns(&CacheMemory{}), nil)
//if that.sessionShort == nil && that.sessionLong == nil {
// if that.connectDbFunc == nil {
// that.SetSession(CacheIns(&CacheMemory{}), nil)
// } else {
// this.SetSession(CacheIns(&CacheMemory{}), CacheIns(&CacheDb{Db: &this.Db, Time: this.Config.GetInt64("cacheLongTime")}))
// that.SetSession(CacheIns(&CacheMemory{}), CacheIns(&CacheDb{Db: &that.Db, Time: that.Config.GetInt64("cacheLongTime")}))
// }
//
//}
this.Router = router
that.Router = router
//重新设置MethodRouter//直达路由
this.MethodRouter = MethodRouter{}
that.MethodRouter = MethodRouter{}
modeRouterStrict := true
if this.Config.Get("modeRouterStrict").(bool) == false {
if that.Config.GetBool("modeRouterStrict") == false {
modeRouterStrict = false
}
if router != nil {
@ -84,7 +86,7 @@ func (this *Application) Run(router Router) {
if !modeRouterStrict {
mk = strings.ToLower(mk)
}
this.MethodRouter["/"+pk+"/"+ck+"/"+mk] = mv
that.MethodRouter["/"+pk+"/"+ck+"/"+mk] = mv
}
}
}
@ -92,137 +94,139 @@ func (this *Application) Run(router Router) {
}
}
//this.Port = port
this.Port = this.Config.GetString("port")
this.TLSPort = this.Config.GetString("tlsPort")
//that.Port = port
that.Port = that.Config.GetString("port")
that.TLSPort = that.Config.GetString("tlsPort")
if this.connectDbFunc != nil && (this.Db.DB == nil || this.Db.DB.Ping() != nil) {
this.Db.SetConnect(this.connectDbFunc)
if that.connectDbFunc != nil && (that.Db.DB == nil || that.Db.DB.Ping() != nil) {
that.Db.SetConnect(that.connectDbFunc)
}
if this.CacheIns == nil {
this.CacheIns = CacheIns(&CacheMemory{Map: Map{}, Time: this.Config.GetInt64("cacheShortTime")})
if that.CacheIns == nil {
that.CacheIns = CacheIns(&CacheMemory{Map: Map{}, Time: that.Config.GetInt64("cacheShortTime")})
}
//异常处理
defer func() {
if err := recover(); err != nil {
//this.SetError(errors.New(fmt.Sprint(err)), LOG_FMT)
LogFmt(err, 2, LOG_ERROR)
//that.SetError(errors.New(fmt.Sprint(err)), LOG_FMT)
that.Log.Warn(err)
this.Run(router)
that.Run(router)
}
}()
this.Server = &http.Server{}
that.Server = &http.Server{}
if !IsRun {
IsRun = true
}
ch := make(chan int)
if ObjToCeilInt(this.Port) != 0 {
if ObjToCeilInt(that.Port) != 0 {
go func() {
App[this.Port] = this
this.Server.Handler = this
App[that.Port] = that
that.Server.Handler = that
//启动服务
this.Server.Addr = ":" + this.Port
err := this.Server.ListenAndServe()
LogFmt(err, 2)
that.Server.Addr = ":" + that.Port
err := that.Server.ListenAndServe()
that.Log.Error(err)
ch <- 1
}()
}
if ObjToCeilInt(this.TLSPort) != 0 {
if ObjToCeilInt(that.TLSPort) != 0 {
go func() {
App[this.TLSPort] = this
this.Server.Handler = this
App[that.TLSPort] = that
that.Server.Handler = that
//启动服务
this.Server.Addr = ":" + this.TLSPort
err := this.Server.ListenAndServeTLS(this.Config.GetString("tlsCert"), this.Config.GetString("tlsKey"))
LogFmt(err, 2)
that.Server.Addr = ":" + that.TLSPort
err := that.Server.ListenAndServeTLS(that.Config.GetString("tlsCert"), that.Config.GetString("tlsKey"))
that.Log.Error(err)
ch <- 2
}()
}
if ObjToCeilInt(this.Port) == 0 && ObjToCeilInt(this.TLSPort) == 0 {
LogFmt("没有端口启用", 2, LOG_INFO)
if ObjToCeilInt(that.Port) == 0 && ObjToCeilInt(that.TLSPort) == 0 {
that.Log.Error("没有端口启用")
return
}
value := <-ch
LogFmt("启动服务失败 : "+ObjToStr(value), 2, LOG_ERROR)
that.Log.Error("启动服务失败 : " + ObjToStr(value))
}
//启动实例
func (this *Application) SetConnectDB(connect func(err ...*Error) (master, slave *sql.DB)) {
// SetConnectDB 启动实例
func (that *Application) SetConnectDB(connect func(err ...*Error) (master, slave *sql.DB)) {
this.connectDbFunc = connect
this.Db.SetConnect(this.connectDbFunc)
that.connectDbFunc = connect
that.Db.SetConnect(that.connectDbFunc)
}
//设置配置文件路径全路径或者相对路径
func (this *Application) SetSession(short CacheIns, Long CacheIns) {
this.sessionLong = Long
this.sessionShort = short
// SetSession 设置配置文件路径全路径或者相对路径
func (that *Application) SetSession(short CacheIns, Long CacheIns) {
that.sessionLong = Long
that.sessionShort = short
}
//默认配置缓存和session实现
func (this *Application) SetDefault(connect func(err ...*Error) (*sql.DB, *sql.DB)) {
this.SetConfig()
// SetDefault 默认配置缓存和session实现
func (that *Application) SetDefault(connect func(err ...*Error) (*sql.DB, *sql.DB)) {
that.SetConfig()
if connect != nil {
this.connectDbFunc = connect
this.Db.SetConnect(this.connectDbFunc)
that.connectDbFunc = connect
that.Db.SetConnect(that.connectDbFunc)
}
}
//设置配置文件路径全路径或者相对路径
func (this *Application) SetCache(cache CacheIns) {
// SetCache 设置配置文件路径全路径或者相对路径
func (that *Application) SetCache(cache CacheIns) {
this.CacheIns = cache
that.CacheIns = cache
}
//设置配置文件路径全路径或者相对路径
func (this *Application) SetConfig(configPath ...string) {
// SetConfig 设置配置文件路径全路径或者相对路径
func (that *Application) SetConfig(configPath ...string) {
that.Log = GetLog("", true)
if len(configPath) != 0 {
this.configPath = configPath[0]
that.configPath = configPath[0]
}
if this.configPath == "" {
this.configPath = "config/config.json"
if that.configPath == "" {
that.configPath = "config/config.json"
}
//加载配置文件
btes, err := ioutil.ReadFile(this.configPath)
this.Config = DeepCopyMap(Config).(Map)
btes, err := ioutil.ReadFile(that.configPath)
that.Config = DeepCopyMap(Config).(Map)
if err == nil {
cmap := Map{}
//文件是否损坏
cmap.JsonToMap(string(btes), &this.Error)
cmap.JsonToMap(string(btes), &that.Error)
for k, v := range cmap {
this.Config[k] = v //程序配置
that.Config[k] = v //程序配置
Config[k] = v //系统配置
}
} else {
LogFmt("配置文件不存在,或者配置出错,使用缺省默认配置", 2)
that.Log.Error("配置文件不存在,或者配置出错,使用缺省默认配置")
}
//文件如果损坏则不写入配置防止配置文件数据丢失
if this.Error.GetError() == nil {
if that.Error.GetError() == nil {
var configByte bytes.Buffer
err = json.Indent(&configByte, []byte(this.Config.ToJsonString()), "", "\t")
err = json.Indent(&configByte, []byte(that.Config.ToJsonString()), "", "\t")
//判断配置文件是否序列有变化有则修改配置,五则不变
//fmt.Println(len(btes))
if len(btes) != 0 && configByte.String() == string(btes) {
@ -230,22 +234,26 @@ func (this *Application) SetConfig(configPath ...string) {
}
//写入配置说明
var configNoteByte bytes.Buffer
json.Indent(&configNoteByte, []byte(ConfigNote.ToJsonString()), "", "\t")
_ = json.Indent(&configNoteByte, []byte(ConfigNote.ToJsonString()), "", "\t")
os.MkdirAll(filepath.Dir(this.configPath), os.ModeDir)
err = ioutil.WriteFile(this.configPath, configByte.Bytes(), os.ModeAppend)
_ = os.MkdirAll(filepath.Dir(that.configPath), os.ModeDir)
err = ioutil.WriteFile(that.configPath, configByte.Bytes(), os.ModeAppend)
if err != nil {
this.Error.SetError(err)
that.Error.SetError(err)
}
ioutil.WriteFile(filepath.Dir(this.configPath)+"/confignote.json", configNoteByte.Bytes(), os.ModeAppend)
_ = ioutil.WriteFile(filepath.Dir(that.configPath)+"/configNote.json", configNoteByte.Bytes(), os.ModeAppend)
}
that.Log = GetLog(that.Config.GetString("logFile"), true)
if that.Config.GetBool("webConnectLogShow") {
that.WebConnectLog = GetLog(that.Config.GetString("webConnectLogFile"), false)
}
}
//连接判断,返回true继续传输至控制层false则停止传输
func (this *Application) SetConnectListener(lis func(this *Context) bool) {
this.connectListener = append(this.connectListener, lis)
// SetConnectListener 连接判断,返回true继续传输至控制层false则停止传输
func (that *Application) SetConnectListener(lis func(this *Context) bool) {
that.connectListener = append(that.connectListener, lis)
}
//网络错误
@ -254,7 +262,7 @@ func (this *Application) SetConnectListener(lis func(this *Context) bool) {
//}
//序列化链接
func (this *Application) urlSer(url string) (string, []string) {
func (that *Application) urlSer(url string) (string, []string) {
q := strings.Index(url, "?")
if q == -1 {
q = len(url)
@ -275,9 +283,9 @@ func (this *Application) urlSer(url string) (string, []string) {
//访问
func (this *Application) handler(w http.ResponseWriter, req *http.Request) {
func (that *Application) handler(w http.ResponseWriter, req *http.Request) {
_, s := this.urlSer(req.RequestURI)
_, s := that.urlSer(req.RequestURI)
//获取cookie
// 如果cookie存在直接将sessionId赋值为cookie.Value
// 如果cookie不存在就查找传入的参数中是否有token
@ -285,7 +293,7 @@ func (this *Application) handler(w http.ResponseWriter, req *http.Request) {
// 如果token存在就判断token是否在Session中有保存
// 如果有取出token并复制给cookie
// 没有保存就生成随机的session
cookie, err := req.Cookie(this.Config.GetString("sessionName"))
cookie, err := req.Cookie(that.Config.GetString("sessionName"))
sessionId := Md5(strconv.Itoa(Rand(10)))
token := req.FormValue("token")
//isFirst:=false
@ -296,7 +304,7 @@ func (this *Application) handler(w http.ResponseWriter, req *http.Request) {
//else{
// isFirst=true;
//}
http.SetCookie(w, &http.Cookie{Name: this.Config.GetString("sessionName"), Value: sessionId, Path: "/"})
http.SetCookie(w, &http.Cookie{Name: that.Config.GetString("sessionName"), Value: sessionId, Path: "/"})
} else {
sessionId = cookie.Value
}
@ -307,31 +315,31 @@ func (this *Application) handler(w http.ResponseWriter, req *http.Request) {
}
//访问实例
context := Context{SessionIns: SessionIns{SessionId: sessionId,
LongCache: this.sessionLong,
ShortCache: this.sessionShort,
LongCache: that.sessionLong,
ShortCache: that.sessionShort,
},
CacheIns: this.CacheIns,
Resp: w, Req: req, Application: this, RouterString: s, Config: this.Config, Db: &this.Db, HandlerStr: unescapeUrl}
CacheIns: that.CacheIns,
Resp: w, Req: req, Application: that, RouterString: s, Config: that.Config, Db: &that.Db, HandlerStr: unescapeUrl}
//header默认设置
header := w.Header()
header.Set("Content-Type", "text/html; charset=utf-8")
//url去掉参数并序列化
context.HandlerStr, context.RouterString = this.urlSer(context.HandlerStr)
context.HandlerStr, context.RouterString = that.urlSer(context.HandlerStr)
//跨域设置
this.crossDomain(&context)
that.crossDomain(&context)
//是否展示日志
if this.Config.GetInt("connectLogShow") != 0 {
LogFmt(Substr(context.Req.RemoteAddr, 0, strings.Index(context.Req.RemoteAddr, ":"))+" "+context.HandlerStr, 0, LOG_INFO)
if that.WebConnectLog != nil {
that.WebConnectLog.Infoln(Substr(context.Req.RemoteAddr, 0, strings.Index(context.Req.RemoteAddr, ":")) + " " + context.HandlerStr)
}
//访问拦截true继续false暂停
connectListenerLen := len(this.connectListener)
connectListenerLen := len(that.connectListener)
if connectListenerLen != 0 {
for i := 0; i < connectListenerLen; i++ {
if !this.connectListener[i](&context) {
if !that.connectListener[i](&context) {
context.View()
return
@ -342,9 +350,9 @@ func (this *Application) handler(w http.ResponseWriter, req *http.Request) {
//接口服务
//if len(s) == 3 {
// //如果满足规则则路由到对应控制器去
// if this.Router[s[0]] != nil && this.Router[s[0]][s[1]] != nil && this.Router[s[0]][s[1]][s[2]] != nil {
// if that.Router[s[0]] != nil && that.Router[s[0]][s[1]] != nil && that.Router[s[0]][s[1]][s[2]] != nil {
// //控制层
// this.Router[s[0]][s[1]][s[2]](&context)
// that.Router[s[0]][s[1]][s[2]](&context)
// //header.Set("Content-Type", "text/html; charset=utf-8")
// context.View()
// return
@ -352,25 +360,25 @@ func (this *Application) handler(w http.ResponseWriter, req *http.Request) {
//
//}
//验证接口严格模式
modeRouterStrict := this.Config.Get("modeRouterStrict").(bool)
modeRouterStrict := that.Config.GetBool("modeRouterStrict")
tempHandlerStr := context.HandlerStr
if !modeRouterStrict {
tempHandlerStr = strings.ToLower(tempHandlerStr)
}
//执行接口
if this.MethodRouter[tempHandlerStr] != nil {
this.MethodRouter[tempHandlerStr](&context)
if that.MethodRouter[tempHandlerStr] != nil {
that.MethodRouter[tempHandlerStr](&context)
context.View()
return
}
//url赋值
path := this.Config.GetString("tpt") + tempHandlerStr
path := that.Config.GetString("tpt") + tempHandlerStr
//判断是否为默认
if path[len(path)-1] == '/' {
defFile := this.Config.GetSlice("defFile")
defFile := that.Config.GetSlice("defFile")
for i := 0; i < len(defFile); i++ {
temp := path + defFile.GetString(i)
@ -394,7 +402,7 @@ func (this *Application) handler(w http.ResponseWriter, req *http.Request) {
//设置header
delete(header, "Content-Type")
if this.Config.GetInt("debug") != 1 {
if that.Config.GetInt("debug") != 1 {
header.Set("Cache-Control", "public")
}
@ -407,7 +415,7 @@ func (this *Application) handler(w http.ResponseWriter, req *http.Request) {
}
func (this *Application) crossDomain(context *Context) {
func (that *Application) crossDomain(context *Context) {
//没有跨域设置
if context.Config.GetString("crossDomain") == "" {
return
@ -421,7 +429,7 @@ func (this *Application) crossDomain(context *Context) {
header.Set("Access-Control-Allow-Headers", "X-Requested-With,Content-Type,Access-Token")
if context.Config.GetString("crossDomain") != "auto" {
header.Set("Access-Control-Allow-Origin", this.Config.GetString("crossDomain"))
header.Set("Access-Control-Allow-Origin", that.Config.GetString("crossDomain"))
return
}
@ -450,6 +458,7 @@ func (this *Application) crossDomain(context *Context) {
}
}
//Init 初始化application
func Init(config string) Application {
appIns := Application{}
//手动模式,
@ -459,7 +468,7 @@ func Init(config string) Application {
return appIns
}
//后期整改
// SetDB 智能数据库设置
func SetDB(appIns *Application) {
db := appIns.Config.GetMap("db")
dbSqlite := db.GetMap("sqlite")

View File

@ -1,16 +0,0 @@
package common
type LOG_MODE int
const (
LOG_NIL = 0
LOG_FMT = 1
//LOG_FILE = 2
LOG_INFO LOG_MODE = 0
LOG_WARN LOG_MODE = 1
LOG_ERROR LOG_MODE = 2
)
//session储存头
const HEAD_SESSION_ADD = "session#"

View File

@ -1,17 +1,19 @@
package common
import "time"
import (
"time"
)
type ContextBase struct {
Error
tag int64
tag string
}
//唯一标志
func (this *ContextBase) GetTag() int64 {
func (this *ContextBase) GetTag() string {
if this.tag == int64(0) {
this.tag = time.Now().UnixNano()
if this.tag == "" {
this.tag = ObjToStr(time.Now().Unix()) + ":" + ObjToStr(Random())
}
return this.tag
}

View File

@ -1,25 +1,17 @@
package common
//框架层处理错误
// Error 框架层处理错误
type Error struct {
error
err error
}
func (this *Error) GetError() error {
func (that *Error) GetError() error {
return this.error
return that.error
}
func (this *Error) SetError(err error, loglevel ...int) {
this.error = nil
if err == nil {
this.error = err
this.err = err
return
}
this.error = err
func (that *Error) SetError(err error) {
that.error = err
return
}

View File

@ -3,7 +3,6 @@ package common
import (
"crypto/md5"
"encoding/hex"
"fmt"
"math"
"strings"
)
@ -25,86 +24,6 @@ import (
// return res
//}
//func LogError(logMsg interface{}) {
//
// logFmt(fmt.Sprintln(logMsg), 2, LOG_ERROR)
//}
//func LogWarn(logMsg interface{}) {
//
// logFmt(fmt.Sprintln(logMsg), 2, LOG_WARN)
//}
//func LogInfo(logMsg ...interface{}) {
//
// logFmt(fmt.Sprintln(logMsg), 2, LOG_INFO)
//}
//
//func LogFmt(logMsg interface{}, loglevel ...LOG_MODE) {
//
// logFmt(logMsg, 2, loglevel...)
//}
//
////日志打印以及存储到文件
//func logFmt(logMsg interface{}, printLevel int, loglevel ...LOG_MODE) {
//
// if Config.GetInt("logLevel") == int(LOG_NIL) {
// return
// }
//
// lev := LOG_INFO
// if len(loglevel) != 0 {
// lev = loglevel[0]
// }
// gofile := ""
//
// if Config.GetInt("debug") != 0 && printLevel != 0 {
// _, file, line, ok := runtime.Caller(printLevel)
// if ok {
// gofile = " " + file + ":" + ObjToStr(line)
// }
// }
//
// logStr := ""
//
// if lev == LOG_INFO {
// logStr = "info:"
// }
// if printLevel == 0 {
// logStr = "connect:"
// }
//
// if lev == LOG_WARN {
// logStr = "warn:"
// }
//
// if lev == LOG_ERROR {
// logStr = "error:"
// }
//
// logStr = fmt.Sprintln(time.Now().Format("2006/01/02 15:04:05"), logStr, logMsg, gofile)
// //打印日志
// fmt.Print(logStr)
// //不需要存储到文件
// if Config.GetString("logFile") == "" {
// return
// }
// //存储到文件
// logFilePath := time.Now().Format(Config.GetString("logFile"))
//
// os.MkdirAll(filepath.Dir(logFilePath), os.ModeAppend)
// //os.Create(logFilePath)
// f, err := os.OpenFile(logFilePath, os.O_APPEND|os.O_CREATE, 0644)
// if err != nil {
// return
// }
// f.Write([]byte(logStr))
// f.Close()
//
//}
//日志打印以及存储到文件
func LogFmt(logMsg interface{}, printLevel int, loglevel ...LOG_MODE) {
fmt.Println(logMsg)
}
//字符串首字符大写
func StrFirstToUpper(str string) string {
if len(str) == 0 {

View File

@ -6,79 +6,79 @@ import (
type Slice []interface{}
//获取string
func (this Slice) GetString(key int, err ...*Error) string {
// GetString 获取string
func (that Slice) GetString(key int, err ...*Error) string {
if len(err) != 0 {
err[0].SetError(nil)
}
return ObjToStr((this)[key])
return ObjToStr((that)[key])
}
//获取Int
func (this Slice) GetInt(key int, err ...*Error) int {
v := ObjToInt((this)[key], err...)
// GetInt 获取Int
func (that Slice) GetInt(key int, err ...*Error) int {
v := ObjToInt((that)[key], err...)
return v
}
//获取Int
func (this Slice) GetInt64(key int, err ...*Error) int64 {
v := ObjToInt64((this)[key], err...)
// GetInt64 获取Int
func (that Slice) GetInt64(key int, err ...*Error) int64 {
v := ObjToInt64((that)[key], err...)
return v
}
//获取向上取整Int64
func (this Slice) GetCeilInt64(key int, err ...*Error) int64 {
v := ObjToCeilInt64((this)[key], err...)
// GetCeilInt64 获取向上取整Int64
func (that Slice) GetCeilInt64(key int, err ...*Error) int64 {
v := ObjToCeilInt64((that)[key], err...)
return v
}
//获取向上取整Int
func (this Slice) GetCeilInt(key int, err ...*Error) int {
v := ObjToCeilInt((this)[key], err...)
// GetCeilInt 获取向上取整Int
func (that Slice) GetCeilInt(key int, err ...*Error) int {
v := ObjToCeilInt((that)[key], err...)
return v
}
//获取向上取整float64
func (this Slice) GetCeilFloat64(key int, err ...*Error) float64 {
v := ObjToCeilFloat64((this)[key], err...)
// GetCeilFloat64 获取向上取整float64
func (that Slice) GetCeilFloat64(key int, err ...*Error) float64 {
v := ObjToCeilFloat64((that)[key], err...)
return v
}
//获取Float64
func (this Slice) GetFloat64(key int, err ...*Error) float64 {
v := ObjToFloat64((this)[key], err...)
// GetFloat64 获取Float64
func (that Slice) GetFloat64(key int, err ...*Error) float64 {
v := ObjToFloat64((that)[key], err...)
return v
}
func (this Slice) GetSlice(key int, err ...*Error) Slice {
v := ObjToSlice((this)[key], err...)
func (that Slice) GetSlice(key int, err ...*Error) Slice {
v := ObjToSlice((that)[key], err...)
return v
}
func (this Slice) GetBool(key int, err ...*Error) bool {
func (that Slice) GetBool(key int, err ...*Error) bool {
//var v Slice
v := ObjToBool((this)[key], err...)
v := ObjToBool((that)[key], err...)
return v
}
func (this Slice) GetMap(key int, err ...*Error) Map {
func (that Slice) GetMap(key int, err ...*Error) Map {
//var v Map
v := ObjToMap((this)[key], err...)
v := ObjToMap((that)[key], err...)
return v
}
func (this Slice) Get(key int, err ...*Error) interface{} {
func (that Slice) Get(key int, err ...*Error) interface{} {
if key < len(this) {
return this[key]
if key < len(that) {
return that[key]
}
e := errors.New("没有存储key及对应的数据")
if len(err) != 0 {
@ -87,10 +87,10 @@ func (this Slice) Get(key int, err ...*Error) interface{} {
return nil
}
func (this Slice) Put(key int, value interface{}) {
this[key] = value
func (that Slice) Put(key int, value interface{}) {
that[key] = value
}
func (this Slice) ToJsonString() string {
return ObjToStr(this)
func (that Slice) ToJsonString() string {
return ObjToStr(that)
}

4
const.go Normal file
View File

@ -0,0 +1,4 @@
package hotime
//session储存头
const HEAD_SESSION_ADD = "session#"

View File

@ -9,10 +9,10 @@ import (
)
type Context struct {
*Application
ContextBase
Resp http.ResponseWriter
Req *http.Request
Application *Application
RouterString []string
Config Map
Db *HoTimeDB
@ -22,22 +22,22 @@ type Context struct {
HandlerStr string //复写请求url
}
//唯一标志
func (this *Context) Mtd(router [3]string) Map {
this.Application.Router[router[0]][router[1]][router[2]](this)
d := this.RespData
this.RespData = nil
// Mtd 唯一标志
func (that *Context) Mtd(router [3]string) Map {
that.Application.Router[router[0]][router[1]][router[2]](that)
d := that.RespData
that.RespData = nil
return d
}
//打印
func (this *Context) Display(statu int, data interface{}) {
func (that *Context) Display(statu int, data interface{}) {
resp := Map{"statu": statu}
if statu != 0 {
temp := Map{}
tpe := this.Config.GetMap("error").GetString(ObjToStr(statu))
tpe := that.Config.GetMap("error").GetString(ObjToStr(statu))
if tpe == "" {
//logFmt(errors.New("找不到对应的错误码"), 2, LOG_WARN)
}
@ -49,19 +49,19 @@ func (this *Context) Display(statu int, data interface{}) {
resp["result"] = data
}
this.RespData = resp
that.RespData = resp
//this.Data=d;
//that.Data=d;
}
func (this *Context) View() {
if this.RespData == nil {
func (that *Context) View() {
if that.RespData == nil {
return
}
d, err := json.Marshal(this.RespData)
d, err := json.Marshal(that.RespData)
if err != nil {
return
}
this.RespData = nil
this.Resp.Write(d)
that.RespData = nil
that.Resp.Write(d)
}

267
db/db.go
View File

@ -22,27 +22,28 @@ type HoTimeDB struct {
ConnectFunc func(err ...*Error) (*sql.DB, *sql.DB)
LastErr Error
limit Slice
Tx *sql.Tx //事务对象
*sql.Tx //事务对象
SlaveDB *sql.DB
}
//设置数据库配置连接
func (this *HoTimeDB) SetConnect(connect func(err ...*Error) (master, slave *sql.DB), err ...*Error) {
this.ConnectFunc = connect
this.InitDb()
// SetConnect 设置数据库配置连接
func (that *HoTimeDB) SetConnect(connect func(err ...*Error) (master, slave *sql.DB), err ...*Error) {
that.ConnectFunc = connect
_ = that.InitDb(err...)
}
//设置数据库配置连接
func (this *HoTimeDB) GetType() string {
return this.Type
// GetType 设置数据库配置连接
func (that *HoTimeDB) GetType() string {
return that.Type
}
//事务如果action返回true则执行成功false则回滚
func (this *HoTimeDB) Action(action func(db HoTimeDB) bool) bool {
db := HoTimeDB{DB: this.DB, CacheIns: this.CacheIns, DBCached: this.DBCached}
// Action 事务如果action返回true则执行成功false则回滚
func (that *HoTimeDB) Action(action func(db HoTimeDB) bool) bool {
db := HoTimeDB{DB: that.DB, CacheIns: that.CacheIns, DBCached: that.DBCached}
tx, err := db.Begin()
if err != nil {
this.LastErr.SetError(err)
that.LastErr.SetError(err)
return false
}
@ -51,66 +52,74 @@ func (this *HoTimeDB) Action(action func(db HoTimeDB) bool) bool {
result := action(db)
if !result {
db.Tx.Rollback()
err = db.Tx.Rollback()
if err != nil {
that.LastErr.SetError(err)
return false
}
return result
}
db.Tx.Commit()
err = db.Tx.Commit()
if err != nil {
that.LastErr.SetError(err)
return false
}
return result
}
func (this *HoTimeDB) InitDb(err ...*Error) Error {
func (that *HoTimeDB) InitDb(err ...*Error) Error {
if len(err) != 0 {
this.LastErr = *(err[0])
that.LastErr = *(err[0])
}
this.DB, this.SlaveDB = this.ConnectFunc(&this.LastErr)
if this.DB == nil {
return this.LastErr
that.DB, that.SlaveDB = that.ConnectFunc(&that.LastErr)
if that.DB == nil {
return that.LastErr
}
e := this.DB.Ping()
e := that.DB.Ping()
this.LastErr.SetError(e)
that.LastErr.SetError(e)
if this.SlaveDB != nil {
e := this.SlaveDB.Ping()
this.LastErr.SetError(e)
if that.SlaveDB != nil {
e := that.SlaveDB.Ping()
that.LastErr.SetError(e)
}
return this.LastErr
return that.LastErr
}
func (this *HoTimeDB) Page(page, pageRow int) *HoTimeDB {
func (that *HoTimeDB) Page(page, pageRow int) *HoTimeDB {
page = (page - 1) * pageRow
if page < 0 {
page = 1
}
this.limit = Slice{page, pageRow}
return this
that.limit = Slice{page, pageRow}
return that
}
func (this *HoTimeDB) PageSelect(table string, qu ...interface{}) []Map {
func (that *HoTimeDB) PageSelect(table string, qu ...interface{}) []Map {
if len(qu) == 1 {
qu = append(qu, Map{"LIMIT": this.limit})
qu = append(qu, Map{"LIMIT": that.limit})
}
if len(qu) == 2 {
temp := qu[1].(Map)
temp["LIMIT"] = this.limit
temp["LIMIT"] = that.limit
qu[1] = temp
}
if len(qu) == 3 {
temp := qu[2].(Map)
temp["LIMIT"] = this.limit
temp["LIMIT"] = that.limit
qu[2] = temp
}
//fmt.Println(qu)
data := this.Select(table, qu...)
data := that.Select(table, qu...)
return data
}
//数据库数据解析
func (this *HoTimeDB) Row(resl *sql.Rows) []Map {
// Row 数据库数据解析
func (that *HoTimeDB) Row(resl *sql.Rows) []Map {
dest := make([]Map, 0)
strs, _ := resl.Columns()
@ -122,7 +131,11 @@ func (this *HoTimeDB) Row(resl *sql.Rows) []Map {
for j := 0; j < len(a); j++ {
b[j] = &a[j]
}
resl.Scan(b...)
err := resl.Scan(b...)
if err != nil {
that.LastErr.SetError(err)
return nil
}
for j := 0; j < len(a); j++ {
if a[j] != nil && reflect.ValueOf(a[j]).Type().String() == "[]uint8" {
lis[strs[j]] = string(a[j].([]byte))
@ -134,9 +147,9 @@ func (this *HoTimeDB) Row(resl *sql.Rows) []Map {
//防止int被误读为float64
jlis, e := json.Marshal(lis)
if e != nil {
this.LastErr.SetError(e)
that.LastErr.SetError(e)
} else {
lis.JsonToMap(string(jlis), &this.LastErr)
lis.JsonToMap(string(jlis), &that.LastErr)
}
dest = append(dest, lis)
@ -201,25 +214,25 @@ func (this *HoTimeDB) Row(resl *sql.Rows) []Map {
//
//}
func (this *HoTimeDB) backupSave(path string, tt string, code int) {
func (that *HoTimeDB) backupSave(path string, tt string, code int) {
fd, _ := os.OpenFile(path, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0644)
defer fd.Close()
str := "\r\n"
if code == 0 || code == 2 {
str += this.backupDdl(tt)
str += that.backupDdl(tt)
}
if code == 0 || code == 1 {
str += "insert into `" + tt + "`\r\n\r\n("
str += this.backupCol(tt)
str += that.backupCol(tt)
}
fd.Write([]byte(str))
_, _ = fd.Write([]byte(str))
}
func (this *HoTimeDB) backupDdl(tt string) string {
func (that *HoTimeDB) backupDdl(tt string) string {
data := this.Query("show create table " + tt)
data := that.Query("show create table " + tt)
if len(data) == 0 {
return ""
}
@ -227,9 +240,9 @@ func (this *HoTimeDB) backupDdl(tt string) string {
return ObjToStr(data[0]["Create Table"]) + ";\r\n\r\n"
}
func (this *HoTimeDB) backupCol(tt string) string {
func (that *HoTimeDB) backupCol(tt string) string {
str := ""
data := this.Select(tt, "*")
data := that.Select(tt, "*")
lthData := len(data)
@ -239,7 +252,7 @@ func (this *HoTimeDB) backupCol(tt string) string {
lthCol := len(data[0])
col := make([]string, lthCol)
tempLthData := 0
for k, _ := range data[0] {
for k := range data[0] {
if tempLthData == lthCol-1 {
str += "`" + k + "`)"
@ -281,89 +294,89 @@ func (this *HoTimeDB) backupCol(tt string) string {
return str
}
func (this *HoTimeDB) md5(query string, args ...interface{}) string {
func (that *HoTimeDB) md5(query string, args ...interface{}) string {
strByte, _ := json.Marshal(args)
str := Md5(query + ":" + string(strByte))
return str
}
func (this *HoTimeDB) Query(query string, args ...interface{}) []Map {
func (that *HoTimeDB) Query(query string, args ...interface{}) []Map {
//fmt.Println(query)
var err error
var resl *sql.Rows
this.LastQuery = query
this.LastData = args
that.LastQuery = query
that.LastData = args
//主从数据库切换只有select语句有从数据库
db := this.DB
if this.SlaveDB != nil {
db = this.SlaveDB
db := that.DB
if that.SlaveDB != nil {
db = that.SlaveDB
}
if db == nil {
err = errors.New("没有初始化数据库")
this.LastErr.SetError(err)
that.LastErr.SetError(err)
return nil
}
if this.Tx != nil {
resl, err = this.Tx.Query(query, args...)
if that.Tx != nil {
resl, err = that.Tx.Query(query, args...)
} else {
resl, err = db.Query(query, args...)
}
this.LastErr.SetError(err)
that.LastErr.SetError(err)
if err != nil {
if err = db.Ping(); err != nil {
this.LastErr.SetError(err)
this.InitDb()
if this.LastErr.GetError() != nil {
that.LastErr.SetError(err)
_ = that.InitDb()
if that.LastErr.GetError() != nil {
return nil
}
return this.Query(query, args...)
return that.Query(query, args...)
}
return nil
}
return this.Row(resl)
return that.Row(resl)
}
func (this *HoTimeDB) Exec(query string, args ...interface{}) (sql.Result, Error) {
func (that *HoTimeDB) Exec(query string, args ...interface{}) (sql.Result, Error) {
this.LastQuery = query
this.LastData = args
that.LastQuery = query
that.LastData = args
var e error
var resl sql.Result
if this.DB == nil {
if that.DB == nil {
err := errors.New("没有初始化数据库")
this.LastErr.SetError(err)
return nil, this.LastErr
that.LastErr.SetError(err)
return nil, that.LastErr
}
if this.Tx != nil {
resl, e = this.Tx.Exec(query, args...)
if that.Tx != nil {
resl, e = that.Tx.Exec(query, args...)
} else {
resl, e = this.DB.Exec(query, args...)
resl, e = that.DB.Exec(query, args...)
}
this.LastErr.SetError(e)
that.LastErr.SetError(e)
//判断是否连接断开了
if e != nil {
if e = this.DB.Ping(); e != nil {
this.LastErr.SetError(e)
this.InitDb()
if this.LastErr.GetError() != nil {
return resl, this.LastErr
if e = that.DB.Ping(); e != nil {
that.LastErr.SetError(e)
_ = that.InitDb()
if that.LastErr.GetError() != nil {
return resl, that.LastErr
}
return this.Exec(query, args...)
return that.Exec(query, args...)
}
}
return resl, this.LastErr
return resl, that.LastErr
}
//func (this *HoTimeDB)copy(data []Map)[]Map{
@ -384,7 +397,8 @@ func (this *HoTimeDB) Exec(query string, args ...interface{}) (sql.Result, Error
// return res
//
//}
func (this *HoTimeDB) Select(table string, qu ...interface{}) []Map {
func (that *HoTimeDB) Select(table string, qu ...interface{}) []Map {
query := "SELECT"
where := Map{}
@ -446,15 +460,15 @@ func (this *HoTimeDB) Select(table string, qu ...interface{}) []Map {
where = qu[intWhere].(Map)
}
temp, resWhere := this.where(where)
temp, resWhere := that.where(where)
query += temp
qs = append(qs, resWhere...)
md5 := this.md5(query, qs...)
md5 := that.md5(query, qs...)
if this.DBCached && this.CacheIns != nil {
if that.DBCached && that.CacheIns != nil {
//如果缓存有则从缓存取
cacheData := this.Cache(table + ":" + md5)
cacheData := that.Cache(table + ":" + md5)
if cacheData.Data != nil {
return cacheData.ToMapArray()
@ -462,23 +476,23 @@ func (this *HoTimeDB) Select(table string, qu ...interface{}) []Map {
}
//无缓存则数据库取
res := this.Query(query, qs...)
res := that.Query(query, qs...)
if res == nil {
res = []Map{}
}
//缓存
if this.DBCached && this.CacheIns != nil {
if that.DBCached && that.CacheIns != nil {
this.Cache(table+":"+md5, res)
_ = that.Cache(table+":"+md5, res)
}
return res
}
func (this *HoTimeDB) Get(table string, qu ...interface{}) Map {
func (that *HoTimeDB) Get(table string, qu ...interface{}) Map {
//fmt.Println(qu)
if len(qu) == 1 {
qu = append(qu, Map{"LIMIT": 1})
@ -494,19 +508,16 @@ func (this *HoTimeDB) Get(table string, qu ...interface{}) Map {
qu[2] = temp
}
//fmt.Println(qu)
data := this.Select(table, qu...)
data := that.Select(table, qu...)
if len(data) == 0 {
return nil
}
return data[0]
}
/**
** 计数
*/
func (this *HoTimeDB) Count(table string, qu ...interface{}) int {
req := []interface{}{}
// Count 计数
func (that *HoTimeDB) Count(table string, qu ...interface{}) int {
var req = []interface{}{}
if len(qu) == 2 {
req = append(req, qu[0])
req = append(req, "COUNT(*)")
@ -517,7 +528,7 @@ func (this *HoTimeDB) Count(table string, qu ...interface{}) int {
}
//req=append(req,qu...)
data := this.Select(table, req...)
data := that.Select(table, req...)
//fmt.Println(data)
if len(data) == 0 {
return 0
@ -533,7 +544,7 @@ var condition = []string{"AND", "OR"}
var vcond = []string{"GROUP", "ORDER", "LIMIT"}
//where语句解析
func (this *HoTimeDB) where(data Map) (string, []interface{}) {
func (that *HoTimeDB) where(data Map) (string, []interface{}) {
where := ""
@ -545,7 +556,7 @@ func (this *HoTimeDB) where(data Map) (string, []interface{}) {
if condition[i] == k {
tw, ts := this.cond(k, v.(Map))
tw, ts := that.cond(k, v.(Map))
where += tw
res = append(res, ts...)
@ -563,7 +574,7 @@ func (this *HoTimeDB) where(data Map) (string, []interface{}) {
y++
}
if x == len(condition) && y == len(vcond) {
tv, vv := this.varCond(k, v)
tv, vv := that.varCond(k, v)
where += tv
res = append(res, vv...)
@ -617,7 +628,7 @@ func (this *HoTimeDB) where(data Map) (string, []interface{}) {
}
func (this *HoTimeDB) varCond(k string, v interface{}) (string, []interface{}) {
func (that *HoTimeDB) varCond(k string, v interface{}) (string, []interface{}) {
where := ""
res := make([]interface{}, 0)
length := len(k)
@ -635,7 +646,7 @@ func (this *HoTimeDB) varCond(k string, v interface{}) (string, []interface{}) {
res = append(res, v)
case "[!]":
k = strings.Replace(k, "[!]", "", -1)
where, res = this.notIn(k, v, where, res)
where, res = that.notIn(k, v, where, res)
case "[#]":
k = strings.Replace(k, "[#]", "", -1)
where += " " + k + "=" + ObjToStr(v)
@ -692,7 +703,7 @@ func (this *HoTimeDB) varCond(k string, v interface{}) (string, []interface{}) {
default:
if reflect.ValueOf(v).Type().String() == "hotime.Slice" {
where += "`" + k + "` IN ("
res = append(res, (v.(Slice))...)
res = append(res, v.(Slice)...)
if len(v.(Slice)) == 0 {
where += ") "
} else {
@ -725,7 +736,7 @@ func (this *HoTimeDB) varCond(k string, v interface{}) (string, []interface{}) {
//fmt.Println(v)
where += "`" + k + "` IN ("
res = append(res, (v.(Slice))...)
res = append(res, v.(Slice)...)
for i := 0; i < len(v.(Slice)); i++ {
if i+1 != len(v.(Slice)) {
where += "?,"
@ -736,7 +747,7 @@ func (this *HoTimeDB) varCond(k string, v interface{}) (string, []interface{}) {
}
} else if reflect.ValueOf(v).Type().String() == "[]interface {}" {
where += "`" + k + "` IN ("
res = append(res, (v.([]interface{}))...)
res = append(res, v.([]interface{})...)
for i := 0; i < len(v.([]interface{})); i++ {
if i+1 != len(v.([]interface{})) {
where += "?,"
@ -757,7 +768,7 @@ func (this *HoTimeDB) varCond(k string, v interface{}) (string, []interface{}) {
}
// this.Db.Update("user",hotime.Map{"ustate":"1"},hotime.Map{"AND":hotime.Map{"OR":hotime.Map{"uid":4,"uname":"dasda"}},"ustate":1})
func (this *HoTimeDB) notIn(k string, v interface{}, where string, res []interface{}) (string, []interface{}) {
func (that *HoTimeDB) notIn(k string, v interface{}, where string, res []interface{}) (string, []interface{}) {
//where:=""
//fmt.Println(reflect.ValueOf(v).Type().String())
if v == nil {
@ -766,7 +777,7 @@ func (this *HoTimeDB) notIn(k string, v interface{}, where string, res []interfa
} else if reflect.ValueOf(v).Type().String() == "hotime.Slice" {
where += "`" + k + "` NOT IN ("
res = append(res, (v.(Slice))...)
res = append(res, v.(Slice)...)
for i := 0; i < len(v.(Slice)); i++ {
if i+1 != len(v.(Slice)) {
where += "?,"
@ -777,7 +788,7 @@ func (this *HoTimeDB) notIn(k string, v interface{}, where string, res []interfa
}
} else if reflect.ValueOf(v).Type().String() == "[]interface {}" {
where += "`" + k + "` NOT IN ("
res = append(res, (v.([]interface{}))...)
res = append(res, v.([]interface{})...)
for i := 0; i < len(v.([]interface{})); i++ {
if i+1 != len(v.([]interface{})) {
where += "?,"
@ -796,7 +807,7 @@ func (this *HoTimeDB) notIn(k string, v interface{}, where string, res []interfa
return where, res
}
func (this *HoTimeDB) cond(tag string, data Map) (string, []interface{}) {
func (that *HoTimeDB) cond(tag string, data Map) (string, []interface{}) {
where := " "
res := make([]interface{}, 0)
lens := len(data)
@ -807,7 +818,7 @@ func (this *HoTimeDB) cond(tag string, data Map) (string, []interface{}) {
if condition[i] == k {
tw, ts := this.cond(k, v.(Map))
tw, ts := that.cond(k, v.(Map))
if lens--; lens <= 0 {
//fmt.Println(lens)
where += "(" + tw + ") "
@ -823,7 +834,7 @@ func (this *HoTimeDB) cond(tag string, data Map) (string, []interface{}) {
if x == len(condition) {
tv, vv := this.varCond(k, v)
tv, vv := that.varCond(k, v)
res = append(res, vv...)
if lens--; lens <= 0 {
@ -838,8 +849,8 @@ func (this *HoTimeDB) cond(tag string, data Map) (string, []interface{}) {
return where, res
}
//更新数据
func (this *HoTimeDB) Update(table string, data Map, where Map) int64 {
// Update 更新数据
func (that *HoTimeDB) Update(table string, data Map, where Map) int64 {
query := "UPDATE " + table + " SET "
//UPDATE Person SET Address = 'Zhongshan 23', City = 'Nanjing' WHERE LastName = 'Wilson'
@ -861,13 +872,13 @@ func (this *HoTimeDB) Update(table string, data Map, where Map) int64 {
}
}
temp, resWhere := this.where(where)
temp, resWhere := that.where(where)
//fmt.Println(resWhere)
query += temp
qs = append(qs, resWhere...)
res, err := this.Exec(query, qs...)
res, err := that.Exec(query, qs...)
rows := int64(0)
if err.GetError() == nil && res != nil {
@ -876,22 +887,22 @@ func (this *HoTimeDB) Update(table string, data Map, where Map) int64 {
//如果更新成功,则删除缓存
if rows != 0 {
if this.DBCached && this.CacheIns != nil {
this.Cache(table+"*", nil)
if that.DBCached && that.CacheIns != nil {
_ = that.Cache(table+"*", nil)
}
}
return rows
}
func (this *HoTimeDB) Delete(table string, data map[string]interface{}) int64 {
func (that *HoTimeDB) Delete(table string, data map[string]interface{}) int64 {
query := "DELETE FROM " + table + " "
temp, resWhere := this.where(data)
temp, resWhere := that.where(data)
query += temp
res, err := this.Exec(query, resWhere...)
res, err := that.Exec(query, resWhere...)
rows := int64(0)
if err.GetError() == nil && res != nil {
rows, _ = res.RowsAffected()
@ -899,8 +910,8 @@ func (this *HoTimeDB) Delete(table string, data map[string]interface{}) int64 {
//如果删除成功,删除对应缓存
if rows != 0 {
if this.DBCached && this.CacheIns != nil {
this.Cache(table+"*", nil)
if that.DBCached && that.CacheIns != nil {
_ = that.Cache(table+"*", nil)
}
}
//return 0
@ -908,8 +919,8 @@ func (this *HoTimeDB) Delete(table string, data map[string]interface{}) int64 {
return rows
}
//插入新数据
func (this *HoTimeDB) Insert(table string, data map[string]interface{}) int64 {
// Insert 插入新数据
func (that *HoTimeDB) Insert(table string, data map[string]interface{}) int64 {
values := make([]interface{}, 0)
queryString := " ("
@ -931,18 +942,18 @@ func (this *HoTimeDB) Insert(table string, data map[string]interface{}) int64 {
}
query := "INSERT INTO " + table + queryString + "VALUES" + valueString
res, err := this.Exec(query, values...)
res, err := that.Exec(query, values...)
id := int64(0)
if err.GetError() == nil && res != nil {
//id, this.LastErr.err = res.LastInsertId()
//id, that.LastErr.err = res.LastInsertId()
}
//如果插入成功,删除缓存
if id != 0 {
if this.DBCached && this.CacheIns != nil {
this.Cache(table+"*", nil)
if that.DBCached && that.CacheIns != nil {
_ = that.Cache(table+"*", nil)
}
}

View File

@ -6,11 +6,8 @@ import (
"../../hotime/common"
"database/sql"
"fmt"
//"go.hoteas.com/hotime/cache"
"golang.org/x/net/websocket"
"time"
//"go.hoteas.com/hotime/cache"
)
func main() {
@ -27,18 +24,18 @@ func main() {
//手动模式,
appIns.SetConfig("example/config/config.json")
//redis缓存接入
//ca:=cache.CacheIns(&cache.CacheRedis{Host:appIns.Config.GetString("redisHost"),Pwd:appIns.Config.GetString("redisPwd"),Time:appIns.Config.GetCeilInt64("cacheLongTime")})
//ca.Cache("xyzm","dasdas")
//ca.Cache("xyzn","dasdas")
//ca.Cache("xyzo","dasdas")
//ca.Cache("xyz*",nil)
ca := cache.CacheIns(&cache.CacheRedis{Host: appIns.Config.GetString("redisHost"), Pwd: appIns.Config.GetString("redisPwd"), Time: appIns.Config.GetCeilInt64("cacheLongTime")})
ca.Cache("xyzm", "dasdas")
ca.Cache("xyzn", "dasdas")
ca.Cache("xyzo", "dasdas")
ca.Cache("xyz*", nil)
//fmt.Println(ca.Cache("xyzm").Data)
//mysql
//mysql.SetDB(&appIns)
//自动选择数据库
dbInterface := cache.HoTimeDBInterface(&appIns.Db)
appIns.SetSession(cache.CacheIns(&cache.CacheMemory{}), cache.CacheIns(&cache.CacheDb{Db: dbInterface, Time: appIns.Config.GetInt64("cacheTime")}))
//appIns.SetCache(cache.CacheIns(&cache.CacheMemory{}))
appIns.SetCache(cache.CacheIns(&cache.CacheMemory{}))
//快捷模式
appIns.SetDefault(func(err ...*common.Error) (*sql.DB, *sql.DB) {
@ -56,6 +53,8 @@ func main() {
"index": hotime.Ctr{
"test": func(this *hotime.Context) {
fmt.Println(this.Db.GetTag())
this.Application.Log.Error("dasdasdas")
this.Log.Error("dadasdasd")
//x:=this.Db.Action(func(db hotime.HoTimeDB) bool {
//
// db.Insert("user",hotime.Map{"unickname":"dasdas"})

114
log/logrus.go Normal file
View File

@ -0,0 +1,114 @@
package log
import (
"fmt"
log "github.com/sirupsen/logrus"
"os"
"path/filepath"
"runtime"
"strings"
"time"
)
func GetLog(path string, showCodeLine bool) *log.Logger {
hook := MyHook{
Field: "line",
Skip: 5,
Path: path, ShowCodeLine: showCodeLine,
}
loger := log.New()
loger.SetFormatter(&log.TextFormatter{})
loger.AddHook(&hook)
loger.Print("dasdasdas")
return loger
}
// MyHook ...
type MyHook struct {
Path string //存储日志的位置
ShowCodeLine bool //输出代码文件名称和日志行
Field string
Skip int
levels []log.Level
}
// Levels 只定义 error 和 panic 等级的日志,其他日志等级不会触发 hook
func (that *MyHook) Levels() []log.Level {
return log.AllLevels
}
// Fire 将异常日志写入到指定日志文件中
func (that *MyHook) Fire(entry *log.Entry) error {
if that.ShowCodeLine {
entry.Data[that.Field] = findCaller(that.Skip)
}
//不需要存储到文件
if that.Path == "" {
return nil
}
//存储到文件
logFilePath := time.Now().Format(that.Path)
err := os.MkdirAll(filepath.Dir(logFilePath), os.ModeAppend)
if err != nil {
return err
}
//os.Create(logFilePath)
f, err := os.OpenFile(logFilePath, os.O_APPEND|os.O_CREATE, 0644)
if err != nil {
return err
}
bte, _ := entry.Bytes()
_, err = f.Write(bte)
if err != nil {
return err
}
err = f.Close()
if err != nil {
return err
}
return nil
}
// 对caller进行递归查询, 直到找到非logrus包产生的第一个调用.
// 因为filename我获取到了上层目录名, 因此所有logrus包的调用的文件名都是 logrus/...
// 因此通过排除logrus开头的文件名, 就可以排除所有logrus包的自己的函数调用
func findCaller(skip int) string {
file := ""
line := 0
for i := 0; i < 10; i++ {
file, line = getCaller(skip + i)
if !strings.HasPrefix(file, "logrus") {
break
}
}
return fmt.Sprintf("%s:%d", file, line)
}
// 这里其实可以获取函数名称的: fnName := runtime.FuncForPC(pc).Name()
// 但是我觉得有 文件名和行号就够定位问题, 因此忽略了caller返回的第一个值:pc
// 在标准库log里面我们可以选择记录文件的全路径或者文件名, 但是在使用过程成并发最合适的,
// 因为文件的全路径往往很长, 而文件名在多个包中往往有重复, 因此这里选择多取一层, 取到文件所在的上层目录那层.
func getCaller(skip int) (string, int) {
_, file, line, ok := runtime.Caller(skip)
//fmt.Println(file)
//fmt.Println(line)
if !ok {
return "", 0
}
n := 0
for i := len(file) - 1; i > 0; i-- {
if file[i] == '/' {
n++
if n >= 2 {
file = file[i+1:]
break
}
}
}
return file, line
}

View File

@ -14,63 +14,63 @@ type SessionIns struct {
ContextBase
}
func (this *SessionIns) set() {
func (that *SessionIns) set() {
if this.ShortCache != nil {
this.ShortCache.Cache(HEAD_SESSION_ADD+this.SessionId, this.Map)
if that.ShortCache != nil {
that.ShortCache.Cache(HEAD_SESSION_ADD+that.SessionId, that.Map)
}
if this.LongCache != nil {
this.LongCache.Cache(HEAD_SESSION_ADD+this.SessionId, this.Map)
if that.LongCache != nil {
that.LongCache.Cache(HEAD_SESSION_ADD+that.SessionId, that.Map)
}
}
func (this *SessionIns) Session(key string, data ...interface{}) *Obj {
func (that *SessionIns) Session(key string, data ...interface{}) *Obj {
if this.Map == nil {
this.get()
if that.Map == nil {
that.get()
}
if len(data) != 0 {
if data[0] == nil {
delete(this.Map, key)
this.set()
delete(that.Map, key)
that.set()
} else {
this.Map[key] = data[0]
this.set()
that.Map[key] = data[0]
that.set()
}
return &Obj{Data: nil}
}
return &Obj{Data: this.Map.Get(key)}
return &Obj{Data: that.Map.Get(key)}
}
func (this *SessionIns) get() {
func (that *SessionIns) get() {
if this.ShortCache != nil {
this.Map = this.ShortCache.Cache(HEAD_SESSION_ADD + this.SessionId).ToMap()
if this.Map != nil {
if that.ShortCache != nil {
that.Map = that.ShortCache.Cache(HEAD_SESSION_ADD + that.SessionId).ToMap()
if that.Map != nil {
return
}
}
if this.LongCache != nil {
this.Map = this.LongCache.Cache(HEAD_SESSION_ADD + this.SessionId).ToMap()
if this.Map != nil {
if this.ShortCache != nil {
this.ShortCache.Cache(HEAD_SESSION_ADD+this.SessionId, this.Map)
if that.LongCache != nil {
that.Map = that.LongCache.Cache(HEAD_SESSION_ADD + that.SessionId).ToMap()
if that.Map != nil {
if that.ShortCache != nil {
that.ShortCache.Cache(HEAD_SESSION_ADD+that.SessionId, that.Map)
}
return
}
}
this.Map = Map{}
this.ShortCache.Cache(HEAD_SESSION_ADD+this.SessionId, this.Map)
that.Map = Map{}
that.ShortCache.Cache(HEAD_SESSION_ADD+that.SessionId, that.Map)
return
}
func (this *SessionIns) Init(short CacheIns, long CacheIns) {
this.ShortCache = short
this.LongCache = long
func (that *SessionIns) Init(short CacheIns, long CacheIns) {
that.ShortCache = short
that.LongCache = long
}

View File

@ -1,6 +1,6 @@
package hotime
//控制器
// Ctr 控制器
type Ctr map[string]Method
type Proj map[string]Ctr
type Router map[string]Proj

4
var.go
View File

@ -11,7 +11,6 @@ var App = map[string]*Application{} //整个项目
var Config = Map{
"debug": 1, //debug 0关闭1开启
"logLevel": LOG_FMT,
"db": Map{
"sqlite": Map{
"path": "config/data.db",
@ -40,6 +39,8 @@ var Config = Map{
var ConfigNote = Map{
"logLevel": "默认0必须0关闭1打印日志等级",
"logFile": "无默认,非必须,如果需要存储日志文件时使用,保存格式为:a/b/c/20060102150405.txt,将生成a/b/c/年月日时分秒.txt按需设置",
"webConnectLogShow": "默认true非必须访问日志如果需要web访问链接、访问ip、访问时间打印false为关闭true开启此功能",
"webConnectLogFile": "无默认非必须webConnectLogShow开启之后才能使用如果需要存储日志文件时使用保存格式为:a/b/c/20060102150405.txt,将生成a/b/c/年月日时分秒.txt按需设置",
"debug": "默认1必须0关闭其他开启0用于生产环境其他值用于开发测试会显示更多内容并能够辅助研发自动生成配置文件、代码等功能,web无缓存", //debug 0关闭1开启
"db": Map{
"注释": "配置即启用非必须默认使用sqlite数据库",
@ -100,7 +101,6 @@ var ConfigNote = Map{
"defFile": "默认访问index.html或者index.htm文件必须默认访问文件类型",
"crossDomain": "默认空 非必须空字符串为不开启如果需要跨域设置auto为智能开启所有网站允许跨域http://www.baidu.com为指定域允许跨域", //是否开启跨域
"modeRouterStrict": "默认false,必须路由严格模式false,为大小写忽略必须匹配true必须大小写匹配", //路由严格模式/a/b/c
"connectLogShow": "默认true非必须访问日志如果需要web访问链接、访问ip、访问时间打印false为关闭true开启此功能",
"sessionName": "默认HOTIME必须设置session的cookie名",
"port": "默认80必须web服务开启Http端口0为不启用http服务,默认80",
"tlsPort": "默认443非必须web服务https端口0为不启用https服务",