├── .travis.yml ├── README.md ├── bin └── conf │ └── develop │ ├── app.conf │ ├── dotlog.conf │ ├── dottask.conf │ └── dotweb.conf ├── config ├── config.go └── model.go ├── const └── const.go ├── core ├── cmap.go ├── exception │ └── exception.go └── timex │ ├── time.go │ └── time_test.go ├── document └── demo.MD ├── global └── global.go ├── main.go ├── protected ├── model │ └── DemoInfo.go ├── repository │ ├── BaseRepository.go │ └── demo │ │ └── DemoRepository.go └── service │ ├── BaseService.go │ └── demo │ └── DemoService.go ├── resources ├── config │ └── develop │ │ ├── app.conf │ │ ├── dotlog.conf │ │ ├── dottask.conf │ │ └── dotweb.conf └── version.yaml ├── server ├── contract │ └── ResponseInfo.go ├── handlers │ ├── demo │ │ └── demo.go │ └── test │ │ └── default.go ├── router.go ├── server.go └── validate │ └── validate.go ├── task ├── service.go └── tasks │ └── demo.go └── util ├── file └── files.go ├── http ├── http.go └── http_test.go ├── json └── json.go ├── rsa ├── rsa.go └── rsa_test.go └── time └── time.go /.travis.yml: -------------------------------------------------------------------------------- 1 | language: go 2 | sudo: required 3 | 4 | go: 5 | - 1.8 6 | 7 | env: 8 | - GO15VENDOREXPERIMENT="1" 9 | 10 | before_install: 11 | - Project=devfeel 12 | 13 | script: 14 | - go build -o "$Project" -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # DotWeb-Start 2 | 基于dotweb的示范项目结构 3 | 4 | ## 注意事项 5 | * 使用配置文件方式,包含app.conf、dotweb.conf、dotlog.conf 6 | * bin目录为特定目录,建议在开发环境时,将编译生成的文件输出到该目录 7 | * 确保bin目录下conf/develop目录下3个配置文件存在 8 | 9 | 10 | ## 目录说明 11 | * config:全局配置文件定义及使用代码 12 | * const:全局常量 13 | * core:全局核心对象 14 | * document:文档目录 15 | * global:全局访问对象定义及入口 16 | * protected:业务逻辑处理模块,包含数据模型、数据操作等 17 | * resources:开发\测试\生产不同环境资源、配置文件及版本信息 18 | * server:web服务目录,包含常规处理逻辑、路由、静态资源等 19 | * task:task服务目录,主要负责调度器相关 20 | * util:通用方法 21 | 22 | ## 依赖项 23 | * github.com/devfeel/dotweb 24 | * github.com/devfeel/dotlog 25 | * github.com/devfeel/mapper 26 | * github.com/devfeel/middleware 27 | * github.com/devfeel/database -------------------------------------------------------------------------------- /bin/conf/develop/app.conf: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /bin/conf/develop/dotlog.conf: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /bin/conf/develop/dottask.conf: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /bin/conf/develop/dotweb.conf: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 |   -------------------------------------------------------------------------------- /config/config.go: -------------------------------------------------------------------------------- 1 | package config 2 | 3 | import ( 4 | "github.com/devfeel/dotweb-start/const" 5 | "github.com/devfeel/dotweb-start/core" 6 | "github.com/devfeel/dotweb-start/util/file" 7 | "github.com/devfeel/dotweb-start/util/json" 8 | "encoding/xml" 9 | "github.com/devfeel/dotlog" 10 | "io/ioutil" 11 | "strconv" 12 | ) 13 | 14 | var ( 15 | CurrentConfig *AppConfig 16 | CurrentBaseDir string 17 | innerLogger dotlog.Logger 18 | appSetMap *core.CMap 19 | allowIPMap *core.CMap 20 | redisMap *core.CMap 21 | databaseMap *core.CMap 22 | ) 23 | 24 | func SetBaseDir(baseDir string) { 25 | CurrentBaseDir = baseDir 26 | } 27 | 28 | //初始化配置文件 29 | func InitConfig(configFile string) *AppConfig { 30 | innerLogger = dotlog.GetLogger(_const.LoggerName_Inner) 31 | CurrentBaseDir = _file.GetCurrentDirectory() 32 | innerLogger.Info("AppConfig::InitConfig 配置文件[" + configFile + "]开始...") 33 | content, err := ioutil.ReadFile(configFile) 34 | if err != nil { 35 | innerLogger.Warn("AppConfig::InitConfig 配置文件[" + configFile + "]无法解析 - " + err.Error()) 36 | panic(err) 37 | } 38 | 39 | var result AppConfig 40 | err = xml.Unmarshal(content, &result) 41 | if err != nil { 42 | innerLogger.Warn("AppConfig::InitConfig 配置文件[" + configFile + "]解析失败 - " + err.Error()) 43 | panic(err) 44 | } 45 | 46 | //init config base 47 | CurrentConfig = &result 48 | 49 | //init AppConfig 50 | innerLogger.Info("AppConfig::InitConfig Load AppSet Start") 51 | tmpAppSetMap := core.NewCMap() 52 | for _, v := range result.AppSets { 53 | tmpAppSetMap.Set(v.Key, v.Value) 54 | innerLogger.Info("AppConfig::InitConfig Load AppSet => " + _json.GetJsonString(&v)) 55 | } 56 | appSetMap = tmpAppSetMap 57 | innerLogger.Info("AppConfig::InitConfig Load AppSet Finished [" + strconv.Itoa(appSetMap.Len()) + "]") 58 | 59 | //init redisConfig 60 | innerLogger.Info("AppConfig::InitConfig Start Load RedisInfo") 61 | tmpRedisMap := core.NewCMap() 62 | for k, v := range result.Redises { 63 | tmpRedisMap.Set(v.ID, result.Redises[k]) 64 | innerLogger.Info("AppConfig::InitConfig Load RedisInfo => " + _json.GetJsonString(v)) 65 | } 66 | redisMap = tmpRedisMap 67 | innerLogger.Info("AppConfig::InitConfig Finish Load RedisInfo") 68 | 69 | //init databaseConfig 70 | innerLogger.Info("AppConfig::InitConfig Start Load DataBaseInfo") 71 | temDataBaseMap := core.NewCMap() 72 | for k, v := range result.Databases { 73 | temDataBaseMap.Set(v.ID, result.Databases[k]) 74 | innerLogger.Info("AppConfig::InitConfig Load DataBaseInfo => " + _json.GetJsonString(v)) 75 | } 76 | databaseMap = temDataBaseMap 77 | innerLogger.Info("AppConfig::InitConfig Finish Load DataBaseInfo") 78 | 79 | innerLogger.Info("AppConfig::InitConfig 配置文件[" + configFile + "]完成") 80 | 81 | CurrentConfig.ConfigPath = GetAppConfig("ConfigPath") 82 | 83 | return CurrentConfig 84 | } 85 | 86 | func GetAppConfig(key string) string { 87 | return appSetMap.GetString(key) 88 | } 89 | 90 | func GetAppSetMap() *core.CMap { 91 | return appSetMap 92 | } 93 | 94 | func GetRedisInfo(redisID string) (*RedisInfo, bool) { 95 | info, exists := redisMap.Get(redisID) 96 | if exists { 97 | return info.(*RedisInfo), exists 98 | } else { 99 | return nil, false 100 | } 101 | } 102 | 103 | 104 | func GetDataBaseInfo(databaseId string) (*DataBaseInfo, bool) { 105 | info, exists := databaseMap.Get(databaseId) 106 | if exists { 107 | return info.(*DataBaseInfo), exists 108 | } else { 109 | return nil, false 110 | } 111 | } 112 | 113 | 114 | //检测IP是否被允许访问 115 | func CheckAllowIP(ip string) bool { 116 | return allowIPMap.Exists(ip) 117 | } 118 | -------------------------------------------------------------------------------- /config/model.go: -------------------------------------------------------------------------------- 1 | package config 2 | 3 | import ( 4 | "encoding/xml" 5 | ) 6 | 7 | //配置信息 8 | type AppConfig struct { 9 | XMLName xml.Name `xml:"config"` 10 | AppSets []*AppSet `xml:"appsettings>add"` 11 | Redises []*RedisInfo `xml:"redises>redis"` 12 | Databases []*DataBaseInfo `xml:"databases>database"` 13 | AllowIps []string `xml:"allowips>ip"` 14 | ConfigPath string 15 | } 16 | 17 | //AppSetting配置 18 | type AppSet struct { 19 | Key string `xml:"key,attr"` 20 | Value string `xml:"value,attr"` 21 | } 22 | 23 | //Redis信息 24 | type RedisInfo struct { 25 | ID string `xml:"id,attr"` 26 | ServerUrl string `xml:"serverurl,attr"` 27 | } 28 | 29 | //DataBase信息 30 | type DataBaseInfo struct { 31 | ID string `xml:"id,attr"` 32 | ServerUrl string `xml:"serverurl,attr"` 33 | } 34 | 35 | -------------------------------------------------------------------------------- /const/const.go: -------------------------------------------------------------------------------- 1 | package _const 2 | 3 | const ( 4 | Global_ProjectName = "{project}" 5 | Global_Version = "V1.0 - 20171101" 6 | ) 7 | 8 | const ( 9 | RedisKey_ProjectPre = "{project}" 10 | ) 11 | 12 | const ( 13 | LoggerName_Inner = "DefaultLogger" 14 | LoggerName_Mongodb = "MongodbLogger" 15 | LoggerName_Service = "ServiceLogger" 16 | LoggerName_Repository = "RepositoryLogger" 17 | ) 18 | 19 | const ( 20 | ApiRetCode_Ok = 0 21 | ApiRetCode_Error = -9999 22 | ApiRetCode_BindError = -9100 23 | ApiRetCode_ServiceError = -2001 24 | ApiRetMsg_Ok = "" 25 | ) 26 | -------------------------------------------------------------------------------- /core/cmap.go: -------------------------------------------------------------------------------- 1 | package core 2 | 3 | import ( 4 | "fmt" 5 | "sync" 6 | ) 7 | 8 | //自带锁,并发安全的Map 9 | type CMap struct { 10 | contextMap map[string]interface{} 11 | *sync.RWMutex 12 | } 13 | 14 | func NewCMap() *CMap { 15 | return &CMap{ 16 | contextMap: make(map[string]interface{}), 17 | RWMutex: new(sync.RWMutex), 18 | } 19 | } 20 | 21 | /* 22 | * 以key、value置入AppContext 23 | */ 24 | func (ctx *CMap) Set(key string, value interface{}) error { 25 | ctx.Lock() 26 | ctx.contextMap[key] = value 27 | ctx.Unlock() 28 | return nil 29 | } 30 | 31 | /* 32 | * 读取指定key在AppContext中的内容 33 | */ 34 | func (ctx *CMap) Get(key string) (value interface{}, exists bool) { 35 | ctx.RLock() 36 | value, exists = ctx.contextMap[key] 37 | ctx.RUnlock() 38 | return value, exists 39 | } 40 | 41 | //remove item by gived key 42 | //if not exists key, do nothing... 43 | func (ctx *CMap) Remove(key string) { 44 | ctx.Lock() 45 | delete(ctx.contextMap, key) 46 | ctx.Unlock() 47 | } 48 | 49 | //get item by gived key, and remove it 50 | //only can be read once, it will be locked 51 | func (ctx *CMap) Once(key string) (value interface{}, exists bool) { 52 | ctx.Lock() 53 | defer ctx.Unlock() 54 | value, exists = ctx.contextMap[key] 55 | if exists { 56 | delete(ctx.contextMap, key) 57 | } 58 | return value, exists 59 | } 60 | 61 | /* 62 | * 读取指定key在AppContext中的内容,以string格式输出 63 | */ 64 | func (ctx *CMap) GetString(key string) string { 65 | value, exists := ctx.Get(key) 66 | if !exists { 67 | return "" 68 | } 69 | return fmt.Sprint(value) 70 | } 71 | 72 | /* 73 | * 读取指定key在AppContext中的内容,以int格式输出 74 | */ 75 | func (ctx *CMap) GetInt(key string) int { 76 | value, exists := ctx.Get(key) 77 | if !exists { 78 | return 0 79 | } 80 | return value.(int) 81 | } 82 | 83 | //check exists key 84 | func (ctx *CMap) Exists(key string) bool { 85 | _, exists := ctx.contextMap[key] 86 | return exists 87 | } 88 | 89 | //get current map, returns map[string]interface{} 90 | func (ctx *CMap) GetCurrentMap() map[string]interface{} { 91 | return ctx.contextMap 92 | } 93 | 94 | //get context length 95 | func (ctx *CMap) Len() int { 96 | return len(ctx.contextMap) 97 | } 98 | -------------------------------------------------------------------------------- /core/exception/exception.go: -------------------------------------------------------------------------------- 1 | package exception 2 | 3 | import ( 4 | "fmt" 5 | "runtime/debug" 6 | ) 7 | 8 | type Exception interface { 9 | GetErrString() string 10 | GetStackString() string 11 | GetDefaultLogString() string 12 | } 13 | 14 | type exception struct { 15 | ErrString string 16 | StackString string 17 | DefaultLogString string 18 | } 19 | 20 | func (e *exception) GetErrString() string { 21 | return e.ErrString 22 | } 23 | 24 | func (e *exception) GetStackString() string { 25 | return e.StackString 26 | } 27 | 28 | func (e *exception) GetDefaultLogString() string { 29 | return e.DefaultLogString 30 | } 31 | 32 | //统一异常处理 33 | func CatchError(title string, err interface{}) Exception { 34 | ex := new(exception) 35 | ex.ErrString = fmt.Sprintln(err) 36 | ex.StackString = string(debug.Stack()) 37 | ex.DefaultLogString = title + " CatchError [" + ex.GetErrString() + "] [" + ex.GetStackString() + "]" 38 | return ex 39 | } 40 | -------------------------------------------------------------------------------- /core/timex/time.go: -------------------------------------------------------------------------------- 1 | package timex 2 | 3 | import "time" 4 | 5 | type Time time.Time 6 | 7 | var ( 8 | timeJSONFormat = "2006-01-02 15:04:05" 9 | ) 10 | 11 | func SetTimeJJSONFormat(format string){ 12 | timeJSONFormat = format 13 | } 14 | 15 | func GetTimeJSONFormat()string{ 16 | return timeJSONFormat 17 | } 18 | 19 | func (t *Time) UnmarshalJSON(data []byte) (err error) { 20 | now, err := time.ParseInLocation(`"`+timeJSONFormat+`"`, string(data), time.Local) 21 | *t = Time(now) 22 | return 23 | } 24 | 25 | func (t Time) MarshalJSON() ([]byte, error) { 26 | b := make([]byte, 0, len(timeJSONFormat)+2) 27 | b = append(b, '"') 28 | b = time.Time(t).AppendFormat(b, timeJSONFormat) 29 | b = append(b, '"') 30 | return b, nil 31 | } 32 | 33 | func (t Time) String() string { 34 | return time.Time(t).Format(timeJSONFormat) 35 | } 36 | 37 | -------------------------------------------------------------------------------- /core/timex/time_test.go: -------------------------------------------------------------------------------- 1 | package timex 2 | 3 | import ( 4 | "time" 5 | "testing" 6 | "encoding/json" 7 | ) 8 | 9 | type Person struct { 10 | Id int64 `json:"id"` 11 | Name string `json:"name"` 12 | Birthday Time `json:"birthday"` 13 | } 14 | 15 | func TestTimeJson(t *testing.T) { 16 | now := Time(time.Now()) 17 | t.Log(now) 18 | src := `{"id":5,"name":"xiaoming","birthday":"2016-06-30 16:09:51"}` 19 | p := new(Person) 20 | err := json.Unmarshal([]byte(src), p) 21 | if err != nil { 22 | t.Fatal(err) 23 | } 24 | t.Log(p) 25 | t.Log(time.Time(p.Birthday)) 26 | js, _ := json.Marshal(p) 27 | t.Log(string(js)) 28 | } 29 | 30 | func TestTimeJson_NewFormat(t *testing.T) { 31 | now := Time(time.Now()) 32 | t.Log(now) 33 | SetTimeJJSONFormat("2006-01-02T15:04:05") 34 | src := `{"id":5,"name":"xiaoming","birthday":"2016-06-30T16:09:51"}` 35 | p := new(Person) 36 | err := json.Unmarshal([]byte(src), p) 37 | if err != nil { 38 | t.Fatal(err) 39 | } 40 | t.Log(p) 41 | t.Log(time.Time(p.Birthday)) 42 | js, _ := json.Marshal(p) 43 | t.Log(string(js)) 44 | } 45 | -------------------------------------------------------------------------------- /document/demo.MD: -------------------------------------------------------------------------------- 1 | # demo.MD 2 | 3 | dotweb-start项目demo 4 | 5 | #### 依赖项 6 | * github.com/devfeel/dotweb 7 | * github.com/devfeel/dotlog 8 | * github.com/devfeel/cache 9 | * github.com/devfeel/mapper 10 | * github.com/devfeel/middleware -------------------------------------------------------------------------------- /global/global.go: -------------------------------------------------------------------------------- 1 | package global 2 | 3 | import ( 4 | "github.com/devfeel/dotweb" 5 | "github.com/devfeel/dotlog" 6 | "github.com/devfeel/dotweb-start/const" 7 | "errors" 8 | "github.com/devfeel/dotweb-start/core" 9 | "github.com/devfeel/dottask" 10 | ) 11 | 12 | //全局map 13 | var GlobalItemMap *core.CMap 14 | var DotApp *dotweb.DotWeb 15 | var DotTask *task.TaskService 16 | var InnerLogger dotlog.Logger 17 | 18 | func Init(configPath string) error{ 19 | GlobalItemMap = core.NewCMap() 20 | err := dotlog.StartLogService(configPath + "/dotlog.conf") 21 | if err != nil { 22 | return errors.New("log service start error => " + err.Error()) 23 | } 24 | InnerLogger = dotlog.GetLogger(_const.LoggerName_Inner) 25 | return nil 26 | } -------------------------------------------------------------------------------- /main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "flag" 5 | "fmt" 6 | _file "github.com/devfeel/dotweb-start/util/file" 7 | "os" 8 | "os/signal" 9 | "syscall" 10 | 11 | "github.com/devfeel/dotweb-start/config" 12 | "github.com/devfeel/dotweb-start/const" 13 | "github.com/devfeel/dotweb-start/core/exception" 14 | "github.com/devfeel/dotweb-start/global" 15 | "github.com/devfeel/dotweb-start/server" 16 | "github.com/devfeel/dotweb-start/task" 17 | ) 18 | 19 | var ( 20 | configFile string 21 | configPath string 22 | RunEnv string 23 | ) 24 | 25 | const ( 26 | RunEnv_Flag = "RunEnv" 27 | RunEnv_Develop = "develop" 28 | RunEnv_Test = "test" 29 | RunEnv_Production = "production" 30 | ) 31 | 32 | func main() { 33 | defer func() { 34 | if err := recover(); err != nil { 35 | ex := exception.CatchError(_const.Global_ProjectName+":main", err) 36 | global.InnerLogger.Error(fmt.Errorf("%v", err), ex.GetDefaultLogString()) 37 | os.Stdout.Write([]byte(ex.GetDefaultLogString())) 38 | } 39 | }() 40 | 41 | parseFlag() 42 | 43 | //全局初始化 44 | err := global.Init(configPath) 45 | if err != nil { 46 | panic(err) 47 | } 48 | 49 | //加载全局xml配置文件 50 | config.InitConfig(configFile) 51 | 52 | //启动Task Service 53 | task.StartTaskService(configPath) 54 | 55 | //监听系统信号 56 | //go listenSignal() 57 | 58 | //启动监听服务 59 | err = server.StartServer(configPath) 60 | if err != nil { 61 | global.InnerLogger.Error(err, "HttpServer.StartServer失败 "+err.Error()) 62 | fmt.Println("HttpServer.StartServer失败 " + err.Error()) 63 | } 64 | 65 | } 66 | 67 | func parseFlag() { 68 | RunEnv = os.Getenv(RunEnv_Flag) 69 | if RunEnv == "" { 70 | RunEnv = RunEnv_Develop 71 | } 72 | 73 | configPath = _file.GetCurrentDirectory() + "/conf/" + RunEnv 74 | //load app config 75 | flag.StringVar(&configFile, "config", "", "配置文件路径") 76 | if configFile == "" { 77 | configFile = configPath + "/app.conf" 78 | } 79 | 80 | } 81 | 82 | func listenSignal() { 83 | c := make(chan os.Signal, 1) 84 | //syscall.SIGSTOP 85 | signal.Notify(c, syscall.SIGHUP) 86 | for { 87 | s := <-c 88 | global.InnerLogger.Info("signal::ListenSignal [" + s.String() + "]") 89 | switch s { 90 | case syscall.SIGHUP: //配置重载 91 | global.InnerLogger.Info("signal::ListenSignal reload config begin...") 92 | //重新加载配置文件 93 | config.InitConfig(configFile) 94 | global.InnerLogger.Info("signal::ListenSignal reload config end") 95 | default: 96 | return 97 | } 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /protected/model/DemoInfo.go: -------------------------------------------------------------------------------- 1 | package model 2 | 3 | type DemoInfo struct { 4 | ID int 5 | DemoID int 6 | DemoName string 7 | } 8 | -------------------------------------------------------------------------------- /protected/repository/BaseRepository.go: -------------------------------------------------------------------------------- 1 | package repository 2 | 3 | import ( 4 | "github.com/devfeel/database/mssql" 5 | "github.com/devfeel/dotlog" 6 | "github.com/devfeel/dotweb-start/const" 7 | ) 8 | 9 | type BaseRepository struct { 10 | mssql.MsSqlDBContext 11 | databaseLogger dotlog.Logger 12 | } 13 | 14 | func (base *BaseRepository) InitLogger() { 15 | base.databaseLogger = dotlog.GetLogger(_const.LoggerName_Repository) 16 | base.GetCommand().SetOnTrace(base.Trace) 17 | base.GetCommand().SetOnDebug(base.Debug) 18 | base.GetCommand().SetOnInfo(base.Info) 19 | base.GetCommand().SetOnWarn(base.Warn) 20 | base.GetCommand().SetOnError(base.Error) 21 | } 22 | 23 | func (base *BaseRepository) Trace(content interface{}) { 24 | if base.databaseLogger != nil { 25 | base.databaseLogger.Trace(content) 26 | } 27 | } 28 | 29 | func (base *BaseRepository) Debug(content interface{}) { 30 | if base.databaseLogger != nil { 31 | base.databaseLogger.Debug(content) 32 | } 33 | } 34 | 35 | func (base *BaseRepository) Info(content interface{}) { 36 | if base.databaseLogger != nil { 37 | base.databaseLogger.Info(content) 38 | } 39 | } 40 | 41 | func (base *BaseRepository) Warn(content interface{}) { 42 | if base.databaseLogger != nil { 43 | base.databaseLogger.Warn(content) 44 | } 45 | } 46 | 47 | func (base *BaseRepository) Error(err error, content interface{}) { 48 | if base.databaseLogger != nil { 49 | base.databaseLogger.Error(err, content) 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /protected/repository/demo/DemoRepository.go: -------------------------------------------------------------------------------- 1 | package demo 2 | 3 | import ( 4 | "errors" 5 | "github.com/devfeel/dotweb-start/config" 6 | "github.com/devfeel/dotweb-start/protected/model" 7 | "github.com/devfeel/dotweb-start/protected/repository" 8 | "sync" 9 | ) 10 | 11 | const defaultDatabaseID = "demodb" 12 | 13 | var defaultDemoRepository *DemoRepository 14 | var demoRepositoryLocker *sync.Mutex 15 | 16 | func init() { 17 | demoRepositoryLocker = new(sync.Mutex) 18 | } 19 | 20 | type DemoRepository struct { 21 | repository.BaseRepository 22 | } 23 | 24 | // GetMessageRepository return MessageRepository which is inited 25 | func GetDemoRepository() *DemoRepository { 26 | //check default repository is init 27 | if defaultDemoRepository == nil { 28 | demoRepositoryLocker.Lock() 29 | defer demoRepositoryLocker.Unlock() 30 | if defaultDemoRepository == nil { 31 | defaultDemoRepository = NewDemoRepository() 32 | } 33 | } 34 | return defaultDemoRepository 35 | } 36 | 37 | // NewMessageRepository return new MessageRepository 38 | func NewDemoRepository() *DemoRepository { 39 | dbInfo, exists := config.GetDataBaseInfo(defaultDatabaseID) 40 | if !exists || dbInfo.ServerUrl == "" { 41 | err := errors.New("no config " + defaultDatabaseID + " database config") 42 | panic(err) 43 | } 44 | repository := new(DemoRepository) 45 | repository.Init(dbInfo.ServerUrl) 46 | repository.InitLogger() 47 | return repository 48 | } 49 | 50 | func (repository *DemoRepository) QueryDemoInfo(dest interface{}, demoId int) error { 51 | sql := "SELECT * FROM [Demo] WITH(NOLOCK) WHERE DemoID = ? " 52 | return repository.FindOne(dest, sql, demoId) 53 | } 54 | 55 | func (repository *DemoRepository) QueryTopDemoList(dest interface{}, rowCount int) error { 56 | sql := "SELECT TOP 10 * FROM [Demo] WITH(NOLOCK)" 57 | return repository.FindList(dest, sql) 58 | } 59 | 60 | func (repository *DemoRepository) InsertDemo(demo *model.DemoInfo) (n int64, err error) { 61 | sql := "INSERT INTO [Demo] ([DemoID], [DemoName]) VALUES(?,?)" 62 | return repository.Insert(sql, demo.DemoID, demo.DemoName) 63 | } 64 | 65 | func (repository *DemoRepository) QueryByPage(dest interface{}, skip, take int) error { 66 | fields := "*" 67 | tableName := "Demo" 68 | where := "" 69 | orderBy := "ID ASC, ID DESC" 70 | return repository.FindListByPage(dest, tableName, fields, where, orderBy, skip, take) 71 | } 72 | -------------------------------------------------------------------------------- /protected/service/BaseService.go: -------------------------------------------------------------------------------- 1 | package service 2 | 3 | import "github.com/devfeel/cache" 4 | 5 | type BaseService struct { 6 | RedisCache cache.RedisCache 7 | } 8 | -------------------------------------------------------------------------------- /protected/service/demo/DemoService.go: -------------------------------------------------------------------------------- 1 | package demo 2 | 3 | import ( 4 | "database/sql" 5 | "errors" 6 | "github.com/devfeel/cache" 7 | "github.com/devfeel/dotlog" 8 | "github.com/devfeel/dotweb-start/config" 9 | "github.com/devfeel/dotweb-start/const" 10 | "github.com/devfeel/dotweb-start/protected/model" 11 | "github.com/devfeel/dotweb-start/protected/repository/demo" 12 | "github.com/devfeel/dotweb-start/protected/service" 13 | "strconv" 14 | ) 15 | 16 | var ( 17 | defaultDemoRepository *demo.DemoRepository 18 | defaultLogger dotlog.Logger 19 | ) 20 | 21 | const ( 22 | defaultRedisID = "DefaultRedis" 23 | RedisKey_DemoInfoID = _const.RedisKey_ProjectPre + "DemoInfoID:" 24 | loggerName_DemoService = "DemoServiceLogger" 25 | ) 26 | 27 | type DemoService struct { 28 | service.BaseService 29 | demoRepository *demo.DemoRepository 30 | } 31 | 32 | func init() { 33 | defaultLogger = dotlog.GetLogger(loggerName_DemoService) 34 | } 35 | 36 | // NewDemoService create ConfService use default repository config 37 | func NewDemoService() *DemoService { 38 | service := &DemoService{ 39 | demoRepository: demo.GetDemoRepository(), 40 | } 41 | 42 | redisInfo, exists := config.GetRedisInfo(defaultRedisID) 43 | if !exists || redisInfo.ServerUrl == "" { 44 | err := errors.New("no config " + defaultRedisID + " redis config") 45 | panic(err) 46 | } 47 | service.RedisCache = cache.GetRedisCache(redisInfo.ServerUrl) 48 | return service 49 | } 50 | 51 | // QueryDemoInfo 根据指定DemoID查询DemoInfo 52 | func (service *DemoService) QueryDemoInfo(demoId int) (*model.DemoInfo, error) { 53 | if demoId <= 0 { 54 | return nil, errors.New("must set demoId") 55 | } 56 | result := new(model.DemoInfo) 57 | var err error 58 | redisKey := RedisKey_DemoInfoID + strconv.Itoa(demoId) 59 | //get from redis 60 | err = service.RedisCache.GetJsonObj(redisKey, result) 61 | if err == nil { 62 | return result, nil 63 | } 64 | 65 | err = service.demoRepository.QueryDemoInfo(result, demoId) 66 | if err == nil { 67 | service.RedisCache.SetJsonObj(redisKey, result) 68 | } else if err == sql.ErrNoRows { 69 | result = nil 70 | err = errors.New("not exists this demo info") 71 | } 72 | return result, err 73 | } 74 | 75 | // QueryDemoList 根据指定记录数查询记录 76 | func (service *DemoService) QueryDemoList(rowNum int) ([]*model.DemoInfo, error) { 77 | if rowNum <= 0 { 78 | return nil, errors.New("must set rowNum") 79 | } 80 | var results []*model.DemoInfo 81 | var err error 82 | err = service.demoRepository.QueryTopDemoList(&results, rowNum) 83 | if err == nil { 84 | if len(results) <= 0 { 85 | results = nil 86 | err = errors.New("not exists this demo info") 87 | } 88 | } 89 | return results, err 90 | } 91 | 92 | func (service *DemoService) AddDemo(demo *model.DemoInfo) error { 93 | if demo == nil { 94 | return errors.New("must set demoinfo") 95 | } 96 | _, err := service.demoRepository.InsertDemo(demo) 97 | defaultLogger.InfoS("AddDemo", *demo, err) 98 | return err 99 | } 100 | -------------------------------------------------------------------------------- /resources/config/develop/app.conf: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /resources/config/develop/dotlog.conf: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /resources/config/develop/dottask.conf: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /resources/config/develop/dotweb.conf: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |   9 | -------------------------------------------------------------------------------- /resources/version.yaml: -------------------------------------------------------------------------------- 1 | #version tag 2 | version:1.0 3 | -------------------------------------------------------------------------------- /server/contract/ResponseInfo.go: -------------------------------------------------------------------------------- 1 | package contract 2 | 3 | type ResponseInfo struct { 4 | RetCode int 5 | RetMsg string 6 | Message interface{} 7 | } 8 | 9 | func NewResonseInfo() *ResponseInfo { 10 | return &ResponseInfo{} 11 | } 12 | 13 | func CreateResponse(retCode int, retMsg string, message interface{}) *ResponseInfo { 14 | return &ResponseInfo{ 15 | RetCode: retCode, 16 | RetMsg: retMsg, 17 | Message: message, 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /server/handlers/demo/demo.go: -------------------------------------------------------------------------------- 1 | package demo 2 | 3 | import ( 4 | "github.com/devfeel/dotweb" 5 | "github.com/devfeel/dotweb-start/server/contract" 6 | "github.com/devfeel/dotweb-start/const" 7 | "strconv" 8 | "github.com/devfeel/dotweb-start/protected/model" 9 | "github.com/devfeel/dotweb-start/protected/service/demo" 10 | ) 11 | 12 | const ( 13 | PageSize = 20 14 | ) 15 | 16 | 17 | // QueryDemoInfo 查询Demo信息,根据传入demoid 18 | // return code: 19 | // 0 success 20 | // -1001 demoid must set 21 | // -2001 query error & err.Error() 22 | func QueryDemoInfo(ctx dotweb.Context) error { 23 | var err error 24 | response := contract.NewResonseInfo() 25 | demoId := ctx.QueryInt("demoid") 26 | demoId_param := ctx.GetRouterName("demoid") 27 | if demoId_param != ""{ 28 | demoId, err = strconv.Atoi(demoId_param) 29 | if err != nil{ 30 | demoId = 0 31 | } 32 | } 33 | 34 | if demoId <= 0{ 35 | return ctx.WriteJson(contract.CreateResponse(-1001, "demoid must set", nil)) 36 | } 37 | 38 | //query data from service 39 | demoService := demo.NewDemoService() 40 | demoInfo, err := demoService.QueryDemoInfo(demoId) 41 | if err != nil { 42 | response.RetCode = _const.ApiRetCode_ServiceError 43 | response.RetMsg = err.Error() 44 | } else { 45 | response.RetCode = _const.ApiRetCode_Ok 46 | response.RetMsg = _const.ApiRetMsg_Ok 47 | response.Message = demoInfo 48 | } 49 | return ctx.WriteJson(response) 50 | } 51 | 52 | 53 | func QueryDemoList(ctx dotweb.Context) error { 54 | var err error 55 | response := contract.NewResonseInfo() 56 | //query data from service 57 | demoService := demo.NewDemoService() 58 | demoInfo, err := demoService.QueryDemoList(10) 59 | if err != nil { 60 | response.RetCode = _const.ApiRetCode_ServiceError 61 | response.RetMsg = err.Error() 62 | } else { 63 | response.RetCode = _const.ApiRetCode_Ok 64 | response.RetMsg = _const.ApiRetMsg_Ok 65 | response.Message = demoInfo 66 | } 67 | return ctx.WriteJson(response) 68 | } 69 | 70 | func AddDemo(ctx dotweb.Context) error { 71 | var err error 72 | response := contract.NewResonseInfo() 73 | demoInfo := &model.DemoInfo{ 74 | DemoID:10000, 75 | DemoName : "demoapp", 76 | } 77 | 78 | //query data from service 79 | demoService := demo.NewDemoService() 80 | err = demoService.AddDemo(demoInfo) 81 | if err != nil { 82 | response.RetCode = _const.ApiRetCode_ServiceError 83 | response.RetMsg = err.Error() 84 | } else { 85 | response.RetCode = _const.ApiRetCode_Ok 86 | response.RetMsg = _const.ApiRetMsg_Ok 87 | response.Message = demoInfo 88 | } 89 | return ctx.WriteJson(response) 90 | } -------------------------------------------------------------------------------- /server/handlers/test/default.go: -------------------------------------------------------------------------------- 1 | package test 2 | 3 | import ( 4 | "github.com/devfeel/dotweb-start/const" 5 | "github.com/devfeel/dotweb" 6 | ) 7 | 8 | func Index(ctx dotweb.Context) error { 9 | ctx.ViewData().Set("version", _const.Global_Version) 10 | ctx.Response().SetHeader("testh", "testh-v") 11 | return ctx.WriteString("welcome to ", _const.Global_ProjectName) 12 | } 13 | -------------------------------------------------------------------------------- /server/router.go: -------------------------------------------------------------------------------- 1 | package server 2 | 3 | import ( 4 | "github.com/devfeel/dotweb" 5 | "github.com/devfeel/dotweb-start/global" 6 | 7 | "github.com/devfeel/dotweb-start/server/handlers/demo" 8 | "github.com/devfeel/dotweb-start/server/handlers/test" 9 | ) 10 | 11 | func InitRoute(server *dotweb.HttpServer) { 12 | g := server.Group("/test") 13 | g.GET("/index", test.Index) 14 | 15 | g = server.Group("/demo") 16 | g.GET("/queryinfo", demo.QueryDemoInfo) 17 | g.GET("/info/:demoid", demo.QueryDemoInfo) 18 | g.GET("/querylist", demo.QueryDemoList) 19 | g.GET("/add", demo.AddDemo) 20 | server.RegisterHandlerFunc(dotweb.RouteMethod_GET, "/task/counter", global.DotTask.CounterOutputHttpHandler) 21 | server.RegisterHandlerFunc(dotweb.RouteMethod_GET, "/task/task", global.DotTask.TaskOutputHttpHandler) 22 | } 23 | -------------------------------------------------------------------------------- /server/server.go: -------------------------------------------------------------------------------- 1 | package server 2 | 3 | import ( 4 | "github.com/devfeel/dotweb-start/global" 5 | _ "fmt" 6 | "github.com/devfeel/dotweb" 7 | "github.com/devfeel/dotweb/config" 8 | "github.com/devfeel/middleware/cors" 9 | "strconv" 10 | ) 11 | 12 | func StartServer(configPath string) error { 13 | appConfig := config.MustInitConfig(configPath + "/dotweb.conf") 14 | global.DotApp = dotweb.ClassicWithConf(appConfig) 15 | 16 | global.DotApp.SetDevelopmentMode() 17 | global.DotApp.UseRequestLog() 18 | global.DotApp.Use(cors.Middleware(cors.NewConfig().UseDefault())) 19 | 20 | //设置路由 21 | InitRoute(global.DotApp.HttpServer) 22 | 23 | global.InnerLogger.Debug("dotweb.StartServer => " + strconv.Itoa(appConfig.Server.Port)) 24 | err := global.DotApp.Start() 25 | if err != nil { 26 | panic(err) 27 | } 28 | return err 29 | } 30 | -------------------------------------------------------------------------------- /server/validate/validate.go: -------------------------------------------------------------------------------- 1 | package validate 2 | 3 | import ( 4 | "github.com/devfeel/dotweb-start/server/contract" 5 | "github.com/pkg/errors" 6 | ) 7 | 8 | func IsNilString(val string, errCode int, errMsg string) (*contract.ResponseInfo, error) { 9 | if val != "" { 10 | return contract.NewResonseInfo(), nil 11 | } else { 12 | return contract.CreateResponse(errCode, errMsg, nil), errors.New("val is nil") 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /task/service.go: -------------------------------------------------------------------------------- 1 | package task 2 | 3 | import ( 4 | "github.com/devfeel/dottask" 5 | "github.com/devfeel/dotweb-start/global" 6 | "github.com/devfeel/dotweb-start/task/tasks" 7 | "fmt" 8 | ) 9 | 10 | func registerTask(service *task.TaskService) { 11 | //TODO register task to service 12 | service.RegisterHandler("Task_Print", tasks.Task_Print) 13 | } 14 | 15 | func StartTaskService(configPath string) { 16 | global.DotTask = task.StartNewService() 17 | 18 | //register all task handler 19 | registerTask(global.DotTask) 20 | 21 | //load config file 22 | global.DotTask.LoadConfig(configPath + "/dottask.conf") 23 | 24 | //start all task 25 | global.DotTask.StartAllTask() 26 | 27 | global.InnerLogger.Debug(fmt.Sprint("StartTaskService", " ", configPath, " ", global.DotTask.PrintAllCronTask())) 28 | } 29 | 30 | func StopTaskService() { 31 | if global.DotTask != nil { 32 | global.DotTask.StopAllTask() 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /task/tasks/demo.go: -------------------------------------------------------------------------------- 1 | package tasks 2 | 3 | import ( 4 | "github.com/devfeel/dottask" 5 | "fmt" 6 | "time" 7 | ) 8 | 9 | func Task_Print(context *task.TaskContext) error { 10 | fmt.Println(time.Now(), "Task_Print", context.TaskID) 11 | return nil 12 | } 13 | -------------------------------------------------------------------------------- /util/file/files.go: -------------------------------------------------------------------------------- 1 | package _file 2 | 3 | import ( 4 | "log" 5 | "os" 6 | "path/filepath" 7 | "strings" 8 | ) 9 | 10 | func GetCurrentDirectory() string { 11 | dir, err := filepath.Abs(filepath.Dir(os.Args[0])) 12 | if err != nil { 13 | log.Fatalln(err) 14 | os.Exit(1) 15 | } 16 | return strings.Replace(dir, "\\", "/", -1) 17 | } 18 | 19 | //get filename extensions 20 | func GetFileExt(fileName string) string { 21 | if fileName == "" { 22 | return "" 23 | } else { 24 | index := strings.LastIndex(fileName, ".") 25 | if index < 0 { 26 | return "" 27 | } else { 28 | return string(fileName[index:]) 29 | } 30 | } 31 | } 32 | 33 | //check filename is exist 34 | func Exist(filename string) bool { 35 | _, err := os.Stat(filename) 36 | return err == nil || os.IsExist(err) 37 | } 38 | -------------------------------------------------------------------------------- /util/http/http.go: -------------------------------------------------------------------------------- 1 | package _http 2 | 3 | import ( 4 | "bytes" 5 | "crypto/tls" 6 | "io/ioutil" 7 | "net" 8 | "net/http" 9 | "net/url" 10 | "time" 11 | ) 12 | 13 | const ( 14 | MaxIdleConns int = 100 15 | MaxIdleConnsPerHost int = 50 16 | IdleConnTimeout int = 90 17 | InsecureSkipVerify = true 18 | ) 19 | 20 | var currClient *http.Client 21 | 22 | func getHttpClient() *http.Client { 23 | return currClient 24 | } 25 | 26 | func init() { 27 | transport := &http.Transport{ 28 | Proxy: http.ProxyFromEnvironment, 29 | DialContext: (&net.Dialer{ 30 | Timeout: 30 * time.Second, 31 | KeepAlive: 30 * time.Second, 32 | }).DialContext, 33 | MaxIdleConns: MaxIdleConns, 34 | MaxIdleConnsPerHost: MaxIdleConnsPerHost, 35 | IdleConnTimeout: time.Duration(IdleConnTimeout) * time.Second, 36 | TLSClientConfig: &tls.Config{InsecureSkipVerify: InsecureSkipVerify}, 37 | } 38 | currClient = &http.Client{Transport: transport} 39 | } 40 | 41 | func HttpGet(url string) (body string, contentType string, intervalTime int64, errReturn error) { 42 | startTime := time.Now() 43 | intervalTime = 0 44 | contentType = "" 45 | body = "" 46 | errReturn = nil 47 | 48 | resp, err := getHttpClient().Get(url) 49 | if err != nil { 50 | intervalTime = int64(time.Now().Sub(startTime) / time.Millisecond) 51 | errReturn = err 52 | return 53 | } 54 | defer resp.Body.Close() 55 | 56 | bytebody, err := ioutil.ReadAll(resp.Body) 57 | intervalTime = int64(time.Now().Sub(startTime) / time.Millisecond) 58 | if err != nil { 59 | intervalTime = int64(time.Now().Sub(startTime) / time.Millisecond) 60 | errReturn = err 61 | return 62 | } 63 | body = string(bytebody) 64 | contentType = resp.Header.Get("Content-Type") 65 | intervalTime = int64(time.Now().Sub(startTime) / time.Millisecond) 66 | return 67 | } 68 | 69 | func HttpPost(url string, postbody string, bodyType string) (body string, contentType string, intervalTime int64, errReturn error) { 70 | startTime := time.Now() 71 | intervalTime = 0 72 | contentType = "" 73 | body = "" 74 | errReturn = nil 75 | postbytes := bytes.NewBuffer([]byte(postbody)) 76 | //resp, err := currClient.Post(url, "application/x-www-form-urlencoded", postbytes) 77 | //resp, err := currClient.Post(url, "application/json", postbytes) 78 | if bodyType == "" { 79 | bodyType = "application/x-www-form-urlencoded" 80 | } 81 | resp, err := getHttpClient().Post(url, bodyType, postbytes) 82 | if err != nil { 83 | intervalTime = int64(time.Now().Sub(startTime) / time.Millisecond) 84 | errReturn = err 85 | return 86 | } 87 | defer resp.Body.Close() 88 | 89 | bytebody, err := ioutil.ReadAll(resp.Body) 90 | if err != nil { 91 | intervalTime = int64(time.Now().Sub(startTime) / time.Millisecond) 92 | errReturn = err 93 | return 94 | } 95 | body = string(bytebody) 96 | contentType = resp.Header.Get("Content-Type") 97 | intervalTime = int64(time.Now().Sub(startTime) / time.Millisecond) 98 | return 99 | 100 | } 101 | 102 | //从指定query集合获取指定key的值 103 | func GetQuery(querys url.Values, key string) string { 104 | if len(querys[key]) > 0 { 105 | return querys[key][0] 106 | } 107 | return "" 108 | } 109 | -------------------------------------------------------------------------------- /util/http/http_test.go: -------------------------------------------------------------------------------- 1 | package _http 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestHttpGet(t *testing.T) { 8 | url := "http://www.baidu.com" 9 | _, _, _, err := HttpGet(url) 10 | if err != nil { 11 | t.Error(err) 12 | } else { 13 | t.Log("HttpGet success") 14 | } 15 | } 16 | 17 | func TestHttpPost(t *testing.T) { 18 | url := "http://www.baidu.com" 19 | _, _, _, err := HttpPost(url, "", "") 20 | if err != nil { 21 | t.Error(err) 22 | } else { 23 | t.Log("HttpPost success") 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /util/json/json.go: -------------------------------------------------------------------------------- 1 | package _json 2 | 3 | import ( 4 | "encoding/json" 5 | ) 6 | 7 | //将传入对象转换为json字符串 8 | func GetJsonString(obj interface{}) string { 9 | resByte, err := json.Marshal(obj) 10 | if err != nil { 11 | return "" 12 | } 13 | return string(resByte) 14 | } 15 | 16 | //将传入对象转换为json字符串 17 | func Marshal(v interface{}) (string, error) { 18 | resByte, err := json.Marshal(v) 19 | if err != nil { 20 | return "", err 21 | } else { 22 | return string(resByte), nil 23 | } 24 | } 25 | 26 | //将传入的json字符串转换为对象 27 | func Unmarshal(jsonstring string, v interface{}) error { 28 | return json.Unmarshal([]byte(jsonstring), v) 29 | } 30 | -------------------------------------------------------------------------------- /util/rsa/rsa.go: -------------------------------------------------------------------------------- 1 | package _rsa 2 | 3 | import ( 4 | "crypto/x509" 5 | "crypto/rsa" 6 | "crypto/rand" 7 | "encoding/pem" 8 | "errors" 9 | ) 10 | 11 | // RsaEncrypt 12 | func RsaEncrypt(origData []byte, publicKey []byte) ([]byte, error) { 13 | block, _ := pem.Decode(publicKey) 14 | if block == nil { 15 | return nil, errors.New("public key error") 16 | } 17 | pubInterface, err := x509.ParsePKIXPublicKey(block.Bytes) 18 | if err != nil { 19 | return nil, err 20 | } 21 | pub := pubInterface.(*rsa.PublicKey) 22 | return rsa.EncryptPKCS1v15(rand.Reader, pub, origData) 23 | } 24 | 25 | // RsaDecrypt 26 | // key-len: 1024 27 | // PKCS#1 28 | func RsaDecrypt(ciphertext []byte, privateKey []byte) ([]byte, error) { 29 | block, _ := pem.Decode(privateKey) 30 | if block == nil { 31 | return nil, errors.New("private key error!") 32 | } 33 | priv, err := x509.ParsePKCS1PrivateKey(block.Bytes) 34 | if err != nil { 35 | return nil, err 36 | } 37 | return rsa.DecryptPKCS1v15(rand.Reader, priv, ciphertext) 38 | } 39 | 40 | -------------------------------------------------------------------------------- /util/rsa/rsa_test.go: -------------------------------------------------------------------------------- 1 | package _rsa 2 | 3 | import ( 4 | "fmt" 5 | "encoding/base64" 6 | "testing" 7 | ) 8 | 9 | var publicKey = []byte(` 10 | -----BEGIN PUBLIC KEY----- 11 | MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCGelAapImDcWTfOU3xFQedpRq8 12 | EoLcoPRa0Xu4GsmtaqS34SgmLd+NwA9VfzB0vLdcwLFEV9lsnr2aScyTVr0feac6 13 | xVIWI7SHmQLGlCw4Akb5kYpSdpHxuxfiTLYgWeAfrDw4idwvKopCmq+XQlpbzUVc 14 | +Af0egG/GyV1bQMy3wIDAQAB 15 | -----END PUBLIC KEY----- 16 | `) 17 | 18 | 19 | var privateKey = []byte(` 20 | -----BEGIN RSA PRIVATE KEY----- 21 | MIICXAIBAAKBgQCGelAapImDcWTfOU3xFQedpRq8EoLcoPRa0Xu4GsmtaqS34Sgm 22 | Ld+NwA9VfzB0vLdcwLFEV9lsnr2aScyTVr0feac6xVIWI7SHmQLGlCw4Akb5kYpS 23 | dpHxuxfiTLYgWeAfrDw4idwvKopCmq+XQlpbzUVc+Af0egG/GyV1bQMy3wIDAQAB 24 | AoGAd5OdVQOHr5SOEJvg/YUon3onWqLPMCYDAhqR+3P+bzCLxWH1lHVn+qCUQf71 25 | 9Ge2WEiTl+TR1e8VQ3Np8H3JbjmH9hHaeZN0k3fQ3LfCqB9c/J9LvSlbScWPoqZU 26 | +fTdrVG62s6330D94oeUOJdnkI7vwA5kIddAgtFhOEXP8oECQQCXGv9TcdmtNZby 27 | 8D6Zd6XGqRLNHIRKuS4GjC5Txiy0XGGibUGtS/R5VUEgORsryJJrE3Rq8Li5KCDX 28 | h16di85BAkEA49Rn7cXPhIWdACTvcs6u+vgualGgeslM+Q59Sxd+9hir+z/ZEyN7 29 | RzaHILzVORoVOvSk5zvKZ4SBFQes73j5HwJAdE05O/ai/igDGNVEuUZX+AHmEKzk 30 | Pcct36hBeAVOHzwDgcrqBAI0FrdBuxV5DkgAOh3tOuowo4J5VKpCbqxOgQJBAInQ 31 | I2nN/UBBfn3m2b0NzwTa+WCwra14dQo2vI2e0drVg7rAnXOZQ+oIzuZ7s1MONwdp 32 | kxKYtU+29EofUXmuKKsCQHAbpFRFH8sOB/F3UDFjo/yakRfiEBggikcRFOJ1jY6k 33 | C2aEY5hDv0f6EXWuyg7iw/9320wV7OPhKCW6J9FANvA= 34 | -----END RSA PRIVATE KEY----- 35 | `) 36 | 37 | 38 | func Test_RSA(t *testing.T){ 39 | raw := "ea4d35ed8fe19e11b17917ad273021_11_22_x1dd" 40 | encryptBytes, err := RsaEncrypt([]byte(raw), publicKey) 41 | if err!=nil{ 42 | t.Error("RsaEncrypt error", err) 43 | return 44 | } 45 | fmt.Println("RsaEncrypt success", base64.StdEncoding.EncodeToString(encryptBytes)) 46 | decryptBytes, err:= RsaDecrypt(encryptBytes, privateKey) 47 | if err!=nil{ 48 | t.Error("RsaDecrypt error", err) 49 | return 50 | } 51 | if raw == string(decryptBytes){ 52 | t.Log("RsaDecrypt success", raw, string(decryptBytes)) 53 | }else{ 54 | t.Error("RsaDecrypt failed", raw, string(decryptBytes)) 55 | } 56 | 57 | } 58 | -------------------------------------------------------------------------------- /util/time/time.go: -------------------------------------------------------------------------------- 1 | package _time 2 | 3 | import ( 4 | "errors" 5 | "time" 6 | ) 7 | 8 | //ParseTime 使用常用的时间格式尝试将字符串转换为time对象 9 | func ParseTime(timeStr string) (time.Time, error) { 10 | timeFormatList := []string{ 11 | time.RFC3339, 12 | "2006-01-02 15:04:05", 13 | "2006-01-02 15:04", 14 | "2006-1-2 15:04:05", 15 | "2006-1-2 15:04", 16 | "2006-1-2 15:04 MST", 17 | "2006-1-2 15:04:05 MST", 18 | "2006-01-02 15:04 MST", 19 | "2006-01-02 15:04:05 MST", 20 | "2006-01-02T15:04:05Z", 21 | "2006-1-2T15:04:05Z", 22 | "2006-01-02T15:04:05", 23 | "2006-1-2T15:04:05", 24 | "2006/01/02 15:04:05", 25 | "2006/01/02 15:04", 26 | "2006/1/2 15:04:05", 27 | "2006/1/2 15:04", 28 | "2006/1/2 15:04 MST", 29 | "2006/1/2 15:04:05 MST", 30 | "2006/01/02 15:04 MST", 31 | "2006/01/02 15:04:05 MST", 32 | "2006/01/02T15:04:05Z", 33 | "2006/1/2T15:04:05Z", 34 | "2006-1-2", 35 | "2006-01-02"} 36 | for _, format := range timeFormatList { 37 | time, err := time.ParseInLocation(format, timeStr, time.Local) 38 | if err == nil { 39 | return time, nil 40 | } 41 | } 42 | return time.Time{}, errors.New("未找到匹配的时间格式") 43 | 44 | } 45 | 46 | // ToDay 获取当前日期 47 | //一个对象,设置为当天日期,其时间组成部分设置为 00:00:00。 48 | func ToDay() time.Time { 49 | now := time.Now() 50 | time, _ := time.ParseInLocation("2006-1-2 MST", now.Format("2006-1-2 MST"), time.Local) 51 | return time 52 | } 53 | 54 | // GetMondayAndFriday 获取指定日期所在周的周一和周五 55 | func GetMondayAndFriday(date time.Time) (monday time.Time, friday time.Time) { 56 | weekDay := int(date.Weekday()) 57 | if weekDay == 0 { 58 | weekDay = 7 59 | } 60 | monday = date.AddDate(0, 0, -weekDay+1) 61 | friday = date.AddDate(0, 0, 5-weekDay) 62 | return monday, friday 63 | } 64 | 65 | // GetTimestamp 获取时间戳 毫秒级 66 | func GetTimestamp(date time.Time) (timestamp int64) { 67 | timestamp = date.UnixNano() / 1000000 68 | return timestamp 69 | } 70 | --------------------------------------------------------------------------------