Compare commits

..

135 Commits

Author SHA1 Message Date
hoteas d6ef790010 优化整体 2022-03-13 02:00:40 +08:00
hoteas 5c64580378 优化整体 2022-03-13 01:48:54 +08:00
hoteas e49164fa81 使用go mod 2022-03-13 01:12:29 +08:00
hoteas 8265e24add 使用go mod 2022-03-13 01:00:59 +08:00
hoteas 283985df52 删除无关代码 2022-03-13 00:26:01 +08:00
hoteas 95adca04bd 删除无关代码 2022-03-13 00:24:36 +08:00
hoteas 87039524a7 政企超链接开始集成 2022-03-12 23:52:42 +08:00
hoteas 66cd21c35f 政企超链接开始集成 2022-03-12 23:52:25 +08:00
hoteas 7e64131931 政企超链接开始集成 2022-03-06 23:55:14 +08:00
hoteas e30d40cfbb 政企超链接开始集成 2022-03-04 00:06:26 +08:00
hoteas 751ed0003d 政企超链接开始集成 2022-03-04 00:06:04 +08:00
hoteas 6d9f89a1d4 政企超链接开始集成 2022-03-03 21:23:57 +08:00
hoteas bc329be03b 政企超链接开始集成 2022-03-02 18:19:15 +08:00
hoteas 4597a0a50d 政企超链接开始集成 2022-03-02 12:14:07 +08:00
hoteas 3dda86d170 政企超链接开始集成 2022-02-28 19:37:52 +08:00
hoteas d847da7591 政企超链接开始集成 2022-02-28 19:08:48 +08:00
hoteas e1eca90835 政企超链接开始集成 2022-02-28 09:59:05 +08:00
hoteas 9283b8c284 政企超链接开始集成 2022-02-28 08:53:38 +08:00
hoteas d8d9afa4d2 政企超链接开始集成 2022-02-24 06:26:36 +08:00
hoteas 4d3829c345 简阳版本 2022-02-19 21:38:35 +08:00
hoteas a23037a437 简阳版本 2022-02-19 21:38:17 +08:00
hoteas 181295e54e 更新研发 2022-02-17 04:10:53 +08:00
hoteas 8cc2499e21 更新研发 2022-02-14 19:11:38 +08:00
hoteas a2c49452b4 更新研发 2022-02-14 19:10:58 +08:00
hoteas ebf0df5ca8 更新研发 2022-01-27 23:41:40 +08:00
hoteas 73bf691ccc 更新研发 2022-01-26 11:45:17 +08:00
hoteas b2e9701826 更新研发 2022-01-23 05:13:19 +08:00
hoteas 789b0a14d1 更新研发 2022-01-22 16:12:02 +08:00
hoteas 3ee64fcd8c 更新研发 2022-01-20 07:15:14 +08:00
hoteas 527503b0d9 企业画像 2022-01-19 05:38:49 +08:00
hoteas a95b2fccd7 更新研发 2022-01-17 04:47:39 +08:00
hoteas 7e2abb43e3 权限模块开发 2022-01-12 17:33:20 +08:00
hoteas 48fd753a96 权限模块开发 2022-01-10 13:23:39 +08:00
hoteas 136232dd57 修复太过于严格的bug 2022-01-03 01:42:35 +08:00
hoteas 008f19355c 增加自适应模式 2021-12-31 02:38:51 +08:00
hoteas 1fc0a5bbbc 增加自适应模式 2021-12-30 22:19:52 +08:00
hoteas ce099b8fc8 增加自适应模式 2021-12-29 00:46:07 +08:00
hoteas 9c00ac6ba1 增加自适应模式 2021-12-28 09:26:26 +08:00
hoteas a5c002bbce 增加自适应模式 2021-12-27 21:30:33 +08:00
hoteas cf50a699a6 增加自适应模式 2021-12-27 21:30:24 +08:00
hoteas 662003c0ca 增加自适应模式 2021-12-27 20:40:16 +08:00
hoteas f24de2562a 优化系统 2021-12-27 18:21:41 +08:00
hoteas b84bd7e16f 优化系统 2021-12-27 14:09:49 +08:00
hoteas 2fb6abf53a Merge branch 'master' into myhs
# Conflicts:
#	example/admin/init.go
#	example/bzyy.exe
#	example/main.go
2021-12-27 14:02:39 +08:00
hoteas 2eab29f428 优化系统 2021-12-27 14:01:04 +08:00
hoteas 84ee0d259f 优化系统 2021-12-27 14:00:08 +08:00
hoteas eccab42fc8 优化系统 2021-12-18 00:07:35 +08:00
hoteas 1465ba36d3 优化系统 2021-12-17 14:37:41 +08:00
hoteas 8380b097b2 调试 2021-12-17 01:21:08 +08:00
hoteas 6b8f901163 调试 2021-12-16 13:40:19 +08:00
hoteas bb16f0a75b 调试 2021-12-16 13:24:31 +08:00
hoteas 84dbc5d71e 出入库完成 2021-12-16 10:49:35 +08:00
hoteas 166eeee64c 出入库完成 2021-12-15 09:24:41 +08:00
hoteas 7a649fd652 出入库完成 2021-12-15 05:56:31 +08:00
hoteas 94ae568526 书写前端接口 2021-12-12 04:22:30 +08:00
hoteas 9ec597f26c 书写前端接口 2021-12-11 23:53:47 +08:00
hoteas 388bc5006d 书写前端代码 2021-12-11 17:59:02 +08:00
hoteas 0e33c2ad9d ocr增加 2021-12-09 11:16:15 +08:00
hoteas af726fbcfb ocr增加 2021-12-09 10:58:53 +08:00
hoteas 1e82a5964d 优化makecode 2021-11-29 03:27:07 +08:00
hoteas d62ba8b0cd 优化makecode 2021-11-23 18:31:00 +08:00
hoteas 320ebe25ec 优化makecode 2021-11-18 12:22:14 +08:00
hoteas 68257d1742 绵阳宏升代码优化 2021-11-15 03:35:13 +08:00
hoteas 80d167cb1b 绵阳宏升代码优化 2021-11-15 03:34:45 +08:00
hoteas cd911e8fa4 巴中代码提交 2021-11-15 03:32:50 +08:00
hoteas faa6fcb00c 初次提交 2021-11-15 03:30:21 +08:00
hoteas 836c1f461f 初次提交 2021-11-15 03:28:14 +08:00
hoteas 97b2f54383 初次提交 2021-11-15 03:26:54 +08:00
hoteas 9d5f8438c5 初次提交 2021-11-13 21:06:29 +08:00
hoteas 3f7963e7cf 初次提交 2021-11-08 09:16:28 +08:00
hoteas 269df85d27 初次提交 2021-11-08 09:15:52 +08:00
hoteas d28c6863e4 初次提交 2021-11-08 06:50:37 +08:00
hoteas bba4990ccc 完善访问日志 2021-11-08 06:49:34 +08:00
hoteas c57afd6a5d 修复短信发送bug 2021-10-27 00:27:24 +08:00
hoteas 25f355c8d0 增加天府通办登录 2021-10-25 23:18:27 +08:00
hoteas b1b0673e69 修复bug 2021-10-21 23:20:58 +08:00
hoteas 72c086d726 修复bug 2021-10-21 23:19:32 +08:00
hoteas 3810ba6c0b 修复bug 2021-10-21 22:52:40 +08:00
hoteas 5c775b4539 修复bug 2021-10-18 04:49:55 +08:00
hoteas deb3e54cc3 修复bug 2021-09-25 04:36:07 +08:00
hoteas d1a8f6c668 短信变更 2021-09-24 15:01:03 +08:00
hoteas 2291ba7402 巴中恩阳适配 2021-09-24 10:49:07 +08:00
hoteas 20390091f2 巴中恩阳适配 2021-09-17 04:45:43 +08:00
hoteas 123d819b0f 开始新增代码生成配置2.0功能,配置文件格式规定完成 2021-09-17 04:00:49 +08:00
hoteas 30e275a27d 开始新增代码生成配置2.0功能,配置文件格式规定完成 2021-09-16 04:33:10 +08:00
hoteas 1a53f587e8 增加表关联新建功能,同时修复数据库bug 2021-09-12 06:14:01 +08:00
hoteas 9c3ba81135 测试 2021-09-12 05:35:14 +08:00
hoteas 62cf625fe9 增加表关联新建功能,同时修复数据库bug 2021-08-30 07:36:17 +08:00
hoteas e1f4876621 增加表关联新建功能,同时修复数据库bug 2021-08-29 06:08:19 +08:00
hoteas b480659a22 增加表关联新建功能,同时修复数据库bug 2021-08-28 13:06:00 +08:00
hoteas 09b1d37ae3 增加表关联新建功能,同时修复数据库bug 2021-08-28 13:05:12 +08:00
hoteas 47b28e7b57 开始新增代码生成配置2.0功能,配置文件格式规定完成 2021-07-21 00:55:59 +08:00
hoteas 9cd7ad34b3 修复浏览器cookie不识别 2021-07-21 00:09:13 +08:00
hoteas d736a74198 增加表关联新建功能,同时修复数据库bug 2021-07-14 00:48:34 +08:00
hoteas ada4a926c0 增加表关联新建功能,同时修复数据库bug 2021-07-07 04:08:40 +08:00
hoteas 4ad401bafc 增加上传接口 2021-07-05 02:20:10 +08:00
hoteas 05c8159601 增加上传接口 2021-07-04 04:03:29 +08:00
hoteas efb6cb980e 优化 2021-06-18 04:56:22 +08:00
hoteas 00ad6487b6 加入树节点功能 2021-06-16 06:10:57 +08:00
hoteas 9aa836a72c 加入树节点功能 2021-06-14 01:19:05 +08:00
hoteas 9ea6082d04 接入搜索功能 2021-06-13 10:40:19 +08:00
hoteas 9e595ab6e8 接入搜索功能 2021-06-13 09:53:37 +08:00
hoteas 8b6dd5fdad 接入搜索功能 2021-06-13 03:08:43 +08:00
hoteas 5c8df885a2 优化表单生成规则 2021-06-12 13:33:35 +08:00
hoteas cc4d91cdbb 优化表单生成规则 2021-06-11 09:41:23 +08:00
hoteas 32167d4721 增加menu自动化添加功能 2021-06-11 08:06:44 +08:00
hoteas 1077f09755 优化代码 2021-06-07 11:32:47 +08:00
hoteas 642bf97272 优化代码 2021-06-06 07:50:58 +08:00
hoteas 4038598470 优化代码 2021-06-06 02:27:22 +08:00
hoteas 79453d4d2a 生成代码,逐步进行优化 2021-06-05 02:18:56 +08:00
hoteas 6aa2b74840 生成代码,逐步进行优化 2021-06-04 10:05:07 +08:00
hoteas a003612810 生成代码,逐步进行优化 2021-06-04 10:04:37 +08:00
hoteas d6c11a5d93 已经接入配置文件,开始准备生成代码 2021-06-04 03:03:48 +08:00
hoteas fe085ce889 已经接入配置文件,开始准备生成代码 2021-06-04 02:57:56 +08:00
hoteas 99933e02f4 引入数据库,代码,配置文件三位一体内容,准备进行一体化配置 2021-06-03 05:31:09 +08:00
hoteas 9af232840c 接入RESTfull风格接口 2021-05-30 00:10:07 +08:00
hoteas 465ea889a2 接入RESTfull风格接口 2021-05-30 00:01:15 +08:00
hoteas c46fdd8985 接入RESTfull风格接口 2021-05-29 02:57:03 +08:00
hoteas 9fd0a5fd61 完善error库 2021-05-29 00:54:27 +08:00
hoteas 95489fcf49 完善error库 2021-05-29 00:41:17 +08:00
hoteas 0e2932ca89 完善error库 2021-05-29 00:37:20 +08:00
hoteas 764d88894e 完善error库 2021-05-29 00:15:13 +08:00
hoteas 339302956a 缓存测试成功 2021-05-28 23:48:33 +08:00
hoteas 1101937028 缓存驱动更换成功,支持3级缓存,memory,以及db 2021-05-28 22:52:22 +08:00
hoteas fc315064e7 optimize log tool 2021-05-25 20:27:24 +08:00
hoteas 740059075a optimize log tool 2021-05-25 19:53:34 +08:00
hoteas 770f0a94c9 optimize log tool 2021-05-25 05:28:56 +08:00
hoteas df07afb744 use logrus to project default log tools 2021-05-25 05:08:17 +08:00
hoteas 9bc930750d 整个包结构重构 2021-05-24 07:27:41 +08:00
hoteas 77ded19742 move redis code to package hotime 2021-05-24 06:16:32 +08:00
hoteas 2632517fab mysql add master and slave mode 2021-05-24 06:14:58 +08:00
hoteas c8e926446e add cache to framework 2021-05-24 05:47:56 +08:00
hoteas 253f836571 调整配置项设置 2021-05-23 03:35:49 +08:00
hoteas babf6595ee 测试demo调整 2021-05-22 04:52:03 +08:00
hoteas 91dc207a78 增加readme文件和授权文件 2021-04-30 00:27:12 +08:00
54 changed files with 4621 additions and 1513 deletions
+2 -1
View File
@@ -1,2 +1,3 @@
/.idea/*
.idea
.idea
/example/config/app.json
+208
View File
@@ -0,0 +1,208 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION,
AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction, and distribution
as defined by Sections 1 through 9 of that document.
"Licensor" shall mean the copyright owner or entity authorized by the copyright
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 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.
"You" (or "Your") shall mean an individual or Legal Entity exercising permissions
granted by that License.
"Source" form shall mean the preferred form for making modifications, including
but not limited to software source code, documentation source, and configuration
files.
"Object" form shall mean any form resulting from mechanical transformation
or translation of a Source form, including but not limited to compiled object
code, generated documentation, and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or Object form,
made available under the License, as indicated by a copyright notice that
is included in or attached to the work (an example is provided in the Appendix
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 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.
"Contribution" shall mean any work of authorship, including the original version
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 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
issue tracking systems that are managed by, or on behalf of, the Licensor
for the purpose of discussing and improving the Work, but excluding communication
that is conspicuously marked or otherwise designated in writing by the copyright
owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity on behalf
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 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 that License,
each Contributor hereby grants to You a perpetual, worldwide, non-exclusive,
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)
alone or by combination of their Contribution(s) with the Work to which such
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 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
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 that License; and
(b) You must cause any modified files to carry prominent notices stating that
You changed the files; and
(c) You must retain, in the Source form of any Derivative Works that You distribute,
all copyright, patent, trademark, and attribution notices from the Source
form of the Work, excluding those notices that do not pertain to any part
of the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its distribution,
then any Derivative Works that You distribute must include a readable copy
of the attribution notices contained within such NOTICE file, excluding those
notices that do not pertain to any part of the Derivative Works, in at least
one of the following places: within a NOTICE text file distributed as part
of the Derivative Works; within the Source form or documentation, if provided
along with the Derivative Works; or, within a display generated by the Derivative
Works, if and wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and do not modify the
License. You may add Your own attribution notices within Derivative Works
that You distribute, alongside or as an addendum to the NOTICE text from the
Work, provided that such additional attribution notices cannot be construed
as modifying the License.
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 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 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.
6. Trademarks. that License does not grant permission to use the trade names,
trademarks, service marks, or product names of the Licensor, except as required
for reasonable and customary use in describing the origin of the Work and
reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or agreed to
in writing, Licensor provides the Work (and each Contributor provides its
Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
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 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 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
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 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
asserted against, such Contributor by reason of your accepting any such warranty
or additional liability. END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following boilerplate
notice, with the fields enclosed by brackets "[]" replaced with your own identifying
information. (Don't include the brackets!) The text should be enclosed in
the appropriate comment syntax for the file format. We also recommend that
a file or class name and description of purpose be included on the same "printed
page" as the copyright notice for easier identification within third-party
archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use that file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
+6
View File
@@ -0,0 +1,6 @@
# hotime
golang web服务框架
支持数据库dbmysql、sqlite3
支持缓存cacheredismemory,数据库
自带工具类,上下文,以及session等功能
+470 -175
View File
@@ -1,9 +1,14 @@
package hotime
import (
"bytes"
. "code.hoteas.com/golang/hotime/cache"
"code.hoteas.com/golang/hotime/code"
. "code.hoteas.com/golang/hotime/common"
. "code.hoteas.com/golang/hotime/db"
. "code.hoteas.com/golang/hotime/log"
"database/sql"
"encoding/json"
"github.com/sirupsen/logrus"
"io"
"io/ioutil"
"net/http"
"net/url"
@@ -11,61 +16,71 @@ import (
"path/filepath"
"strconv"
"strings"
"time"
)
type Application struct {
*code.MakeCode
MakeCodeRouter Router
MethodRouter
Router
contextBase
ContextBase
Error
Log *logrus.Logger
WebConnectLog *logrus.Logger
Port string //端口号
TLSPort string //ssl访问端口号
connectListener []func(this *Context) bool //所有的访问监听,true按原计划继续使用,false表示有监听器处理
connectDbFunc func(err ...*Error) *sql.DB
connectListener []func(that *Context) bool //所有的访问监听,true按原计划继续使用,false表示有监听器处理
connectDbFunc func(err ...*Error) (master, slave *sql.DB)
configPath string
Config Map
Db HoTimeDB
Server *http.Server
CacheIns
sessionLong CacheIns
sessionShort CacheIns
*HoTimeCache
*http.Server
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.HoTimeCache == nil {
that.SetCache()
}
//防止手动设置session误伤
if this.sessionShort == nil && this.sessionLong == nil {
if this.connectDbFunc == nil {
this.SetSession(CacheIns(&CacheMemory{}), nil)
} else {
this.SetSession(CacheIns(&CacheMemory{}), CacheIns(&CacheDb{Db: &this.Db, Time: this.Config.GetInt64("cacheLongTime")}))
}
//if that.sessionShort == nil && that.sessionLong == nil {
// if that.connectDbFunc == nil {
// that.SetSession(CacheIns(&CacheMemory{}), nil)
// } else {
// that.SetSession(CacheIns(&CacheMemory{}), CacheIns(&CacheDb{Db: &that.Db, Time: that.Config.GetInt64("cacheLongTime")}))
// }
//
//}
//that.Router = router
if that.Router == nil {
that.Router = Router{}
}
for k, v := range router {
that.Router[k] = v
}
this.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 {
for pk, pv := range router {
if that.Router != nil {
for pk, pv := range that.Router {
if !modeRouterStrict {
pk = strings.ToLower(pk)
}
@@ -79,7 +94,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
}
}
}
@@ -87,181 +102,173 @@ 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 this.CacheIns == nil {
this.CacheIns = CacheIns(&CacheMemory{Map: Map{}, Time: this.Config.GetInt64("cacheShortTime")})
if that.connectDbFunc != nil && (that.Db.DB == nil || that.Db.DB.Ping() != nil) {
that.Db.SetConnect(that.connectDbFunc)
}
//异常处理
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) *sql.DB) {
// SetConnectDB 启动实例
func (that *Application) SetConnectDB(connect func(err ...*Error) (master, slave *sql.DB)) {
//this.Db.DBCached=false
//if this.Config.GetCeilInt("dbCached")!=0{
// this.Db.DBCached=true
//}
that.connectDbFunc = connect
this.connectDbFunc = connect
this.Db.SetConnect(this.connectDbFunc)
this.Db.DBCached = false
if this.Config.GetCeilInt("dbCached") != 0 {
this.Db.DBCached = true
}
this.Db.Type = this.Config.GetString("dbType")
that.Db.SetConnect(that.connectDbFunc, &that.Error)
}
//设置配置文件路径全路径或者相对路径
func (this *Application) SetSession(short CacheIns, Long CacheIns) {
this.sessionLong = Long
this.sessionShort = short
}
//默认配置缓存和session实现
func (this *Application) SetDefault(connect func(err ...*Error) *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) {
this.CacheIns = cache
// SetCache 设置配置文件路径全路径或者相对路径
func (that *Application) SetCache() {
cacheIns := HoTimeCache{}
cacheIns.Init(that.Config.GetMap("cache"), HoTimeDBInterface(&that.Db), &that.Error)
that.HoTimeCache = &cacheIns
//mode生产模式开启的时候才开启数据库缓存,防止调试出问题
if that.Config.GetInt("mode") == 0 {
that.Db.HoTimeCache = &cacheIns
}
}
//设置配置文件路径全路径或者相对路径
func (this *Application) SetConfig(configPath ...string) {
// SetConfig 设置配置文件路径全路径或者相对路径
func (that *Application) SetConfig(configPath ...string) {
that.Log = GetLog("", true)
that.Error = Error{Logger: that.Log}
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("配置文件不存在,或者配置出错,使用缺省默认配置")
}
that.Log = GetLog(that.Config.GetString("logFile"), true)
that.Error = Error{Logger: that.Log}
if that.Config.Get("webConnectLogShow") == nil || that.Config.GetBool("webConnectLogShow") {
that.WebConnectLog = GetLog(that.Config.GetString("webConnectLogFile"), false)
}
//文件如果损坏则不写入配置防止配置文件数据丢失
if this.Error.GetError() == nil {
var configByte bytes.Buffer
if that.Error.GetError() == nil {
//var configByte bytes.Buffer
err = json.Indent(&configByte, []byte(this.Config.ToJsonString()), "", "\t")
//判断配置文件是否序列有变化有则修改配置,五则不变
//判断配置文件是否序列有变化,有则修改配置,无则不变
//fmt.Println(len(btes))
if len(btes) != 0 && configByte.String() == string(btes) {
configStr := that.Config.ToJsonString()
if len(btes) != 0 && configStr == string(btes) {
return
}
//写入配置说明
var configNoteByte bytes.Buffer
json.Indent(&configNoteByte, []byte(ConfigNote.ToJsonString()), "", "\t")
//var configNoteByte bytes.Buffer
configNoteStr := ConfigNote.ToJsonString()
//_ = 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, []byte(configStr), os.ModePerm)
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", []byte(configNoteStr), os.ModePerm)
}
}
//连接判断,返回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(that *Context) bool) {
that.connectListener = append(that.connectListener, lis)
}
//网络错误
//func (this *Application) session(w http.ResponseWriter, req *http.Request) {
//func (that *Application) session(w http.ResponseWriter, req *http.Request) {
//
//}
//序列化链接
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)
@@ -282,9 +289,10 @@ 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) {
nowUnixTime := time.Now()
_, s := this.urlSer(req.RequestURI)
_, s := that.urlSer(req.RequestURI)
//获取cookie
// 如果cookie存在直接将sessionId赋值为cookie.Value
// 如果cookie不存在就查找传入的参数中是否有token
@@ -292,20 +300,24 @@ 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
if err != nil || (len(token) == 32 && cookie.Value != token) {
if len(token) == 32 {
sessionId = token
}
//else{
// isFirst=true;
//}
http.SetCookie(w, &http.Cookie{Name: this.Config.GetString("sessionName"), Value: sessionId, Path: "/"})
} else {
needSetCookie := ""
token := req.Header.Get("Authorization")
if len(token) != 32 {
token = req.FormValue("token")
}
//没有cookie或者cookie不等于token
//有token优先token
if len(token) == 32 {
sessionId = token
//没有token,则查阅session
} else if err == nil && cookie.Value != "" {
sessionId = cookie.Value
//session也没有则判断是否创建cookie
} else {
needSetCookie = sessionId
}
unescapeUrl, err := url.QueryUnescape(req.RequestURI)
@@ -313,32 +325,44 @@ func (this *Application) handler(w http.ResponseWriter, req *http.Request) {
unescapeUrl = req.RequestURI
}
//访问实例
context := Context{SessionIns: SessionIns{SessionId: sessionId,
LongCache: this.sessionLong,
ShortCache: this.sessionShort,
},
CacheIns: this.CacheIns,
Resp: w, Req: req, Application: this, RouterString: s, Config: this.Config, Db: &this.Db, HandlerStr: unescapeUrl}
context := Context{SessionIns: SessionIns{SessionId: sessionId, HoTimeCache: that.HoTimeCache},
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)
//是否展示日志
if this.Config.GetInt("connectLogShow") != 0 {
logFmt(Substr(context.Req.RemoteAddr, 0, strings.Index(context.Req.RemoteAddr, ":"))+" "+context.HandlerStr, 0, LOG_INFO)
}
that.crossDomain(&context, needSetCookie)
defer func() {
//是否展示日志
if that.WebConnectLog != nil {
ipStr := Substr(context.Req.RemoteAddr, 0, strings.Index(context.Req.RemoteAddr, ":"))
//负载均衡优化
if ipStr == "127.0.0.1" {
if req.Header.Get("X-Forwarded-For") != "" {
ipStr = req.Header.Get("X-Forwarded-For")
} else if req.Header.Get("X-Real-IP") != "" {
ipStr = req.Header.Get("X-Real-IP")
}
}
that.WebConnectLog.Infoln(ipStr, context.Req.Method,
"time cost:", ObjToFloat64(time.Now().UnixNano()-nowUnixTime.UnixNano())/1000000.00, "ms",
"data length:", ObjToFloat64(context.DataSize)/1000.00, "KB", 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
@@ -347,37 +371,26 @@ 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 {
// //控制层
// this.Router[s[0]][s[1]][s[2]](&context)
// //header.Set("Content-Type", "text/html; charset=utf-8")
// context.View()
// return
// }
//
//}
//验证接口严格模式
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)
@@ -401,12 +414,20 @@ 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("mode") == 0 {
header.Set("Cache-Control", "public")
} else {
header.Set("Cache-Control", "no-cache")
}
if strings.Index(path, ".m3u8") != -1 {
header.Add("Content-Type", "audio/mpegurl")
t := strings.LastIndex(path, ".")
if t != -1 {
tt := path[t:]
if MimeMaps[tt] != "" {
header.Add("Content-Type", MimeMaps[tt])
}
}
//w.Write(data)
@@ -414,32 +435,66 @@ func (this *Application) handler(w http.ResponseWriter, req *http.Request) {
}
func (this *Application) crossDomain(context *Context) {
func (that *Application) crossDomain(context *Context, sessionId string) {
//没有跨域设置
if context.Config.GetString("crossDomain") == "" {
if sessionId != "" {
http.SetCookie(context.Resp, &http.Cookie{Name: that.Config.GetString("sessionName"), Value: sessionId, Path: "/"})
}
return
}
header := context.Resp.Header()
header.Set("Access-Control-Allow-Origin", "*")
header.Set("Access-Control-Allow-Methods", "*")
header.Set("Access-Control-Allow-Credentials", "true")
header.Set("Access-Control-Expose-Headers", "*")
header.Set("Access-Control-Allow-Headers", "X-Requested-With,Content-Type,Access-Token")
if context.Config.GetString("crossDomain") != "*" {
header.Set("Access-Control-Allow-Origin", this.Config.GetString("crossDomain"))
//不跨域,则不设置
remoteHost := context.Req.Host
if context.Config.GetString("port") == "80" || context.Config.GetString("port") == "443" {
remoteHost = remoteHost + ":" + context.Config.GetString("port")
}
if context.Config.GetString("crossDomain") != "auto" {
//不跨域,则不设置
if strings.Contains(context.Config.GetString("crossDomain"), remoteHost) {
if sessionId != "" {
http.SetCookie(context.Resp, &http.Cookie{Name: that.Config.GetString("sessionName"), Value: sessionId, Path: "/"})
}
return
}
header.Set("Access-Control-Allow-Origin", that.Config.GetString("crossDomain"))
// 后端设置,2592000单位秒,这里是30天
header.Set("Access-Control-Max-Age", "2592000")
//header.Set("Access-Control-Allow-Origin", "*")
header.Set("Access-Control-Allow-Methods", "GET,POST,OPTIONS,PUT,DELETE")
header.Set("Access-Control-Allow-Credentials", "true")
header.Set("Access-Control-Expose-Headers", "*")
header.Set("Access-Control-Allow-Headers", "X-Requested-With,Content-Type,Access-Token")
if sessionId != "" {
//跨域允许需要设置cookie的允许跨域https才有效果
context.Resp.Header().Set("Set-Cookie", that.Config.GetString("sessionName")+"="+sessionId+"; Path=/; SameSite=None; Secure")
}
return
}
origin := context.Req.Header.Get("Origin")
if origin != "" {
header.Set("Access-Control-Allow-Origin", origin)
refer := context.Req.Header.Get("Referer")
if (origin != "" && strings.Contains(origin, remoteHost)) || strings.Contains(refer, remoteHost) {
if sessionId != "" {
http.SetCookie(context.Resp, &http.Cookie{Name: that.Config.GetString("sessionName"), Value: sessionId, Path: "/"})
}
return
}
refer := context.Req.Header.Get("Referer")
if refer != "" {
if origin != "" {
header.Set("Access-Control-Allow-Origin", origin)
//return
} else if refer != "" {
tempInt := 0
lastInt := strings.IndexFunc(refer, func(r rune) bool {
if r == '/' && tempInt > 8 {
@@ -454,5 +509,245 @@ func (this *Application) crossDomain(context *Context) {
}
refer = Substr(refer, 0, lastInt)
header.Set("Access-Control-Allow-Origin", refer)
//header.Set("Access-Control-Allow-Origin", "*")
}
header.Set("Access-Control-Allow-Methods", "GET,POST,OPTIONS,PUT,DELETE")
header.Set("Access-Control-Allow-Credentials", "true")
header.Set("Access-Control-Expose-Headers", "*")
header.Set("Access-Control-Allow-Headers", "X-Requested-With,Content-Type,Access-Token")
if sessionId != "" {
//跨域允许需要设置cookie的允许跨域https才有效果
context.Resp.Header().Set("Set-Cookie", that.Config.GetString("sessionName")+"="+sessionId+"; Path=/; SameSite=None; Secure")
}
}
//Init 初始化application
func Init(config string) Application {
appIns := Application{}
//手动模式,
appIns.SetConfig(config)
SetDB(&appIns)
appIns.SetCache()
appIns.MakeCode = &code.MakeCode{}
codeConfig := appIns.Config.GetMap("codeConfig")
appIns.MakeCodeRouter = Router{}
if codeConfig != nil {
for k, _ := range codeConfig {
if appIns.Config.GetInt("mode") == 2 {
appIns.MakeCode.Db2JSON(k, codeConfig.GetString(k), &appIns.Db, true)
appIns.MakeCodeRouter[k] = Proj{}
} else if appIns.Config.GetInt("mode") == 3 {
appIns.MakeCode.Db2JSON(k, codeConfig.GetString(k), &appIns.Db, false)
appIns.MakeCodeRouter[k] = Proj{}
} else {
appIns.MakeCode.Db2JSON(k, codeConfig.GetString(k), nil, false)
appIns.MakeCodeRouter[k] = Proj{}
}
//接入动态代码层
if appIns.Router == nil {
appIns.Router = Router{}
}
appIns.Router[k] = TptProject
for k1, _ := range appIns.MakeCode.TableColumns {
appIns.Router[k][k1] = appIns.Router[k]["hotimeCommon"]
}
setMakeCodeLintener(k, &appIns)
}
}
return appIns
}
// SetDB 智能数据库设置
func SetDB(appIns *Application) {
db := appIns.Config.GetMap("db")
dbSqlite := db.GetMap("sqlite")
dbMysql := db.GetMap("mysql")
if db != nil && dbSqlite != nil {
SetSqliteDB(appIns, dbSqlite)
}
if db != nil && dbMysql != nil {
SetMysqlDB(appIns, dbMysql)
}
}
func SetMysqlDB(appIns *Application, config Map) {
appIns.Db.Type = "mysql"
appIns.Db.DBName = config.GetString("name")
appIns.Db.Prefix = config.GetString("prefix")
appIns.SetConnectDB(func(err ...*Error) (master, slave *sql.DB) {
//master数据库配置
query := config.GetString("user") + ":" + config.GetString("password") +
"@tcp(" + config.GetString("host") + ":" + config.GetString("port") + ")/" + config.GetString("name") + "?charset=utf8"
DB, e := sql.Open("mysql", query)
if e != nil && len(err) != 0 {
err[0].SetError(e)
}
master = DB
//slave数据库配置
configSlave := config.GetMap("slave")
if configSlave != nil {
query := configSlave.GetString("user") + ":" + configSlave.GetString("password") +
"@tcp(" + config.GetString("host") + ":" + configSlave.GetString("port") + ")/" + configSlave.GetString("name") + "?charset=utf8"
DB1, e := sql.Open("mysql", query)
if e != nil && len(err) != 0 {
err[0].SetError(e)
}
slave = DB1
}
return master, slave
//return DB
})
}
func SetSqliteDB(appIns *Application, config Map) {
appIns.Db.Type = "sqlite"
appIns.Db.Prefix = config.GetString("prefix")
appIns.SetConnectDB(func(err ...*Error) (master, slave *sql.DB) {
db, e := sql.Open("sqlite3", config.GetString("path"))
if e != nil && len(err) != 0 {
err[0].SetError(e)
}
master = db
return master, slave
})
}
func setMakeCodeLintener(name string, appIns *Application) {
appIns.SetConnectListener(func(context *Context) bool {
if len(context.RouterString) < 2 || appIns.MakeCodeRouter[context.RouterString[0]] == nil {
return true
}
if len(context.RouterString) > 1 && context.RouterString[0] == name {
if context.RouterString[1] == "hotime" && context.RouterString[2] == "login" {
return true
}
if context.RouterString[1] == "hotime" && context.RouterString[2] == "logout" {
return true
}
if context.Session(name+"_id").Data == nil {
context.Display(2, "你还没有登录")
return false
}
}
//文件上传接口
if len(context.RouterString) == 1 && context.RouterString[0] == "file" && context.Req.Method == "POST" {
if context.Session(name+"_id").Data == nil {
context.Display(2, "你还没有登录")
return false
}
//读取网络文件
fi, fheader, err := context.Req.FormFile("file")
if err != nil {
context.Display(3, err)
return false
}
filePath := context.Config.GetString("filePath")
if filePath == "" {
filePath = "file/2006/01/02/"
}
path := time.Now().Format(filePath)
e := os.MkdirAll(context.Config.GetString("tpt")+"/"+path, os.ModeDir)
if e != nil {
context.Display(3, e)
return false
}
filePath = path + Md5(ObjToStr(RandX(100000, 9999999))) + fheader.Filename[strings.LastIndex(fheader.Filename, "."):]
newFile, e := os.Create(context.Config.GetString("tpt") + "/" + filePath)
if e != nil {
context.Display(3, e)
return false
}
_, e = io.Copy(newFile, fi)
if e != nil {
context.Display(3, e)
return false
}
context.Display(0, filePath)
return false
}
if len(context.RouterString) < 2 || len(context.RouterString) > 3 ||
!(context.Router[context.RouterString[0]] != nil &&
context.Router[context.RouterString[0]][context.RouterString[1]] != nil) {
return true
}
//排除无效操作
if len(context.RouterString) == 2 &&
context.Req.Method != "GET" &&
context.Req.Method != "POST" {
return true
}
//列表检索
if len(context.RouterString) == 2 &&
context.Req.Method == "GET" {
if context.Router[context.RouterString[0]][context.RouterString[1]]["search"] == nil {
return true
}
context.Router[context.RouterString[0]][context.RouterString[1]]["search"](context)
}
//新建
if len(context.RouterString) == 2 &&
context.Req.Method == "POST" {
if context.Router[context.RouterString[0]][context.RouterString[1]]["add"] == nil {
return true
}
context.Router[context.RouterString[0]][context.RouterString[1]]["add"](context)
}
if len(context.RouterString) == 3 &&
context.Req.Method == "POST" {
return true
}
//查询单条
if len(context.RouterString) == 3 &&
context.Req.Method == "GET" {
if context.Router[context.RouterString[0]][context.RouterString[1]]["info"] == nil {
return true
}
context.Router[context.RouterString[0]][context.RouterString[1]]["info"](context)
}
//更新
if len(context.RouterString) == 3 &&
context.Req.Method == "PUT" {
if context.Router[context.RouterString[0]][context.RouterString[1]]["update"] == nil {
return true
}
context.Router[context.RouterString[0]][context.RouterString[1]]["update"](context)
}
//移除
if len(context.RouterString) == 3 &&
context.Req.Method == "DELETE" {
if context.Router[context.RouterString[0]][context.RouterString[1]]["remove"] == nil {
return true
}
context.Router[context.RouterString[0]][context.RouterString[1]]["remove"](context)
}
context.View()
return false
})
}
+277
View File
@@ -0,0 +1,277 @@
package cache
import (
. "code.hoteas.com/golang/hotime/common"
"errors"
)
// HoTimeCache 可配置memorydbredis,默认启用memory,默认优先级为memory>redis>db,memory与数据库缓存设置项一致,
//缓存数据填充会自动反方向反哺,加入memory缓存过期将自动从redis更新,但memory永远不会更新redis,如果是集群建议不要开启memory,配置即启用
type HoTimeCache struct {
*Error
dbCache *CacheDb
redisCache *CacheRedis
memoryCache *CacheMemory
Config Map
}
func (that *HoTimeCache) Session(key string, data ...interface{}) *Obj {
var reData *Obj
if len(data) == 0 {
//内存缓存有
if that.memoryCache != nil && that.memoryCache.SessionSet {
reData = that.memoryCache.Cache(key, data...)
if reData.Data != nil {
return reData
}
}
//redis缓存有
if that.redisCache != nil && that.redisCache.SessionSet {
reData = that.redisCache.Cache(key, data...)
if reData.Data != nil {
if that.memoryCache != nil && that.memoryCache.SessionSet {
that.memoryCache.Cache(key, reData.Data)
}
return reData
}
}
//db缓存有
if that.dbCache != nil && that.dbCache.SessionSet {
reData = that.dbCache.Cache(key, data...)
if reData.Data != nil {
if that.memoryCache != nil && that.memoryCache.SessionSet {
that.memoryCache.Cache(key, reData.Data)
}
if that.redisCache != nil && that.redisCache.SessionSet {
that.redisCache.Cache(key, reData.Data)
}
return reData
}
}
return reData
}
//设置缓存
//设置内存缓存
if that.memoryCache != nil && that.memoryCache.SessionSet {
reData = that.memoryCache.Cache(key, data...)
}
//redis缓存有
if that.redisCache != nil && that.redisCache.SessionSet {
reData = that.redisCache.Cache(key, data...)
}
//redis缓存有
if that.dbCache != nil && that.dbCache.SessionSet {
reData = that.dbCache.Cache(key, data...)
}
return reData
}
func (that *HoTimeCache) Db(key string, data ...interface{}) *Obj {
var reData *Obj
if len(data) == 0 {
//内存缓存有
if that.memoryCache != nil && that.memoryCache.DbSet {
reData = that.memoryCache.Cache(key, data...)
if reData.Data != nil {
return reData
}
}
//redis缓存有
if that.redisCache != nil && that.redisCache.DbSet {
reData = that.redisCache.Cache(key, data...)
if reData.Data != nil {
if that.memoryCache != nil && that.memoryCache.DbSet {
that.memoryCache.Cache(key, reData.Data)
}
return reData
}
}
//redis缓存有
if that.dbCache != nil && that.dbCache.DbSet {
reData = that.dbCache.Cache(key, data...)
if reData.Data != nil {
if that.memoryCache != nil && that.memoryCache.DbSet {
that.memoryCache.Cache(key, reData.Data)
}
if that.redisCache != nil && that.redisCache.DbSet {
that.redisCache.Cache(key, reData.Data)
}
return reData
}
}
return reData
}
//设置缓存
//设置内存缓存
if that.memoryCache != nil && that.memoryCache.DbSet {
reData = that.memoryCache.Cache(key, data...)
}
//redis缓存有
if that.redisCache != nil && that.redisCache.DbSet {
reData = that.redisCache.Cache(key, data...)
}
//redis缓存有
if that.dbCache != nil && that.dbCache.DbSet {
reData = that.dbCache.Cache(key, data...)
}
return reData
}
func (that *HoTimeCache) Cache(key string, data ...interface{}) *Obj {
var reData *Obj
if len(data) == 0 {
//内存缓存有
if that.memoryCache != nil {
reData = that.memoryCache.Cache(key, data...)
if reData != nil {
return reData
}
}
//redis缓存有
if that.redisCache != nil {
reData = that.redisCache.Cache(key, data...)
if reData.Data != nil {
if that.memoryCache != nil {
that.memoryCache.Cache(key, reData.Data)
}
return reData
}
}
//redis缓存有
if that.dbCache != nil {
reData = that.dbCache.Cache(key, data...)
if reData.Data != nil {
if that.memoryCache != nil {
that.memoryCache.Cache(key, reData.Data)
}
if that.redisCache != nil {
that.redisCache.Cache(key, reData.Data)
}
return reData
}
}
return reData
}
//设置缓存
//设置内存缓存
if that.memoryCache != nil {
reData = that.memoryCache.Cache(key, data...)
}
//redis缓存有
if that.redisCache != nil {
reData = that.redisCache.Cache(key, data...)
}
//redis缓存有
if that.dbCache != nil {
reData = that.dbCache.Cache(key, data...)
}
return reData
}
func (that *HoTimeCache) Init(config Map, hotimeDb HoTimeDBInterface, err ...*Error) {
//防止空数据问题
if config == nil {
config = Map{}
}
if err[0] != nil {
that.Error = err[0]
}
that.Config = config
//memory配置初始化
memory := that.Config.GetMap("memory")
if memory == nil {
memory = Map{
"db": true,
"session": true,
"sort": 0,
"timeout": 60 * 60 * 2,
}
}
if memory.Get("db") == nil {
memory["db"] = true
}
if memory.Get("session") == nil {
memory["session"] = true
}
if memory.Get("timeout") == nil {
memory["timeout"] = 60 * 60 * 2
}
that.Config["memory"] = memory
that.memoryCache = &CacheMemory{TimeOut: memory.GetCeilInt64("timeout"),
DbSet: memory.GetBool("db"), SessionSet: memory.GetBool("session")}
if err[0] != nil {
that.memoryCache.SetError(err[0])
}
//db配置初始化
redis := that.Config.GetMap("redis")
if redis != nil {
if redis.GetString("host") == "" || redis.GetString("port") == "" {
if err[0] != nil {
err[0].SetError(errors.New("请检查redis配置host和port配置"))
}
return
}
if redis.Get("db") == nil {
redis["db"] = true
}
if redis.Get("session") == nil {
redis["session"] = true
}
if redis.Get("timeout") == nil {
redis["timeout"] = 60 * 60 * 24 * 15
}
that.Config["redis"] = redis
that.redisCache = &CacheRedis{TimeOut: redis.GetCeilInt64("timeout"),
DbSet: redis.GetBool("db"), SessionSet: redis.GetBool("session"), Host: redis.GetString("host"),
Pwd: redis.GetString("password"), Port: redis.GetCeilInt64("port")}
if err[0] != nil {
that.redisCache.SetError(err[0])
}
}
//db配置初始化
db := that.Config.GetMap("db")
if db != nil {
if db.Get("db") == nil {
db["db"] = false
}
if db.Get("session") == nil {
db["session"] = true
}
if db.Get("timeout") == nil {
db["timeout"] = 60 * 60 * 24 * 30
}
that.Config["db"] = db
that.dbCache = &CacheDb{TimeOut: db.GetCeilInt64("timeout"),
DbSet: db.GetBool("db"), SessionSet: db.GetBool("session"),
Db: hotimeDb}
if err[0] != nil {
that.dbCache.SetError(err[0])
}
}
}
+173
View File
@@ -0,0 +1,173 @@
package cache
import (
. "code.hoteas.com/golang/hotime/common"
"database/sql"
"encoding/json"
"strings"
"time"
)
type HoTimeDBInterface interface {
GetPrefix() string
Query(query string, args ...interface{}) []Map
Exec(query string, args ...interface{}) (sql.Result, *Error)
Get(table string, qu ...interface{}) Map
Select(table string, qu ...interface{}) []Map
Delete(table string, data map[string]interface{}) int64
Update(table string, data Map, where Map) int64
Insert(table string, data map[string]interface{}) int64
GetType() string
}
type CacheDb struct {
TimeOut int64
DbSet bool
SessionSet bool
Db HoTimeDBInterface
*Error
ContextBase
isInit bool
}
func (that *CacheDb) GetError() *Error {
return that.Error
}
func (that *CacheDb) SetError(err *Error) {
that.Error = err
}
func (that *CacheDb) initDbTable() {
if that.isInit {
return
}
if that.Db.GetType() == "mysql" {
dbNames := that.Db.Query("SELECT DATABASE()")
if len(dbNames) == 0 {
return
}
dbName := dbNames[0].GetString("DATABASE()")
res := that.Db.Query("SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA='" + dbName + "' AND TABLE_NAME='" + that.Db.GetPrefix() + "cached'")
if len(res) != 0 {
that.isInit = true
return
}
_, e := that.Db.Exec("CREATE TABLE `" + that.Db.GetPrefix() + "cached` ( `id` int(11) unsigned NOT NULL AUTO_INCREMENT, `ckey` varchar(60) DEFAULT NULL, `cvalue` varchar(2000) DEFAULT NULL, `time` bigint(20) DEFAULT NULL, `endtime` bigint(20) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=198740 DEFAULT CHARSET=utf8")
if e.GetError() == nil {
that.isInit = true
}
}
if that.Db.GetType() == "sqlite" {
res := that.Db.Query(`select * from sqlite_master where type = 'table' and name = '` + that.Db.GetPrefix() + `cached'`)
if len(res) != 0 {
that.isInit = true
return
}
_, e := that.Db.Exec(`CREATE TABLE "` + that.Db.GetPrefix() + `cached" (
"id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
"ckey" TEXT(60),
"cvalue" TEXT(2000),
"time" integer,
"endtime" integer
);`)
if e.GetError() == nil {
that.isInit = true
}
}
}
//获取Cache键只能为string类型
func (that *CacheDb) get(key string) interface{} {
cached := that.Db.Get("cached", "*", Map{"ckey": key})
if cached == nil {
return nil
}
//data:=cacheMap[key];
if cached.GetInt64("endtime") <= time.Now().Unix() {
that.Db.Delete("cached", Map{"id": cached.GetString("id")})
return nil
}
data := Map{}
data.JsonToMap(cached.GetString("cvalue"))
return data.Get("data")
}
//key value ,时间为时间戳
func (that *CacheDb) set(key string, value interface{}, tim int64) {
bte, _ := json.Marshal(Map{"data": value})
num := that.Db.Update("cached", Map{"cvalue": string(bte), "time": time.Now().UnixNano(), "endtime": tim}, Map{"ckey": key})
if num == int64(0) {
that.Db.Insert("cached", Map{"cvalue": string(bte), "time": time.Now().UnixNano(), "endtime": tim, "ckey": key})
}
//随机执行删除命令
if Rand(1000) > 950 {
that.Db.Delete("cached", Map{"endtime[<]": time.Now().Unix()})
}
}
func (that *CacheDb) delete(key string) {
del := strings.Index(key, "*")
//如果通配删除
if del != -1 {
key = Substr(key, 0, del)
that.Db.Delete("cached", Map{"ckey": key + "%"})
} else {
that.Db.Delete("cached", Map{"ckey": key})
}
}
func (that *CacheDb) Cache(key string, data ...interface{}) *Obj {
that.initDbTable()
if len(data) == 0 {
return &Obj{Data: that.get(key)}
}
tim := time.Now().Unix()
if len(data) == 1 && data[0] == nil {
that.delete(key)
return &Obj{Data: nil}
}
if len(data) == 1 {
if that.TimeOut == 0 {
//that.Time = Config.GetInt64("cacheLongTime")
}
tim += that.TimeOut
}
if len(data) == 2 {
that.SetError(nil)
tempt := ObjToInt64(data[1], that.Error)
if tempt > tim {
tim = tempt
} else if that.GetError() == nil {
tim = tim + tempt
}
}
that.set(key, data[0], tim)
return &Obj{Data: nil}
}
+158
View File
@@ -0,0 +1,158 @@
package cache
import (
. "code.hoteas.com/golang/hotime/common"
"strings"
"sync"
"time"
)
type CacheMemory struct {
TimeOut int64
DbSet bool
SessionSet bool
Map
*Error
ContextBase
mutex *sync.RWMutex
}
func (that *CacheMemory) GetError() *Error {
return that.Error
}
func (that *CacheMemory) SetError(err *Error) {
that.Error = err
}
//获取Cache键只能为string类型
func (that *CacheMemory) get(key string) interface{} {
that.Error.SetError(nil)
if that.Map == nil {
that.Map = Map{}
}
if that.Map[key] == nil {
return nil
}
data := that.Map.Get(key, that.Error).(cacheData)
if that.Error.GetError() != nil {
return nil
}
if data.time < time.Now().Unix() {
delete(that.Map, key)
return nil
}
return data.data
}
func (that *CacheMemory) refreshMap() {
go func() {
that.mutex.Lock()
defer that.mutex.Unlock()
for key, v := range that.Map {
data := v.(cacheData)
if data.time <= time.Now().Unix() {
delete(that.Map, key)
}
}
}()
}
//key value ,时间为时间戳
func (that *CacheMemory) set(key string, value interface{}, time int64) {
that.Error.SetError(nil)
var data cacheData
if that.Map == nil {
that.Map = Map{}
}
dd := that.Map[key]
if dd == nil {
data = cacheData{}
} else {
data = dd.(cacheData)
}
data.time = time
data.data = value
that.Map.Put(key, data)
}
func (that *CacheMemory) delete(key string) {
del := strings.Index(key, "*")
//如果通配删除
if del != -1 {
key = Substr(key, 0, del)
for k, _ := range that.Map {
if strings.Index(k, key) != -1 {
delete(that.Map, k)
}
}
} else {
delete(that.Map, key)
}
}
func (that *CacheMemory) Cache(key string, data ...interface{}) *Obj {
x := RandX(1, 100000)
if x > 99950 {
that.refreshMap()
}
if that.mutex == nil {
that.mutex = &sync.RWMutex{}
}
reData := &Obj{Data: nil}
if len(data) == 0 {
that.mutex.RLock()
reData.Data = that.get(key)
that.mutex.RUnlock()
return reData
}
tim := time.Now().Unix()
if len(data) == 1 && data[0] == nil {
that.mutex.Lock()
that.delete(key)
that.mutex.Unlock()
return reData
}
if len(data) == 1 {
tim = tim + that.TimeOut
}
if len(data) == 2 {
that.Error.SetError(nil)
tempt := ObjToInt64(data[1], that.Error)
if tempt > tim {
tim = tempt
} else if that.Error.GetError() == nil {
tim = tim + tempt
}
}
that.mutex.Lock()
that.set(key, data[0], tim)
that.mutex.Unlock()
return reData
}
+71 -54
View File
@@ -1,67 +1,84 @@
package cache
import (
. "code.hoteas.com/golang/hotime"
. "code.hoteas.com/golang/hotime/common"
"github.com/garyburd/redigo/redis"
"strings"
"time"
)
type CacheRedis struct {
Host string
Pwd string
Time int64
conn redis.Conn
tag int64
Error
TimeOut int64
DbSet bool
SessionSet bool
Host string
Pwd string
Port int64
conn redis.Conn
tag int64
ContextBase
*Error
}
func (that *CacheRedis) GetError() *Error {
return that.Error
}
func (that *CacheRedis) SetError(err *Error) {
that.Error = err
}
//唯一标志
func (this *CacheRedis) GetTag() int64 {
func (that *CacheRedis) GetTag() int64 {
if this.tag == int64(0) {
this.tag = time.Now().UnixNano()
if that.tag == int64(0) {
that.tag = time.Now().UnixNano()
}
return this.tag
return that.tag
}
func (this *CacheRedis) reCon() bool {
func (that *CacheRedis) reCon() bool {
var err error
this.conn, err = redis.Dial("tcp", this.Host)
that.conn, err = redis.Dial("tcp", that.Host+":"+ObjToStr(that.Port))
if err != nil {
this.conn = nil
this.Error.SetError(err)
that.conn = nil
that.Error.SetError(err)
return false
}
_, err = this.conn.Do("AUTH", this.Pwd)
if err != nil {
this.conn = nil
this.Error.SetError(err)
return false
if that.Pwd != "" {
_, err = that.conn.Do("AUTH", that.Pwd)
if err != nil {
that.conn = nil
that.Error.SetError(err)
return false
}
}
return true
}
func (this *CacheRedis) del(key string) {
func (that *CacheRedis) del(key string) {
del := strings.Index(key, "*")
if del != -1 {
val, err := redis.Strings(this.conn.Do("KEYS", key))
val, err := redis.Strings(that.conn.Do("KEYS", key))
if err != nil {
return
}
this.conn.Send("MULTI")
that.conn.Send("MULTI")
for i, _ := range val {
this.conn.Send("DEL", val[i])
that.conn.Send("DEL", val[i])
}
this.conn.Do("EXEC")
that.conn.Do("EXEC")
} else {
_, err := this.conn.Do("DEL", key)
_, err := that.conn.Do("DEL", key)
if err != nil {
this.Error.SetError(err)
_, err = this.conn.Do("PING")
that.Error.SetError(err)
_, err = that.conn.Do("PING")
if err != nil {
if this.reCon() {
_, err = this.conn.Do("DEL", key)
if that.reCon() {
_, err = that.conn.Do("DEL", key)
}
}
}
@@ -69,32 +86,32 @@ func (this *CacheRedis) del(key string) {
}
//key value ,时间为时间戳
func (this *CacheRedis) set(key string, value string, time int64) {
_, err := this.conn.Do("SET", key, value, "EX", ObjToStr(time))
func (that *CacheRedis) set(key string, value string, time int64) {
_, err := that.conn.Do("SET", key, value, "EX", ObjToStr(time))
if err != nil {
this.Error.SetError(err)
_, err = this.conn.Do("PING")
that.Error.SetError(err)
_, err = that.conn.Do("PING")
if err != nil {
if this.reCon() {
_, err = this.conn.Do("SET", key, value, "EX", ObjToStr(time))
if that.reCon() {
_, err = that.conn.Do("SET", key, value, "EX", ObjToStr(time))
}
}
}
}
func (this *CacheRedis) get(key string) *Obj {
func (that *CacheRedis) get(key string) *Obj {
reData := &Obj{}
var err error
reData.Data, err = redis.String(this.conn.Do("GET", key))
reData.Data, err = redis.String(that.conn.Do("GET", key))
if err != nil {
reData.Data = nil
if !strings.Contains(err.Error(), "nil returned") {
this.Error.SetError(err)
_, err = this.conn.Do("PING")
that.Error.SetError(err)
_, err = that.conn.Do("PING")
if err != nil {
if this.reCon() {
reData.Data, err = redis.String(this.conn.Do("GET", key))
if that.reCon() {
reData.Data, err = redis.String(that.conn.Do("GET", key))
}
}
@@ -104,10 +121,10 @@ func (this *CacheRedis) get(key string) *Obj {
return reData
}
func (this *CacheRedis) Cache(key string, data ...interface{}) *Obj {
func (that *CacheRedis) Cache(key string, data ...interface{}) *Obj {
reData := &Obj{}
if this.conn == nil {
re := this.reCon()
if that.conn == nil {
re := that.reCon()
if !re {
return reData
}
@@ -115,38 +132,38 @@ func (this *CacheRedis) Cache(key string, data ...interface{}) *Obj {
//查询缓存
if len(data) == 0 {
reData = this.get(key)
reData = that.get(key)
return reData
}
tim := int64(0)
//删除缓存
if len(data) == 1 && data[0] == nil {
this.del(key)
that.del(key)
return reData
}
//添加缓存
if len(data) == 1 {
if this.Time == 0 {
this.Time = Config.GetInt64("cacheShortTime")
if that.TimeOut == 0 {
//that.Time = Config.GetInt64("cacheShortTime")
}
tim += this.Time
tim += that.TimeOut
}
if len(data) == 2 {
this.Error.SetError(nil)
tempt := ObjToInt64(data[1], &this.Error)
that.Error.SetError(nil)
tempt := ObjToInt64(data[1], that.Error)
if tempt > tim {
tim = tempt
} else if this.GetError() == nil {
} else if that.GetError() == nil {
tim = tim + tempt
}
}
this.set(key, ObjToStr(data[0]), tim)
that.set(key, ObjToStr(data[0]), tim)
return reData
+20
View File
@@ -0,0 +1,20 @@
package cache
import (
. "code.hoteas.com/golang/hotime/common"
)
type CacheIns interface {
//set(key string, value interface{}, time int64)
//get(key string) interface{}
//delete(key string)
GetError() *Error
SetError(err *Error)
Cache(key string, data ...interface{}) *Obj
}
//单条缓存数据
type cacheData struct {
time int64
data interface{}
}
-146
View File
@@ -1,146 +0,0 @@
package hotime
import (
"encoding/json"
"strings"
"time"
)
type CacheDb struct {
Time int64
Db *HoTimeDB
contextBase
isInit bool
}
func (this *CacheDb) initDbTable() {
if this.isInit {
return
}
if this.Db.Type == "mysql" {
dbNames := this.Db.Query("SELECT DATABASE()")
if len(dbNames) == 0 {
return
}
dbName := dbNames[0].GetString("DATABASE()")
res := this.Db.Query("SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA='" + dbName + "' AND TABLE_NAME='cached'")
if len(res) != 0 {
this.isInit = true
return
}
_, e := this.Db.Exec("CREATE TABLE `cached` ( `id` int(11) unsigned NOT NULL AUTO_INCREMENT, `ckey` varchar(60) DEFAULT NULL, `cvalue` varchar(2000) DEFAULT NULL, `time` bigint(20) DEFAULT NULL, `endtime` bigint(20) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=198740 DEFAULT CHARSET=utf8")
if e.GetError() == nil {
this.isInit = true
}
}
if this.Db.Type == "sqlite" {
res := this.Db.Query(`select * from sqlite_master where type = 'table' and name = 'cached'`)
if len(res) != 0 {
this.isInit = true
return
}
_, e := this.Db.Exec(`CREATE TABLE "cached" (
"id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
"ckey" TEXT(60),
"cvalue" TEXT(2000),
"time" integer,
"endtime" integer
);`)
if e.GetError() == nil {
this.isInit = true
}
}
}
//获取Cache键只能为string类型
func (this *CacheDb) get(key string) interface{} {
cached := this.Db.Get("cached", "*", Map{"ckey": key})
if cached == nil {
return nil
}
//data:=cacheMap[key];
if cached.GetInt64("endtime") <= time.Now().Unix() {
this.Db.Delete("cached", Map{"id": cached.GetString("id")})
return nil
}
data := Map{}
data.JsonToMap(cached.GetString("cvalue"))
return data.Get("data")
}
//key value ,时间为时间戳
func (this *CacheDb) set(key string, value interface{}, tim int64) {
bte, _ := json.Marshal(Map{"data": value})
num := this.Db.Update("cached", Map{"cvalue": string(bte), "time": time.Now().UnixNano(), "endtime": tim}, Map{"ckey": key})
if num == int64(0) {
this.Db.Insert("cached", Map{"cvalue": string(bte), "time": time.Now().UnixNano(), "endtime": tim, "ckey": key})
}
//随机执行删除命令
if Rand(1000) > 950 {
this.Db.Delete("cached", Map{"endtime[<]": time.Now().Unix()})
}
}
func (this *CacheDb) delete(key string) {
del := strings.Index(key, "*")
//如果通配删除
if del != -1 {
key = Substr(key, 0, del)
this.Db.Delete("cached", Map{"ckey": key + "%"})
} else {
this.Db.Delete("cached", Map{"ckey": key})
}
}
func (this *CacheDb) Cache(key string, data ...interface{}) *Obj {
this.initDbTable()
if len(data) == 0 {
return &Obj{Data: this.get(key)}
}
tim := time.Now().Unix()
if len(data) == 1 && data[0] == nil {
this.delete(key)
return &Obj{Data: nil}
}
if len(data) == 1 {
if this.Time == 0 {
this.Time = Config.GetInt64("cacheLongTime")
}
tim += this.Time
}
if len(data) == 2 {
this.SetError(nil)
tempt := ObjToInt64(data[1], &this.Error)
if tempt > tim {
tim = tempt
} else if this.GetError() == nil {
tim = tim + tempt
}
}
this.set(key, data[0], tim)
return &Obj{Data: nil}
}
-146
View File
@@ -1,146 +0,0 @@
package hotime
import (
"strings"
"sync"
"time"
)
type CacheMemory struct {
Time int64
Map
contextBase
mutex *sync.RWMutex
}
//获取Cache键只能为string类型
func (this *CacheMemory) get(key string) interface{} {
this.Error.SetError(nil)
if this.Map == nil {
this.Map = Map{}
}
if this.Map[key] == nil {
return nil
}
data := this.Map.Get(key, &this.Error).(cacheData)
if this.GetError() != nil {
return nil
}
if data.time < time.Now().Unix() {
delete(this.Map, key)
return nil
}
return data.data
}
func (this *CacheMemory) refreshMap() {
go func() {
this.mutex.Lock()
defer this.mutex.Unlock()
for key, v := range this.Map {
data := v.(cacheData)
if data.time <= time.Now().Unix() {
delete(this.Map, key)
}
}
}()
}
//key value ,时间为时间戳
func (this *CacheMemory) set(key string, value interface{}, time int64) {
this.Error.SetError(nil)
var data cacheData
if this.Map == nil {
this.Map = Map{}
}
dd := this.Map[key]
if dd == nil {
data = cacheData{}
} else {
data = dd.(cacheData)
}
data.time = time
data.data = value
this.Map.Put(key, data)
}
func (this *CacheMemory) delete(key string) {
del := strings.Index(key, "*")
//如果通配删除
if del != -1 {
key = Substr(key, 0, del)
for k, _ := range this.Map {
if strings.Index(k, key) != -1 {
delete(this.Map, key)
}
}
} else {
delete(this.Map, key)
}
}
func (this *CacheMemory) Cache(key string, data ...interface{}) *Obj {
x := RandX(1, 100000)
if x > 99950 {
this.refreshMap()
}
if this.mutex == nil {
this.mutex = &sync.RWMutex{}
}
reData := &Obj{Data: nil}
if len(data) == 0 {
this.mutex.RLock()
reData.Data = this.get(key)
this.mutex.RUnlock()
return reData
}
tim := time.Now().Unix()
if len(data) == 1 && data[0] == nil {
this.mutex.Lock()
this.delete(key)
this.mutex.Unlock()
return reData
}
if len(data) == 1 {
if this.Time == 0 {
this.Time = Config.GetInt64("cacheShortTime")
}
tim = tim + this.Time
}
if len(data) == 2 {
this.Error.SetError(nil)
tempt := ObjToInt64(data[1], &this.Error)
if tempt > tim {
tim = tempt
} else if this.GetError() == nil {
tim = tim + tempt
}
}
this.mutex.Lock()
this.set(key, data[0], tim)
this.mutex.Unlock()
return reData
}
+232
View File
@@ -0,0 +1,232 @@
package hotime
import (
. "code.hoteas.com/golang/hotime/common"
"strings"
)
// Project 管理端项目
var TptProject = Proj{
//"user": UserCtr,
"hotimeCommon": Ctr{
"info": func(that *Context) {
hotimeName := that.RouterString[0]
data := that.Db.Get(hotimeName, "*", Map{"id": that.Session(hotimeName + "_id").ToCeilInt()})
str, inData := that.MakeCode.Info(that.RouterString[1], data, that.Db)
where := Map{"id": that.RouterString[2]}
if len(inData) == 1 {
inData["id"] = where["id"]
where = Map{"AND": inData}
} else if len(inData) > 1 {
where["OR"] = inData
where = Map{"AND": where}
}
re := that.Db.Get(that.RouterString[1], str, where)
if re == nil {
that.Display(4, "找不到对应信息")
return
}
for k, v := range re {
column := that.MakeCode.TableColumns[that.RouterString[1]][k]
if column == nil {
continue
}
if (column["list"] == nil || column.GetBool("list")) && column.GetString("link") != "" {
re[column.GetString("link")] = that.Db.Get(column.GetString("link"), "id,"+column.GetString("value"), Map{"id": v})
}
}
that.Display(0, re)
},
"add": func(that *Context) {
inData := that.MakeCode.Add(that.RouterString[1], that.Req)
if inData == nil {
that.Display(3, "请求参数不足")
return
}
re := that.Db.Insert(that.RouterString[1], inData)
if re == 0 {
that.Display(4, "无法插入对应数据")
return
}
//索引管理,便于检索以及权限
if inData.Get("parent_id") != nil && inData.GetString("index") != "" {
index := that.Db.Get(that.RouterString[1], "`index`", Map{"id": inData.Get("parent_id")})
inData["index"] = index.GetString("index") + ObjToStr(re) + ","
that.Db.Update(that.RouterString[1], Map{"index": inData["index"]}, Map{"id": re})
} else if inData.GetString("index") != "" {
inData["index"] = "," + ObjToStr(re) + ","
that.Db.Update(that.RouterString[1], Map{"index": inData["index"]}, Map{"id": re})
}
that.Display(0, re)
},
"update": func(that *Context) {
inData := that.MakeCode.Edit(that.RouterString[1], that.Req)
if inData == nil {
that.Display(3, "没有找到要更新的数据")
return
}
//索引管理,便于检索以及权限
if inData.GetString("index") != "" {
if inData.Get("parent_id") != nil {
Index := that.Db.Get(that.RouterString[1], "`index`", Map{"id": that.RouterString[2]})
parentIndex := that.Db.Get(that.RouterString[1], "`index`", Map{"id": inData.Get("parent_id")})
inData["index"] = parentIndex.GetString("index") + that.RouterString[2] + ","
childNodes := that.Db.Select(that.RouterString[1], "id,`index``", Map{"index[~]": "," + that.RouterString[2] + ","})
for _, v := range childNodes {
v["index"] = strings.Replace(v.GetString("index"), Index.GetString("index"), inData.GetString("index"), -1)
that.Db.Update(that.RouterString[1], Map{"index": v["index"]}, Map{"id": v.GetCeilInt("id")})
}
} else {
delete(inData, "index")
}
}
re := that.Db.Update(that.RouterString[1], inData, Map{"id": that.RouterString[2]})
if re == 0 {
that.Display(4, "更新数据失败")
return
}
that.Display(0, re)
},
"remove": func(that *Context) {
inData := that.MakeCode.Delete(that.RouterString[1], that.Req)
if inData == nil {
that.Display(3, "请求参数不足")
return
}
re := int64(0)
//索引管理,便于检索以及权限
if inData.Get("parent_id") != nil && inData.GetSlice("index") != nil {
re = that.Db.Delete(that.RouterString[1], Map{"index[~]": "," + that.RouterString[2] + ","})
} else {
re = that.Db.Delete(that.RouterString[1], Map{"id": that.RouterString[2]})
}
if re == 0 {
that.Display(4, "删除数据失败")
return
}
that.Display(0, "删除成功")
},
"search": func(that *Context) {
hotimeName := that.RouterString[0]
data := that.Db.Get(hotimeName, "*", Map{"id": that.Session(hotimeName + "_id").ToCeilInt()})
columnStr, leftJoin, where := that.MakeCode.Search(that.RouterString[1], data, that.Req, that.Db)
page := ObjToInt(that.Req.FormValue("page"))
pageSize := ObjToInt(that.Req.FormValue("pageSize"))
if page < 1 {
page = 1
}
if pageSize <= 0 {
pageSize = 20
}
count := that.Db.Count(that.RouterString[1], leftJoin, where)
reData := that.Db.Page(page, pageSize).
PageSelect(that.RouterString[1], leftJoin, columnStr, where)
for _, v := range reData {
for k, _ := range v {
column := that.MakeCode.TableColumns[that.RouterString[1]][k]
if column == nil {
continue
}
if column["list"] != false && column["name"] == "parent_id" && column.GetString("link") != "" {
parentC := that.Db.Get(column.GetString("link"), column.GetString("value"), Map{"id": v.GetCeilInt(k)})
v[column.GetString("link")+"_"+column.GetString("name")+"_"+column.GetString("value")] = ""
if parentC != nil {
v[column.GetString("link")+"_"+column.GetString("name")+"_"+column.GetString("value")] = parentC.GetString(column.GetString("value"))
}
}
}
}
that.Display(0, Map{"count": count, "data": reData})
},
},
"hotime": Ctr{
"login": func(that *Context) {
hotimeName := that.RouterString[0]
name := that.Req.FormValue("name")
password := that.Req.FormValue("password")
if name == "" || password == "" {
that.Display(3, "参数不足")
return
}
user := that.Db.Get(hotimeName, "*", Map{"AND": Map{"OR": Map{"name": name, "phone": name}, "password": Md5(password)}})
if user == nil {
that.Display(5, "登录失败")
return
}
that.Session(hotimeName+"_id", user.GetCeilInt("id"))
that.Session(hotimeName+"_name", name)
delete(user, "password")
that.Display(0, user)
},
"logout": func(that *Context) {
hotimeName := that.RouterString[0]
that.Session(hotimeName+"_id", nil)
that.Session(hotimeName+"_name", nil)
that.Display(0, "退出登录成功")
},
"info": func(that *Context) {
hotimeName := that.RouterString[0]
data := that.Db.Get(hotimeName, "*", Map{"id": that.Session(hotimeName + "_id").ToCeilInt()})
str, inData := that.MakeCode.Info(hotimeName, data, that.Db)
where := Map{"id": that.Session(hotimeName + "_id").ToCeilInt()}
if len(inData) == 1 {
inData["id"] = where["id"]
where = Map{"AND": inData}
} else if len(inData) > 1 {
where["OR"] = inData
where = Map{"AND": where}
}
re := that.Db.Get(hotimeName, str, where)
if re == nil {
that.Display(4, "找不到对应信息")
return
}
for k, v := range re {
column := that.MakeCode.TableColumns[hotimeName][k]
if column == nil {
continue
}
if (column["list"] == nil || column.GetBool("list")) && column.GetString("link") != "" {
//是角色表则取下角色值
if column.GetString("link") == "role" {
re[column.GetString("link")] = that.Db.Get(column.GetString("link"), "id,auth,"+column.GetString("value"), Map{"id": v})
} else {
re[column.GetString("link")] = that.Db.Get(column.GetString("link"), "id,"+column.GetString("value"), Map{"id": v})
}
}
}
that.Display(0, re)
},
},
}
+103
View File
@@ -0,0 +1,103 @@
package code
import (
. "code.hoteas.com/golang/hotime/common"
)
var Config = Map{
"name": "HoTimeDashBoard",
"id": "2f92h3herh23rh2y8",
"label": "HoTime管理平台",
"menus": []Map{
{"label": "平台首页", "name": "HelloWorld", "icon": "el-icon-s-home"},
//{"label": "测试表格", "table": "table", "icon": "el-icon-suitcase"},
//{"label": "系统管理", "name": "setting", "icon": "el-icon-setting",
// "menus": []Map{
// {"label": "用户管理", "table": "user",
// "default": {
// "path": "info",
// "id": "1"
// },
// "auth": ["show","edit","info","add","delete"],
// },
// {"label": "组织管理", "table": "organization"},
// {"label": "地区管理", "table": "area"},
// {"label": "角色管理", "table": "role"},
// {"label": "日志管理", "table": "log"},
// {"label": "系统设置", "table": "system", "default": "edit"},
// },
//},
},
}
var DefaultMenuParentName = "sys"
var ColumnDataType = map[string]string{
//sqlite专有类型
"real": "number",
//mysql数据类型宽泛类型
"int": "number",
"float": "number",
"double": "number",
"decimal": "number",
"char": "text",
"text": "text",
"blob": "text",
"date": "time",
"time": "time",
"year": "time",
"geometry": "gis", //不建议使用gis类型,建议使用其他代替
}
type ColumnShow struct {
Name string
List bool
Edit bool
Info bool
Must bool
Type string //空字符串表示
Strict bool //name严格匹配必须是这个词才行
}
var ColumnNameType = []ColumnShow{
//通用
{"idcard", false, true, true, false, "", false},
{"id", true, false, true, false, "", true},
{"parent_id", true, true, true, false, "", true},
//"sn"{true,true,true,""},
{"status", true, true, true, false, "select", false},
{"state", true, true, true, false, "select", false},
{"sex", true, true, true, false, "select", false},
{"delete", false, false, false, false, "", false},
{"lat", false, true, true, false, "", false},
{"lng", false, true, true, false, "", false},
{"latitude", false, true, true, false, "", false},
{"longitude", false, true, true, false, "", false},
{"index", false, false, false, false, "index", false},
{"password", false, true, false, false, "password", false},
{"pwd", false, true, false, false, "password", false},
{"info", false, true, true, false, "", false},
{"version", false, false, false, false, "", false},
{"seq", false, true, true, false, "", false},
{"sort", false, true, true, false, "", false},
{"note", false, true, true, false, "", false},
{"description", false, true, true, false, "", false},
{"abstract", false, true, true, false, "", false},
{"content", false, true, true, false, "", false},
{"address", false, true, true, false, "", false},
{"full_name", false, true, true, false, "", false},
{"create_time", false, false, true, false, "time", true},
{"modify_time", true, false, true, false, "time", true},
{"image", false, true, true, false, "image", false},
{"img", false, true, true, false, "image", false},
{"icon", false, true, true, false, "image", false},
{"avatar", false, true, true, false, "image", false},
{"file", false, true, true, false, "file", false},
{"age", false, true, true, false, "", false},
{"email", false, true, true, false, "", false},
{"time", true, true, true, true, "time", false},
{"level", false, false, true, false, "", false},
{"rule", true, true, true, false, "form", false},
}
+883
View File
@@ -0,0 +1,883 @@
package code
import (
. "code.hoteas.com/golang/hotime/common"
"code.hoteas.com/golang/hotime/db"
"errors"
"fmt"
"io/ioutil"
"net/http"
"os"
"path/filepath"
"strings"
"time"
)
type MakeCode struct {
IndexMenus Map
TableConfig Map
TableColumns map[string]map[string]Map
SearchColumns map[string]map[string]Map
Config Map
Error
}
func (that *MakeCode) Db2JSON(name string, path string, db *db.HoTimeDB, makeCode bool) {
isMake := false
idSlice := Slice{}
if that.TableColumns == nil {
that.TableColumns = make(map[string]map[string]Map)
}
if that.SearchColumns == nil {
that.SearchColumns = make(map[string]map[string]Map)
}
//加载配置文件
btes, err := ioutil.ReadFile(path)
Config["name"] = name
that.Config = DeepCopyMap(Config).(Map)
if err == nil {
cmap := Map{}
//文件是否损坏
cmap.JsonToMap(string(btes), &that.Error)
for k, v := range cmap {
that.Config[k] = v //程序配置
Config[k] = v //系统配置
}
} else {
that.Error.SetError(errors.New("配置文件不存在,或者配置出错,使用缺省默认配置"))
}
that.IndexMenus = Map{}
menusConfig := that.Config.GetSlice("menus")
//将配置写入到内存中仅作为判断用
if menusConfig != nil {
for kmenu, _ := range menusConfig {
menu := menusConfig.GetMap(kmenu)
if menu != nil {
mname := menu.GetString("table")
if mname == "" { //如果为空则不是表格
mname = menu.GetString("name")
}
that.IndexMenus[mname] = menu
childMenus := menu.GetSlice("menus")
if childMenus != nil {
for ckmenu, _ := range childMenus {
cmenu := childMenus.GetMap(ckmenu)
if cmenu != nil {
cname := cmenu.GetString("table")
if cmenu.GetString("table") == "" {
continue
}
that.IndexMenus[mname+"/"+cname] = cmenu
}
}
}
}
}
}
that.TableConfig = that.Config.GetMap("tables")
if that.TableConfig == nil {
that.TableConfig = Map{}
}
for tableName, _ := range that.TableConfig {
columns := that.TableConfig.GetMap(tableName).GetSlice("columns")
search := that.TableConfig.GetMap(tableName).GetSlice("search")
//初始化
if that.TableColumns[tableName] == nil {
that.TableColumns[tableName] = map[string]Map{}
}
//初始化搜索项
if that.SearchColumns[tableName] == nil {
that.SearchColumns[tableName] = map[string]Map{}
}
//注入源数据
for index, _ := range columns {
columnsName := columns.GetMap(index).GetString("name")
that.TableColumns[tableName][columnsName] = columns.GetMap(index)
}
//注入search源数据
for index, _ := range search {
searchName := search.GetMap(index).GetString("name")
that.SearchColumns[tableName][searchName] = search.GetMap(index)
}
}
if db == nil {
return
}
//数据库反哺
myInit := strings.Replace(InitTpt, "{{name}}", name, -1)
ctrList := ""
nowTables := make([]Map, 0)
if db.Type == "mysql" {
nowTables = db.Select("INFORMATION_SCHEMA.TABLES", "TABLE_NAME as name,TABLE_COMMENT as label", Map{"TABLE_SCHEMA": db.DBName})
}
if db.Type == "sqlite" {
nowTables = db.Select("sqlite_sequence", "name")
}
//idSlice=append(idSlice,nowTables)
for _, v := range nowTables {
if v.GetString("name") == "cached" {
continue
}
if that.TableConfig.GetMap(v.GetString("name")) == nil {
if v.GetString("label") == "" {
v["label"] = v.GetString("name")
}
that.TableConfig[v.GetString("name")] = Map{
"label": v.GetString("label"),
"table": v.GetString("name"),
"auth": []string{"show", "add", "delete", "edit", "info"},
"columns": []Map{},
"search": []Map{
{"type": "search", "name": "keyword", "label": "请输入关键词", "value": nil},
{"type": "search", "name": "daterange", "label": "时间段", "value": nil},
{"type": "search", "name": "sort", "label": "排序", "value": nil},
},
}
}
//初始化
if that.TableColumns[v.GetString("name")] == nil {
that.TableColumns[v.GetString("name")] = make(map[string]Map)
}
//初始化
if that.SearchColumns[v.GetString("name")] == nil {
that.SearchColumns[v.GetString("name")] = make(map[string]Map)
}
tableInfo := make([]Map, 0)
if db.Type == "mysql" {
tableInfo = db.Select("INFORMATION_SCHEMA.COLUMNS", "COLUMN_NAME AS name,COLUMN_TYPE AS type,COLUMN_COMMENT AS label", Map{"AND": Map{"TABLE_SCHEMA": db.DBName, "TABLE_NAME": v.GetString("name")}})
}
if db.Type == "sqlite" {
tableInfo = db.Query("pragma table_info([" + v.GetString("name") + "]);")
}
idSlice = append(idSlice, tableInfo)
for _, info1 := range tableInfo {
info := DeepCopyMap(info1).(Map)
if info.GetString("label") == "" {
info["label"] = info.GetString("name")
}
coloum := that.TableColumns[v.GetString("name")][info.GetString("name")]
if coloum == nil {
//根据类型判断真实类型
for k, v1 := range ColumnDataType {
if strings.Contains(info.GetString("name"), k) || strings.Contains(info.GetString("type"), k) {
info["type"] = v1
}
}
coloum = Map{
"name": info.GetString("name"),
"type": info.GetString("type"),
"label": info.GetString("label"),
//"add": false, "info": false, "edit": false, "list": true,
//"must": false,
}
//备注以空格隔开,空格后的是其他备注
indexNum := strings.Index(info.GetString("label"), " ")
if indexNum > -1 {
coloum["label"] = info.GetString("label")[:indexNum]
}
//去除数据信息,是用:号分割的
indexNum = strings.Index(coloum.GetString("label"), ":")
if indexNum > -1 {
coloum["label"] = coloum.GetString("label")[:indexNum]
}
for _, ColumnName := range ColumnNameType {
if (ColumnName.Strict && coloum.GetString("name") == ColumnName.Name) ||
(!ColumnName.Strict && strings.Contains(coloum.GetString("name"), ColumnName.Name)) {
//全部都不需要则不加入
if ColumnName.Edit == false && ColumnName.List == false && ColumnName.Info == false {
coloum["notUse"] = true
//continue
}
coloum["info"] = ColumnName.Info
coloum["edit"] = ColumnName.Edit
coloum["add"] = ColumnName.Edit
coloum["list"] = ColumnName.List
coloum["must"] = ColumnName.Must
if ColumnName.Info {
delete(coloum, "info")
}
if ColumnName.Edit {
delete(coloum, "edit")
delete(coloum, "add")
}
if ColumnName.List {
delete(coloum, "list")
}
if ColumnName.Must {
delete(coloum, "must")
}
if ColumnName.Type != "" {
coloum["type"] = ColumnName.Type
}
if ColumnName.Strict && coloum.GetString("name") == ColumnName.Name {
break
}
}
}
//如果是select类型需要设置options
if coloum.GetString("type") == "number" {
coloum["sortable"] = true
}
//if !coloum.GetBool("notUse") {
that.TableConfig.GetMap(v.GetString("name"))["columns"] = append(that.TableConfig.GetMap(v.GetString("name")).GetSlice("columns"), coloum)
//}
//如果是select类型需要设置options
//if coloum.GetString("type") == "select" {
options := Slice{}
comments := strings.Split(info.GetString("label"), ":")
if len(comments) >= 2 {
optionComment := strings.Split(comments[1], ",")
for _, v := range optionComment {
optionSlice := strings.Split(v, "-")
if len(optionSlice) >= 2 {
options = append(options, Map{"name": optionSlice[1], "value": optionSlice[0]})
}
}
}
if coloum.GetString("type") == "select" {
coloum["must"] = true
coloum["options"] = options
} else if len(options) > 0 {
coloum["must"] = true
coloum["options"] = options
coloum["type"] = "select"
}
//}
}
//else {
//
// //if !(coloum.GetString("label") != "备注" && info.GetString("label") == "备注") {
// // coloum["label"] = info.GetString("label")
// //}
// //coloum["type"] = info.GetString("type")
//}
//暂时不关闭参数,保证表数据完全读取到
that.TableColumns[v.GetString("name")][info.GetString("name")] = coloum
}
if makeCode {
//创建模块文件
//判断文件是否存在
//_, err := os.OpenFile(name+"/"+v.GetString("name"), os.O_RDONLY, os.ModePerm)
_, err := os.Stat(name + "/" + v.GetString("name") + ".go")
if err != nil { //文件不存在,则根据模板创建
myCtr := strings.Replace(CtrTpt, "{{name}}", name, -1)
myCtr = strings.Replace(myCtr, "{{table}}", v.GetString("name"), -1)
_ = os.MkdirAll(name, os.ModeDir)
err = ioutil.WriteFile(name+"/"+v.GetString("name")+".go", []byte(myCtr), os.ModePerm)
if err != nil {
that.Error.SetError(err)
}
isMake = true
}
ctrList = ctrList + `"` + v.GetString("name") + `":` + v.GetString("name") + "Ctr,\r\n "
}
}
that.Config["tables"] = that.TableConfig
//生成id,判断数据库是否有改变,以保证数据库和配置文件匹配唯一
id := Md5(ObjToStr(idSlice))
if id == that.Config.GetString("id") {
if isMake { //有生成包文件
fmt.Println("有新的业务代码生成,请重新运行")
os.Exit(-1)
}
return
}
//数据生成完后进一步解析
for fk, fv := range that.TableColumns {
//判断是否将表写入menu中
isMenusGet := false //判断是否被目录收录
for indexKey, _ := range that.IndexMenus {
indexCode := strings.Index(indexKey, fk)
if indexCode == 0 || indexCode == 4 {
isMenusGet = false
continue
}
//如果相等或者表名在目录中已经设置(主要前一位是/并且他是最后一个字符串)
if indexKey == fk || (indexCode != -1 && indexKey[indexCode-1] == '/' && indexKey[indexCode:] == fk) {
isMenusGet = true
break
}
}
//目录没有收录
if !isMenusGet {
tablePrefixCode := strings.Index(fk, "_")
isNewPrefix := false //假定表名没有前缀
prefixName := ""
//并且代表有前缀,根据数据表分库设定使用
if tablePrefixCode != -1 {
prefixName = fk[:tablePrefixCode]
} else {
prefixName = fk
}
//if tablePrefixCode != -1 {
for ck, _ := range that.TableColumns {
//判断不止一个前缀相同
if (strings.Index(ck, prefixName) == 0 || strings.Index(prefixName, ck) == 4) && ck != fk {
isNewPrefix = true
break
}
}
//}
prefixName = DefaultMenuParentName + ":" + prefixName
menuIns := Map{"label": that.TableConfig.GetMap(fk).GetString("label"), "table": fk}
//多耗费一点内存
mMenu := Map{"menus": Slice{menuIns}, "label": that.TableConfig.GetMap(fk).GetString("label"), "name": prefixName, "icon": "el-icon-setting"}
//表名有前缀
if !isNewPrefix {
//是否已有对应前缀,已经有对应的menu只需要push进去即可
prefixName = DefaultMenuParentName
mMenu = Map{"menus": Slice{menuIns}, "label": "系统管理", "name": prefixName, "icon": "el-icon-setting"}
}
//没有新前缀
if that.IndexMenus[prefixName] != nil {
if that.IndexMenus[prefixName+"/"+fk] == nil {
that.IndexMenus.GetMap(prefixName)["menus"] = append(that.IndexMenus.GetMap(prefixName).GetSlice("menus"), menuIns)
that.IndexMenus[prefixName+"/"+fk] = menuIns
} else {
for k, v := range menuIns {
that.IndexMenus.GetMap(prefixName + "/" + fk)[k] = v
}
}
} else {
that.Config["menus"] = append(that.Config.GetSlice("menus"), mMenu) //注入配置
//写入Index
that.IndexMenus[prefixName] = mMenu
that.IndexMenus[prefixName+"/"+fk] = menuIns
}
}
for k, v := range fv {
//搜索服务
if that.SearchColumns[fk][v.GetString("name")] == nil &&
v.GetString("type") == "select" {
search := that.TableConfig.GetMap(fk).GetSlice("search")
sv := DeepCopyMap(v).(Map)
sv["value"] = nil
sv["options"] = append(sv.GetSlice("options"), Map{"name": "全部", "value": nil})
that.TableConfig.GetMap(fk)["search"] = append(search, sv)
that.SearchColumns[fk][k] = sv
}
//虚招后缀是_id结尾的表字段 假设org_id
if len(k) <= 3 || strings.LastIndex(k, "_id") != len(k)-3 {
continue
}
//普通表匹配 org_id匹配为org
oldTableName := k[:len(k)-3]
//上级ID匹配
if oldTableName == "parent" {
oldTableName = fk
}
//如果本身匹配则不再继续精简匹配
if that.TableConfig[oldTableName] == nil {
//如果依然找不到则查询system_org是否存在
if that.TableConfig[DefaultMenuParentName+"_"+oldTableName] != nil {
oldTableName = DefaultMenuParentName + "_" + oldTableName
}
//字段有动词前缀,自动进行解析
prefixColumn := strings.Index(oldTableName, "_")
//sys_org_id oldTableName即为sys此处判断为org表存在
if prefixColumn > -1 && that.TableConfig[oldTableName[prefixColumn+1:]] != nil {
oldTableName = oldTableName[prefixColumn+1:]
}
if prefixColumn >= len(oldTableName) {
prefixColumn = -1
}
//如果依然找不到则查询system_org是否存在
if prefixColumn > -1 && that.TableConfig[DefaultMenuParentName+"_"+oldTableName[prefixColumn+1:]] != nil {
oldTableName = DefaultMenuParentName + "_" + oldTableName[prefixColumn+1:]
}
}
//普通方式查询不到,则转换为大型项目模块划分,暂时只支持一级模块划分,
//比如表sys_user 字段org_id,查询不到sys_org表则查询org表,org表查询不到则查询默认前缀system_org表
//都查询不到则找不到,
prefix := strings.Index(fk, "_")
tableName := oldTableName
if prefix > 0 {
//表模块前缀sys_user sys即为前缀 sys_org
tableName = fk[:prefix+1] + oldTableName
if that.TableConfig[tableName] == nil || that.TableConfig[oldTableName] != nil {
//不存在则改为org
tableName = oldTableName
}
//表前缀+去除字段前缀
prefixColumn := strings.Index(oldTableName, "_")
if prefixColumn > -1 {
tableName = fk[:prefix+1] + oldTableName[prefixColumn+1:]
if that.TableConfig[tableName] == nil {
tableName = oldTableName
}
}
}
//如果数据匹配则写入到配置中
if that.TableConfig[tableName] != nil {
v["link"] = tableName
//一般查询name字段或者label字段,如果没有name字段则默认第二个地段
if that.TableColumns[tableName]["name"] != nil {
v["value"] = "name"
continue
}
if that.TableColumns[tableName]["label"] != nil {
v["value"] = "label"
continue
}
if len(that.TableConfig.GetMap(tableName).GetSlice("columns")) > 2 {
v["value"] = that.TableConfig.GetMap(tableName).GetSlice("columns").GetMap(1).GetString("name")
continue
}
}
}
}
//搜索增加树节点
for fk, fv := range that.TableColumns {
for k, v := range fv {
if v.GetString("link") != "" && that.SearchColumns[fk][k] == nil &&
that.TableColumns[v.GetString("link")]["parent_id"] != nil {
//搜索服务
search := that.TableConfig.GetMap(fk).GetSlice("search")
sv := Map{"type": "tree", "label": v["label"], "name": v["name"], "value": v["value"], "link": v["link"]}
that.TableConfig.GetMap(fk)["search"] = append(search, sv)
that.SearchColumns[fk][k] = sv
}
}
}
fmt.Println(id, "---", that.Config.GetString("id"))
that.Config["id"] = id
if makeCode {
//init文件初始化
myInit = strings.Replace(myInit, "{{id}}", id, -1)
myInit = strings.Replace(myInit, "{{tablesCtr}}", ctrList, -1)
_ = os.MkdirAll(name, os.ModeDir)
err = ioutil.WriteFile(name+"/init.go", []byte(myInit), os.ModePerm)
if err != nil {
that.Error.SetError(err)
}
}
//写入配置文件
//var configByte bytes.Buffer
//err = json.Indent(&configByte, []byte(that.Config.ToJsonString()), "", "\t")
_ = os.MkdirAll(filepath.Dir(path), os.ModeDir)
err = ioutil.WriteFile(path, []byte(that.Config.ToJsonString()), os.ModePerm)
if err != nil {
that.Error.SetError(err)
}
fmt.Println("有新的代码生成,请重新运行")
os.Exit(-1)
}
func (that *MakeCode) Info(table string, userData Map, db *db.HoTimeDB) (string, Map) {
reStr := ""
data := Map{}
var ruleData Map
for _, v := range that.TableColumns[table] {
if v == nil {
continue
}
//准备加入索引权限
if v.GetString("link") != "" &&
userData != nil &&
that.TableColumns[v.GetString("link")]["parent_id"] != nil {
//初始化ruleData
if ruleData == nil {
ruleData = Map{}
for _, v := range that.TableColumns["admin"] {
if v.GetString("link") != "" &&
v.GetString("name") != "parent_id" &&
userData.Get(v.GetString("name")) != nil {
ruleData[v.GetString("link")] = userData.Get(v.GetString("name"))
}
}
}
if ruleData[v.GetString("link")] != nil {
if v.GetString("name") == "parent_id" {
data["index[~]"] = "," + ruleData.GetString(v.GetString("link")) + ","
} else {
idMap := db.Select(v.GetString("link"), "id", Map{"index[~]": "," + ruleData.GetString(v.GetString("link")) + ","})
ids := Slice{ruleData.GetCeilInt(v.GetString("link"))}
for _, v := range idMap {
ids = append(ids, v.GetCeilInt("id"))
}
data[v.GetString("name")] = ids
}
}
}
if v.Get("info") == nil || v.GetBool("info") {
reStr += "`" + v.GetString("name") + "`,"
}
}
if len(reStr) != 0 {
reStr = reStr[:len(reStr)-1]
}
return reStr, data
}
func (that *MakeCode) Add(table string, req *http.Request) Map {
data := Map{}
for _, v := range that.TableColumns[table] {
//不可使用,未在前端展示,但在内存中保持有
if v.GetBool("notUse") {
if v.GetString("type") == "index" && that.TableColumns[table]["parent_id"] != nil {
data[v.GetString("name")] = ","
}
continue
}
if v.Get("add") == nil || v.GetBool("add") {
if len(req.Form[v.GetString("name")]) == 0 {
if v.GetBool("must") {
return nil
} else {
continue
}
}
reqValue := req.FormValue(v.GetString("name"))
if (reqValue == "" || reqValue == "null") && strings.Contains(v.GetString("name"), "id") {
data[v.GetString("name")] = nil
} else {
if v.GetString("type") == "password" {
data[v.GetString("name")] = Md5(reqValue)
} else {
data[v.GetString("name")] = reqValue
}
}
}
if v.GetString("name") == "create_time" {
data[v.GetString("name")] = time.Now().Unix()
continue
}
if v.GetString("name") == "modify_time" {
data[v.GetString("name")] = time.Now().Unix()
}
}
if len(data) == 0 {
return nil
}
return data
}
func (that *MakeCode) Edit(table string, req *http.Request) Map {
data := Map{}
for _, v := range that.TableColumns[table] {
//不可使用,未在前端展示,但在内存中保持有
if v.GetBool("notUse") {
if v.GetString("type") == "index" && that.TableColumns[table]["parent_id"] != nil {
data[v.GetString("name")] = ","
}
continue
}
if v.Get("edit") == nil || v.GetBool("edit") {
reqValue := req.FormValue(v.GetString("name"))
if reqValue == "" || reqValue == "null" {
continue
}
if v.GetString("type") == "password" {
data[v.GetString("name")] = Md5(reqValue)
} else {
data[v.GetString("name")] = reqValue
}
}
if v.GetString("name") == "modify_time" {
data[v.GetString("name")] = time.Now().Unix()
}
}
if len(data) == 0 {
return nil
}
return data
}
func (that *MakeCode) Delete(table string, req *http.Request) Map {
data := Map{}
for _, v := range that.TableColumns[table] {
//不可使用,未在前端展示,但在内存中保持有
if v.GetBool("notUse") {
if v.GetString("type") == "index" && that.TableColumns[table]["parent_id"] != nil {
data[v.GetString("name")] = ","
}
continue
}
}
return data
}
func (that *MakeCode) Search(table string, userData Map, req *http.Request, db *db.HoTimeDB) (string, Map, Map) {
reStr := ""
leftJoin := Map{}
data := Map{}
keyword := Map{}
daterange := Map{}
sort := Map{}
var ruleData Map
hasUser := false
keywordStr := req.FormValue("keyword")
for _, v := range that.TableColumns[table] {
//不可使用,未在前端展示,但在内存中保持有
if v.GetBool("notUse") {
continue
}
if v["list"] != false {
if v.GetString("link") != "" &&
v.GetString("name") != "parent_id" {
reStr += table + "." + v.GetString("name") + "," +
v.GetString("link") + "." + v.GetString("value") + " AS " +
v.GetString("link") + "_" + v.GetString("name") + "_" + v.GetString("value") + ","
leftJoin["[>]"+v.GetString("link")] =
table + "." + v.GetString("name") + "=" +
v.GetString("link") + ".id"
if v.GetString("link") == "admin" {
hasUser = true
}
reqValue := req.FormValue(v.GetString("name"))
if reqValue != "" {
data[table+"."+v.GetString("name")] = reqValue
}
} else {
reStr += table + "." + v.GetString("name") + ","
}
//准备加入索引权限
if v.GetString("link") != "" &&
userData != nil &&
that.TableColumns[v.GetString("link")]["parent_id"] != nil {
//初始化ruleData
if ruleData == nil {
ruleData = Map{}
for _, v := range that.TableColumns["admin"] {
if v.GetString("link") != "" &&
v.GetString("name") != "parent_id" &&
userData.Get(v.GetString("name")) != nil {
ruleData[v.GetString("link")] = userData.Get(v.GetString("name"))
}
}
}
if ruleData[v.GetString("link")] != nil {
if v.GetString("name") == "parent_id" {
data[table+".index[~]"] = "," + ruleData.GetString(v.GetString("link")) + ","
} else {
idMap := db.Select(v.GetString("link"), "id", Map{"index[~]": "," + ruleData.GetString(v.GetString("link")) + ","})
ids := Slice{ruleData.GetCeilInt(v.GetString("link"))}
for _, v := range idMap {
ids = append(ids, v.GetCeilInt("id"))
}
data[table+"."+v.GetString("name")] = ids
}
}
}
if keywordStr != "" {
if v.GetString("type") == "text" {
keyword[table+"."+v.GetString("name")+"[~]"] = keywordStr
}
if v.GetString("name") == "id" {
keyword[table+"."+v.GetString("name")] = keywordStr
}
if v.GetString("link") != "" &&
v.GetString("name") != "parent_id" {
childs := db.Select(v.GetString("link"), "id", Map{v.GetString("value") + "[~]": keywordStr})
childIds := Slice{}
for _, cv := range childs {
childIds = append(childIds, cv.GetString("id"))
}
if len(childIds) != 0 {
keyword[v.GetString("link")+".id"] = childIds
}
}
}
}
}
if len(reStr) != 0 {
reStr = reStr[:len(reStr)-1]
}
search := that.TableConfig.GetMap(table).GetSlice("search")
for k, _ := range search {
reqValue := req.FormValue(search.GetMap(k).GetString("name"))
if reqValue == "" {
continue
}
searchItem := search.GetMap(k)
searchItemName := searchItem.GetString("name")
//columns := that.TableConfig.GetMap(table).GetSlice("columns")
if searchItem.GetString("type") == "search" {
for _, v := range that.TableColumns[table] {
if v["list"] == false {
continue
}
//日期类型
if searchItemName == "daterange" && v.GetString("type") == "time" {
//fmt.Println(req.Form["daterange"])
daterange[table+"."+v.GetString("name")+"[<>]"] = ObjToSlice(req.Form["daterange"])
}
}
if searchItem.GetString("name") == "sort" {
sort["ORDER"] = table + "." + reqValue
}
continue
}
//树节点模式搜索
if searchItemName == "parent_id" {
parentID := ObjToInt(req.FormValue("parent_id"))
if parentID == 0 {
parentID = userData.GetCeilInt(table + "_id")
data["OR"] = Map{table + ".id": parentID, table + ".parent_id": nil}
} else {
data[table+".parent_id"] = parentID
}
continue
}
data[table+"."+searchItemName] = reqValue
}
if sort["ORDER"] == nil {
sort["ORDER"] = table + ".id DESC"
}
where := Map{}
if len(keyword) == 1 {
for k, v := range keyword {
data[k] = v
}
}
if len(keyword) > 1 {
if data["OR"] != nil {
data = Map{"AND": data, "OR": keyword}
} else {
data["OR"] = keyword
}
}
if len(daterange) == 1 {
for k, v := range daterange {
data[k] = v
}
}
if len(daterange) > 1 {
if data["AND"] != nil {
data = Map{"AND": Map{"AND": data, "OR": daterange}}
}
}
if len(data) > 1 {
where["AND"] = data
}
if len(data) == 1 {
where = data
}
if len(where) == 0 && hasUser {
//where["admin.id"] = userData["id"]
}
if len(sort) != 0 {
for k, v := range sort {
where[k] = v
}
}
return reStr, leftJoin, where
}
func setListener() {
}
+230
View File
@@ -0,0 +1,230 @@
package code
var InitTpt = `package {{name}}
import (
. "code.hoteas.com/golang/hotime"
. "code.hoteas.com/golang/hotime/common"
)
var ID = "{{id}}"
// Project 管理端项目
var Project = Proj{
//"user": UserCtr,
{{tablesCtr}}
"hotime":Ctr{
"login": func(that *Context) {
name := that.Req.FormValue("name")
password := that.Req.FormValue("password")
if name == "" || password == "" {
that.Display(3, "参数不足")
return
}
user := that.Db.Get("admin", "*", Map{"AND": Map{"OR":Map{"name": name,"phone":name}, "password": Md5(password)}})
if user == nil {
that.Display(5, "登录失败")
return
}
that.Session("admin_id", user.GetCeilInt("id"))
that.Session("admin_name", name)
that.Display(0, that.SessionId)
},
"logout": func(that *Context) {
that.Session("admin_id", nil)
that.Session("admin_name", nil)
that.Display(0, "退出登录成功")
},
"info": func(that *Context) {
data := that.Db.Get("admin", "*", Map{"id": that.Session("admin_id").ToCeilInt()})
str, inData := that.MakeCode.Info("admin", data, that.Db)
where := Map{"id": that.Session("admin_id").ToCeilInt()}
if len(inData) ==1 {
inData["id"] =where["id"]
where = Map{"AND": inData}
}else if len(inData) >1 {
where["OR"]=inData
where = Map{"AND": where}
}
re := that.Db.Get("admin", str, where)
if re == nil {
that.Display(4, "找不到对应信息")
return
}
for k, v := range re {
column := that.MakeCode.TableColumns["admin"][k]
if column == nil {
continue
}
if (column["list"] == nil || column.GetBool("list")) && column.GetString("link") != "" {
re[column.GetString("link")] = that.Db.Get(column.GetString("link"),"id," +column.GetString("value"), Map{"id": v})
}
}
that.Display(0, re)
},
},
}
`
var CtrTpt = `package {{name}}
import (
. "code.hoteas.com/golang/hotime"
. "code.hoteas.com/golang/hotime/common"
"strings"
)
var {{table}}Ctr = Ctr{
"info": func(that *Context) {
data := that.Db.Get("admin", "*", Map{"id": that.Session("admin_id").ToCeilInt()})
str, inData := that.MakeCode.Info(that.RouterString[1], data, that.Db)
where := Map{"id": that.RouterString[2]}
if len(inData) ==1 {
inData["id"] =where["id"]
where = Map{"AND": inData}
}else if len(inData) >1 {
where["OR"]=inData
where = Map{"AND": where}
}
re := that.Db.Get(that.RouterString[1], str, where)
if re == nil {
that.Display(4, "找不到对应信息")
return
}
for k, v := range re {
column := that.MakeCode.TableColumns[that.RouterString[1]][k]
if column == nil {
continue
}
if (column["list"] == nil || column.GetBool("list")) && column.GetString("link") != "" {
re[column.GetString("link")] = that.Db.Get(column.GetString("link"), "id,"+column.GetString("value"), Map{"id": v})
}
}
that.Display(0, re)
},
"add": func(that *Context) {
inData := that.MakeCode.Add(that.RouterString[1], that.Req)
if inData == nil {
that.Display(3, "请求参数不足")
return
}
re := that.Db.Insert(that.RouterString[1], inData)
if re == 0 {
that.Display(4, "无法插入对应数据")
return
}
//索引管理,便于检索以及权限
if inData.Get("parent_id") != nil && inData.GetString("index") != "" {
index := that.Db.Get(that.RouterString[1], "` + "`index`" + `", Map{"id": inData.Get("parent_id")})
inData["index"] = index.GetString("index")+ObjToStr(re)+","
that.Db.Update(that.RouterString[1],Map{"index":inData["index"]},Map{"id":re})
}else if inData.GetString("index") != ""{
inData["index"] = "," + ObjToStr(re) + ","
that.Db.Update(that.RouterString[1], Map{"index": inData["index"]}, Map{"id": re})
}
that.Display(0, re)
},
"update": func(that *Context) {
inData := that.MakeCode.Edit(that.RouterString[1], that.Req)
if inData == nil {
that.Display(3, "没有找到要更新的数据")
return
}
//索引管理,便于检索以及权限
if inData.Get("parent_id") != nil && inData.GetString("index") != "" {
Index := that.Db.Get(that.RouterString[1], "` + "`index`" + `", Map{"id": that.RouterString[2]})
parentIndex := that.Db.Get(that.RouterString[1], "` + "`index`" + `", Map{"id": inData.Get("parent_id")})
inData["index"] = parentIndex.GetString("index") + that.RouterString[2] + ","
childNodes := that.Db.Select(that.RouterString[1], "id,` + "`index`" + `", Map{"index[~]": "," + that.RouterString[2] + ","})
for _, v := range childNodes {
v["index"] = strings.Replace(v.GetString("index"), Index.GetString("index"), inData.GetString("index"), -1)
that.Db.Update(that.RouterString[1], Map{"index": v["index"]}, Map{"id": v.GetCeilInt("id")})
}
}
re := that.Db.Update(that.RouterString[1], inData, Map{"id": that.RouterString[2]})
if re == 0 {
that.Display(4, "更新数据失败")
return
}
that.Display(0, re)
},
"remove": func(that *Context) {
inData := that.MakeCode.Delete(that.RouterString[1], that.Req)
if inData == nil {
that.Display(3, "请求参数不足")
return
}
re :=int64(0)
//索引管理,便于检索以及权限
if inData.Get("parent_id") != nil && inData.GetSlice("index") != nil {
re=that.Db.Delete(that.RouterString[1], Map{"index[~]": "," + that.RouterString[2] + ","})
}else {
re=that.Db.Delete(that.RouterString[1], Map{"id": that.RouterString[2]})
}
if re == 0 {
that.Display(4, "删除数据失败")
return
}
that.Display(0, "删除成功")
},
"search": func(that *Context) {
data := that.Db.Get("admin", "*", Map{"id": that.Session("admin_id").ToCeilInt()})
columnStr, leftJoin, where := that.MakeCode.Search(that.RouterString[1], data, that.Req, that.Db)
page := ObjToInt(that.Req.FormValue("page"))
pageSize := ObjToInt(that.Req.FormValue("pageSize"))
if page < 1 {
page = 1
}
if pageSize <= 0 {
pageSize = 20
}
count := that.Db.Count(that.RouterString[1], leftJoin, where)
reData := that.Db.Page(page, pageSize).
PageSelect(that.RouterString[1], leftJoin, columnStr, where)
for _, v := range reData {
for k, _ := range v {
column := that.MakeCode.TableColumns[that.RouterString[1]][k]
if column == nil {
continue
}
if column["list"] != false && column["name"] == "parent_id" && column.GetString("link") != "" {
parentC := that.Db.Get(column.GetString("link"), column.GetString("value"), Map{"id": v.GetCeilInt(k)})
v[column.GetString("link")+"_"+column.GetString("name")+"_"+column.GetString("value")] = ""
if parentC != nil {
v[column.GetString("link")+"_"+column.GetString("name")+"_"+column.GetString("value")] = parentC.GetString(column.GetString("value"))
}
}
}
}
that.Display(0, Map{"count": count, "data": reData})
},
}
`
+18
View File
@@ -0,0 +1,18 @@
package common
import (
"time"
)
type ContextBase struct {
tag string
}
//唯一标志
func (that *ContextBase) GetTag() string {
if that.tag == "" {
that.tag = ObjToStr(time.Now().Unix()) + ":" + ObjToStr(Random())
}
return that.tag
}
+27
View File
@@ -0,0 +1,27 @@
package common
import (
"github.com/sirupsen/logrus"
)
// Error 框架层处理错误
type Error struct {
Logger *logrus.Logger
error
}
func (that *Error) GetError() error {
return that.error
}
func (that *Error) SetError(err error) {
that.error = err
if that.Logger != nil && err != nil {
//that.Logger=log.GetLog("",false)
that.Logger.Warn(err)
}
return
}
+45 -90
View File
@@ -1,15 +1,10 @@
package hotime
package common
import (
"crypto/md5"
"encoding/hex"
"fmt"
"math"
"os"
"path/filepath"
"runtime"
"strings"
"time"
)
//安全锁
@@ -29,83 +24,7 @@ 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()
}
//字符串首字符大写
// StrFirstToUpper 字符串首字符大写
func StrFirstToUpper(str string) string {
if len(str) == 0 {
return str
@@ -117,7 +36,43 @@ func StrFirstToUpper(str string) string {
return strings.ToUpper(first) + other
}
//字符串截取
// StrLd 相似度计算 ld compares two strings and returns the levenshtein distance between them.
func StrLd(s, t string, ignoreCase bool) int {
if ignoreCase {
s = strings.ToLower(s)
t = strings.ToLower(t)
}
d := make([][]int, len(s)+1)
for i := range d {
d[i] = make([]int, len(t)+1)
}
for i := range d {
d[i][0] = i
}
for j := range d[0] {
d[0][j] = j
}
for j := 1; j <= len(t); j++ {
for i := 1; i <= len(s); i++ {
if s[i-1] == t[j-1] {
d[i][j] = d[i-1][j-1]
} else {
min := d[i-1][j]
if d[i][j-1] < min {
min = d[i][j-1]
}
if d[i-1][j-1] < min {
min = d[i-1][j-1]
}
d[i][j] = min + 1
}
}
}
return d[len(s)][len(t)]
}
// Substr 字符串截取
func Substr(str string, start int, length int) string {
rs := []rune(str)
rl := len(rs)
@@ -148,7 +103,7 @@ func Substr(str string, start int, length int) string {
return string(rs[start:end])
}
//获取最后出现字符串的下标
// IndexLastStr 获取最后出现字符串的下标
//return 找不到返回 -1
func IndexLastStr(str, sep string) int {
sepSlice := []rune(sep)
@@ -179,7 +134,7 @@ func IndexLastStr(str, sep string) int {
return -1
}
//md5
// Md5 md5
func Md5(req string) string {
md5Ctx := md5.New()
md5Ctx.Write([]byte(req))
@@ -187,7 +142,7 @@ func Md5(req string) string {
return hex.EncodeToString(cipherStr)
}
//随机数
// Rand 随机数
func Rand(count int) int {
res := Random()
for i := 0; i < count; i++ {
@@ -212,7 +167,7 @@ func Random() float64 {
}
//随机数范围
// RandX 随机数范围
func RandX(small int, max int) int {
res := 0
//随机对象
@@ -264,7 +219,7 @@ func RandX(small int, max int) int {
// GetDb()
//}
//复制返回数组
// DeepCopyMap 复制返回数组
func DeepCopyMap(value interface{}) interface{} {
if valueMap, ok := value.(Map); ok {
newMap := make(Map)
@@ -323,7 +278,7 @@ func DeepCopyMap(value interface{}) interface{} {
// }
//}
//浮点数四舍五入保留小数
// Round 浮点数四舍五入保留小数
func Round(f float64, n int) float64 {
pow10_n := math.Pow10(n)
return math.Trunc((f+0.5/pow10_n)*pow10_n) / pow10_n
+163
View File
@@ -0,0 +1,163 @@
package common
import (
"encoding/json"
"errors"
"reflect"
)
//hotime的常用map
type Map map[string]interface{}
//获取string
func (that Map) GetString(key string, err ...*Error) string {
if len(err) != 0 {
err[0].SetError(nil)
}
return ObjToStr((that)[key])
}
func (that *Map) Pointer() *Map {
return that
}
//增加接口
func (that Map) Put(key string, value interface{}) {
//if that==nil{
// that=Map{}
//}
that[key] = value
}
//删除接口
func (that Map) Delete(key string) {
delete(that, key)
}
//获取Int
func (that Map) GetInt(key string, err ...*Error) int {
v := ObjToInt((that)[key], err...)
return v
}
//获取Int
func (that Map) GetInt64(key string, err ...*Error) int64 {
v := ObjToInt64((that)[key], err...)
return v
}
//获取向上取整Int64
func (that Map) GetCeilInt64(key string, err ...*Error) int64 {
v := ObjToCeilInt64((that)[key], err...)
return v
}
//获取向上取整Int
func (that Map) GetCeilInt(key string, err ...*Error) int {
v := ObjToCeilInt((that)[key], err...)
return v
}
//获取向上取整float64
func (that Map) GetCeilFloat64(key string, err ...*Error) float64 {
v := ObjToCeilFloat64((that)[key], err...)
return v
}
//获取Float64
func (that Map) GetFloat64(key string, err ...*Error) float64 {
v := ObjToFloat64((that)[key], err...)
return v
}
func (that Map) GetSlice(key string, err ...*Error) Slice {
//var v Slice
v := ObjToSlice((that)[key], err...)
return v
}
func (that Map) GetBool(key string, err ...*Error) bool {
//var v Slice
v := ObjToBool((that)[key], err...)
return v
}
func (that Map) GetMap(key string, err ...*Error) Map {
//var data Slice
v := ObjToMap((that)[key], err...)
return v
}
func (that Map) Get(key string, err ...*Error) interface{} {
if v, ok := (that)[key]; ok {
return v
}
e := errors.New("没有存储key及对应的数据")
if len(err) != 0 {
err[0].SetError(e)
}
return nil
}
//请传递指针过来
func (that Map) ToStruct(stct interface{}) {
data := reflect.ValueOf(stct).Elem()
for k, v := range that {
ks := StrFirstToUpper(k)
dkey := data.FieldByName(ks)
if !dkey.IsValid() {
continue
}
switch dkey.Type().String() {
case "int":
dkey.SetInt(that.GetInt64(k))
case "int64":
dkey.Set(reflect.ValueOf(that.GetInt64(k)))
case "float64":
dkey.Set(reflect.ValueOf(that.GetFloat64(k)))
case "string":
dkey.Set(reflect.ValueOf(that.GetString(k)))
case "interface{}":
dkey.Set(reflect.ValueOf(v))
}
}
}
func (that Map) ToJsonString() string {
return ObjToStr(that)
}
func (that Map) JsonToMap(jsonStr string, err ...*Error) {
e := json.Unmarshal([]byte(jsonStr), &that)
if e != nil && len(err) != 0 {
err[0].SetError(e)
}
}
+94
View File
@@ -0,0 +1,94 @@
package common
//对象封装方便取用
type Obj struct {
Data interface{}
Error
ContextBase
}
func (that *Obj) Put(data interface{}) {
that.Data = data
}
func (that *Obj) ToInt(err ...Error) int {
if len(err) != 0 {
that.Error = err[0]
}
return ObjToInt(that.Data, &that.Error)
}
func (that *Obj) ToInt64(err ...Error) int64 {
if len(err) != 0 {
that.Error = err[0]
}
return ObjToInt64(that.Data, &that.Error)
}
func (that *Obj) ToFloat64(err ...Error) float64 {
if len(err) != 0 {
that.Error = err[0]
}
return ObjToFloat64(that.Data, &that.Error)
}
// ToCeilFloat64 获取向上取整float64
func (that *Obj) ToCeilFloat64(err ...*Error) float64 {
if len(err) != 0 {
that.Error = *err[0]
}
v := ObjToCeilFloat64(that.Data, err...)
return v
}
func (that *Obj) ToStr() string {
return ObjToStr(that.Data)
}
func (that *Obj) ToMap(err ...Error) Map {
if len(err) != 0 {
that.Error = err[0]
}
return ObjToMap(that.Data, &that.Error)
}
func (that *Obj) ToSlice(err ...Error) Slice {
if len(err) != 0 {
that.Error = err[0]
}
return ObjToSlice(that.Data, &that.Error)
}
func (that *Obj) ToMapArray(err ...Error) []Map {
if len(err) != 0 {
that.Error = err[0]
}
return ObjToMapArray(that.Data, &that.Error)
}
func (that *Obj) ToObj() interface{} {
return that.Data
}
//获取向上取整Int64
func (that *Obj) ToCeilInt64(err ...*Error) int64 {
if len(err) != 0 {
that.Error = *err[0]
}
v := ObjToCeilInt64(that.Data, err...)
return v
}
//获取向上取整Int
func (that *Obj) ToCeilInt(err ...*Error) int {
if len(err) != 0 {
that.Error = *err[0]
}
v := ObjToCeilInt(that.Data, err...)
return v
}
+37 -2
View File
@@ -1,4 +1,4 @@
package hotime
package common
import (
"encoding/json"
@@ -135,6 +135,15 @@ func ObjToFloat64(obj interface{}, e ...*Error) float64 {
err = errors.New("没有合适的转换对象!")
}
}
if math.IsNaN(v) {
err = errors.New("float64 is NaN")
v = 0
}
if math.IsInf(v, 0) {
err = errors.New("float64 is Inf")
v = 0
}
if len(e) != 0 {
e[0].SetError(err)
}
@@ -212,6 +221,31 @@ func ObjToInt(obj interface{}, e ...*Error) int {
return int(v)
}
func ObjToBool(obj interface{}, e ...*Error) bool {
var err error
v := false
if obj == nil {
err = errors.New("没有合适的转换对象!")
} else {
switch obj.(type) {
case bool:
v = obj.(bool)
default:
toInt := ObjToInt(obj)
if toInt != 0 {
v = true
}
err = errors.New("没有合适的转换对象!")
}
}
if len(e) != 0 {
e[0].SetError(err)
}
return v
}
func ObjToStr(obj interface{}) string {
// fmt.Println(reflect.ValueOf(obj).Type().String() )
str := ""
@@ -232,7 +266,8 @@ func ObjToStr(obj interface{}) string {
case float64:
str = strconv.FormatFloat(obj.(float64), 'f', -1, 64)
default:
strbte, err := json.Marshal(obj)
strbte, err := json.MarshalIndent(obj, "", "\t")
if err == nil {
str = string(strbte)
}
+96
View File
@@ -0,0 +1,96 @@
package common
import (
"errors"
)
type Slice []interface{}
// GetString 获取string
func (that Slice) GetString(key int, err ...*Error) string {
if len(err) != 0 {
err[0].SetError(nil)
}
return ObjToStr((that)[key])
}
// GetInt 获取Int
func (that Slice) GetInt(key int, err ...*Error) int {
v := ObjToInt((that)[key], err...)
return v
}
// GetInt64 获取Int
func (that Slice) GetInt64(key int, err ...*Error) int64 {
v := ObjToInt64((that)[key], err...)
return v
}
// GetCeilInt64 获取向上取整Int64
func (that Slice) GetCeilInt64(key int, err ...*Error) int64 {
v := ObjToCeilInt64((that)[key], err...)
return v
}
// GetCeilInt 获取向上取整Int
func (that Slice) GetCeilInt(key int, err ...*Error) int {
v := ObjToCeilInt((that)[key], err...)
return v
}
// GetCeilFloat64 获取向上取整float64
func (that Slice) GetCeilFloat64(key int, err ...*Error) float64 {
v := ObjToCeilFloat64((that)[key], err...)
return v
}
// GetFloat64 获取Float64
func (that Slice) GetFloat64(key int, err ...*Error) float64 {
v := ObjToFloat64((that)[key], err...)
return v
}
func (that Slice) GetSlice(key int, err ...*Error) Slice {
v := ObjToSlice((that)[key], err...)
return v
}
func (that Slice) GetBool(key int, err ...*Error) bool {
//var v Slice
v := ObjToBool((that)[key], err...)
return v
}
func (that Slice) GetMap(key int, err ...*Error) Map {
//var v Map
v := ObjToMap((that)[key], err...)
return v
}
func (that Slice) Get(key int, err ...*Error) interface{} {
if key < len(that) {
return that[key]
}
e := errors.New("没有存储key及对应的数据")
if len(err) != 0 {
err[0].SetError(e)
}
return nil
}
func (that Slice) Put(key int, value interface{}) {
that[key] = value
}
func (that Slice) ToJsonString() string {
return ObjToStr(that)
}
+1 -13
View File
@@ -1,16 +1,4 @@
package hotime
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储存头
// HEAD_SESSION_ADD session储存头
const HEAD_SESSION_ADD = "session#"
+26 -19
View File
@@ -1,65 +1,72 @@
package hotime
import (
. "code.hoteas.com/golang/hotime/cache"
. "code.hoteas.com/golang/hotime/common"
. "code.hoteas.com/golang/hotime/db"
"encoding/json"
"errors"
"net/http"
)
type Context struct {
contextBase
*Application
Resp http.ResponseWriter
Req *http.Request
Application *Application
RouterString []string
Config Map
Db *HoTimeDB
RespData Map
CacheIns
SessionIns
DataSize int
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}
resp := Map{"status": 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)
//logFmt(errors.New("找不到对应的错误码"), 2, LOG_WARN)
}
temp["type"] = tpe
temp["msg"] = data
resp["result"] = temp
//兼容android等需要json转对象的服务
resp["error"] = temp
} else {
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.DataSize = len(d)
that.RespData = nil
that.Resp.Write(d)
return
}
-17
View File
@@ -1,17 +0,0 @@
package hotime
import "time"
type contextBase struct {
Error
tag int64
}
//唯一标志
func (this *contextBase) GetTag() int64 {
if this.tag == int64(0) {
this.tag = time.Now().UnixNano()
}
return this.tag
}
+273 -176
View File
@@ -1,9 +1,13 @@
package hotime
package db
import (
"code.hoteas.com/golang/hotime/cache"
. "code.hoteas.com/golang/hotime/common"
"database/sql"
"encoding/json"
"errors"
_ "github.com/go-sql-driver/mysql"
_ "github.com/mattn/go-sqlite3"
"os"
"reflect"
"strings"
@@ -11,31 +15,38 @@ import (
type HoTimeDB struct {
*sql.DB
contextBase
CacheIns
ContextBase
DBName string
*cache.HoTimeCache
Type string
DBCached bool
Prefix string
LastQuery string
LastData []interface{}
ConnectFunc func(err ...*Error) *sql.DB
LastErr Error
ConnectFunc func(err ...*Error) (*sql.DB, *sql.DB)
LastErr *Error
limit Slice
Tx *sql.Tx //事务对象
*sql.Tx //事务对象
SlaveDB *sql.DB
}
// SetConnect 设置数据库配置连接
func (that *HoTimeDB) SetConnect(connect func(err ...*Error) (master, slave *sql.DB), err ...*Error) {
that.ConnectFunc = connect
_ = that.InitDb(err...)
}
//设置数据库配置连接
func (this *HoTimeDB) SetConnect(connect func(err ...*Error) *sql.DB, err ...*Error) {
this.ConnectFunc = connect
this.InitDb()
// 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, HoTimeCache: that.HoTimeCache, Prefix: that.Prefix}
tx, err := db.Begin()
if err != nil {
this.LastErr.SetError(err)
that.LastErr.SetError(err)
return false
}
@@ -44,62 +55,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.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)
return this.LastErr
if that.SlaveDB != nil {
e := that.SlaveDB.Ping()
that.LastErr.SetError(e)
}
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 := DeepCopyMap(qu[1]).(Map)
temp["LIMIT"] = that.limit
qu[1] = temp
}
if len(qu) == 3 {
temp := qu[2].(Map)
temp["LIMIT"] = this.limit
temp := DeepCopyMap(qu[2]).(Map)
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()
@@ -111,22 +134,27 @@ 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++ {
//fmt.Println(reflect.ValueOf(a[j]).Type().String() )
if a[j] != nil && reflect.ValueOf(a[j]).Type().String() == "[]uint8" {
lis[strs[j]] = string(a[j].([]byte))
} else {
lis[strs[j]] = a[j]
lis[strs[j]] = a[j] //取实际类型
}
}
//防止int被误读为float64
jlis, e := json.Marshal(lis)
if e != nil {
this.LastErr.SetError(e)
} else {
lis.JsonToMap(string(jlis), &this.LastErr)
}
//jlis, e := json.Marshal(lis)
//if e != nil {
// that.LastErr.SetError(e)
//} else {
// lis.JsonToMap(string(jlis), that.LastErr)
//}
dest = append(dest, lis)
@@ -137,7 +165,7 @@ func (this *HoTimeDB) Row(resl *sql.Rows) []Map {
//
////code=0,1,2 0 backup all,1 backup data,2 backup ddl
//func (this *HoTimeDB) Backup(path string, code int) {
//func (that *HoTimeDB) Backup(path string, code int) {
// var cmd *exec.Cmd
// switch code {
// case 0:cmd= exec.Command("mysqldump","-h"+ObjToStr(Config["dbHost"]), "-P"+ObjToStr(Config["dbPort"]),"-u"+ObjToStr(Config["dbUser"]), "-p"+ObjToStr(Config["dbPwd"]),ObjToStr(Config["dbName"]))
@@ -169,7 +197,7 @@ func (this *HoTimeDB) Row(resl *sql.Rows) []Map {
// //db := ``
// //fmt.Println(db)
// //
// //tables := this.Query("show tables")
// //tables := that.Query("show tables")
// //lth := len(tables)
// //if lth == 0 {
// // return
@@ -184,31 +212,31 @@ func (this *HoTimeDB) Row(resl *sql.Rows) []Map {
// //
// //for i := 0; i < lth; i++ {
// // tt := tables[i]["Tables_in_"+db].(string)
// // this.backupSave(path, tt, code)
// // that.backupSave(path, tt, code)
// // debug.FreeOSMemory()
// //}
//
//}
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 ""
}
@@ -216,9 +244,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)
@@ -228,7 +256,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 + "`)"
@@ -270,87 +298,92 @@ 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 := that.DB
if that.SlaveDB != nil {
db = that.SlaveDB
}
if this.DB == nil {
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 = this.DB.Query(query, args...)
resl, err = db.Query(query, args...)
}
this.LastErr.SetError(err)
that.LastErr.SetError(err)
if err != nil {
if err = this.DB.Ping(); err != nil {
this.LastErr.SetError(err)
this.InitDb()
if this.LastErr.GetError() != nil {
if err = db.Ping(); err != 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{
//func (that *HoTimeDB)copy(data []Map)[]Map{
// if data==nil{
// return nil
// }
@@ -368,7 +401,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{}
@@ -406,8 +440,11 @@ func (this *HoTimeDB) Select(table string, qu ...interface{}) []Map {
} else {
query += " *"
}
query += " FROM " + table
if !strings.Contains(table, ".") && !strings.Contains(table, " AS ") {
query += " FROM `" + that.Prefix + table + "`"
} else {
query += " FROM " + that.Prefix + table
}
if join {
for k, v := range qu[0].(Map) {
@@ -430,39 +467,39 @@ 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.HoTimeCache != nil && table != "cached" {
//如果缓存有则从缓存取
cacheData := this.Cache(table + ":" + md5)
cacheData := that.HoTimeCache.Db(table + ":" + md5)
if cacheData.Data != nil {
if cacheData != nil && cacheData.Data != nil {
return cacheData.ToMapArray()
}
}
//无缓存则数据库取
res := this.Query(query, qs...)
res := that.Query(query, qs...)
if res == nil {
res = []Map{}
}
//缓存
if this.DBCached && this.CacheIns != nil {
if that.HoTimeCache != nil && table != "cached" {
this.Cache(table+":"+md5, res)
_ = that.HoTimeCache.Db(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})
@@ -478,19 +515,19 @@ 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 (that *HoTimeDB) GetPrefix() string {
return that.Prefix
}
/**
** 计数
*/
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(*)")
@@ -501,7 +538,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
@@ -517,7 +554,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 := ""
@@ -529,7 +566,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...)
@@ -547,7 +584,16 @@ func (this *HoTimeDB) where(data Map) (string, []interface{}) {
y++
}
if x == len(condition) && y == len(vcond) {
tv, vv := this.varCond(k, v)
if v != nil && reflect.ValueOf(v).Type().String() == "common.Slice" && len(v.(Slice)) == 0 {
continue
}
if v != nil && reflect.ValueOf(v).Type().String() == "[]interface {}" && len(v.([]interface{})) == 0 {
continue
}
tv, vv := that.varCond(k, v)
where += tv
res = append(res, vv...)
@@ -576,7 +622,7 @@ func (this *HoTimeDB) where(data Map) (string, []interface{}) {
where += " " + k
}
if reflect.ValueOf(v).Type().String() == "hotime.Slice" {
if reflect.ValueOf(v).Type().String() == "common.Slice" {
for i := 0; i < len(v.(Slice)); i++ {
where += " " + ObjToStr(v.(Slice)[i])
@@ -601,52 +647,86 @@ 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)
if length > 4 {
if k == "[#]" {
k = strings.Replace(k, "[#]", "", -1)
where += " " + ObjToStr(v) + " "
} else if length > 0 && strings.Contains(k, "[") && k[length-1] == ']' {
def := false
switch Substr(k, length-3, 3) {
case "[>]":
k = strings.Replace(k, "[>]", "", -1)
where += "`" + k + "`>? "
if !strings.Contains(k, ".") {
k = "`" + k + "`"
}
where += k + ">? "
res = append(res, v)
case "[<]":
k = strings.Replace(k, "[<]", "", -1)
where += "`" + k + "`<? "
if !strings.Contains(k, ".") {
k = "`" + k + "`"
}
where += k + "<? "
res = append(res, v)
case "[!]":
k = strings.Replace(k, "[!]", "", -1)
where, res = this.notIn(k, v, where, res)
if !strings.Contains(k, ".") {
k = "`" + k + "`"
}
where, res = that.notIn(k, v, where, res)
case "[#]":
k = strings.Replace(k, "[#]", "", -1)
if !strings.Contains(k, ".") {
k = "`" + k + "`"
}
where += " " + k + "=" + ObjToStr(v)
case "[#!]":
k = strings.Replace(k, "[#!]", "", -1)
if !strings.Contains(k, ".") {
k = "`" + k + "`"
}
where += " " + k + "!=" + ObjToStr(v)
case "[!#]":
k = strings.Replace(k, "[!#]", "", -1)
if !strings.Contains(k, ".") {
k = "`" + k + "`"
}
where += " " + k + "!=" + ObjToStr(v)
case "[~]":
k = strings.Replace(k, "[~]", "", -1)
where += "`" + k + "` LIKE ? "
if !strings.Contains(k, ".") {
k = "`" + k + "`"
}
where += k + " LIKE ? "
v = "%" + ObjToStr(v) + "%"
res = append(res, v)
case "[!~]": //左边任意
k = strings.Replace(k, "[~]", "", -1)
where += "`" + k + "` LIKE ? "
if !strings.Contains(k, ".") {
k = "`" + k + "`"
}
where += k + " LIKE ? "
v = "%" + ObjToStr(v)
res = append(res, v)
case "[~!]": //右边任意
k = strings.Replace(k, "[~]", "", -1)
where += "`" + k + "` LIKE ? "
if !strings.Contains(k, ".") {
k = "`" + k + "`"
}
where += k + " LIKE ? "
v = ObjToStr(v) + "%"
res = append(res, v)
case "[~~]": //手动任意
k = strings.Replace(k, "[~]", "", -1)
where += "`" + k + "` LIKE ? "
if !strings.Contains(k, ".") {
k = "`" + k + "`"
}
where += k + " LIKE ? "
//v = ObjToStr(v)
res = append(res, v)
default:
@@ -657,26 +737,41 @@ func (this *HoTimeDB) varCond(k string, v interface{}) (string, []interface{}) {
switch Substr(k, length-4, 4) {
case "[>=]":
k = strings.Replace(k, "[>=]", "", -1)
where += "`" + k + "`>=? "
if !strings.Contains(k, ".") {
k = "`" + k + "`"
}
where += k + ">=? "
res = append(res, v)
case "[<=]":
k = strings.Replace(k, "[<=]", "", -1)
where += "`" + k + "`<=? "
if !strings.Contains(k, ".") {
k = "`" + k + "`"
}
where += k + "<=? "
res = append(res, v)
case "[><]":
k = strings.Replace(k, "[><]", "", -1)
where += "`" + k + "` NOT BETWEEN ? AND ? "
if !strings.Contains(k, ".") {
k = "`" + k + "`"
}
where += k + " NOT BETWEEN ? AND ? "
res = append(res, v.(Slice)[0])
res = append(res, v.(Slice)[1])
case "[<>]":
k = strings.Replace(k, "[<>]", "", -1)
where += "`" + k + "` BETWEEN ? AND ? "
if !strings.Contains(k, ".") {
k = "`" + k + "`"
}
where += k + " BETWEEN ? AND ? "
res = append(res, v.(Slice)[0])
res = append(res, v.(Slice)[1])
default:
if reflect.ValueOf(v).Type().String() == "hotime.Slice" {
where += "`" + k + "` IN ("
res = append(res, (v.(Slice))...)
if !strings.Contains(k, ".") {
k = "`" + k + "`"
}
if reflect.ValueOf(v).Type().String() == "common.Slice" {
where += k + " IN ("
res = append(res, v.(Slice)...)
if len(v.(Slice)) == 0 {
where += ") "
} else {
@@ -691,25 +786,25 @@ func (this *HoTimeDB) varCond(k string, v interface{}) (string, []interface{}) {
}
} else {
where += "`" + k + "`=? "
where += k + "=? "
res = append(res, v)
}
}
}
} else if k == "[#]" {
k = strings.Replace(k, "[#]", "", -1)
where += " " + ObjToStr(v) + " "
} else {
//fmt.Println(reflect.ValueOf(v).Type().String())
if !strings.Contains(k, ".") {
k = "`" + k + "`"
}
if v == nil {
where += "`" + k + "` IS NULL"
} else if reflect.ValueOf(v).Type().String() == "hotime.Slice" {
where += k + " IS NULL"
} else if reflect.ValueOf(v).Type().String() == "common.Slice" {
//fmt.Println(v)
where += "`" + k + "` IN ("
res = append(res, (v.(Slice))...)
where += k + " IN ("
res = append(res, v.(Slice)...)
for i := 0; i < len(v.(Slice)); i++ {
if i+1 != len(v.(Slice)) {
where += "?,"
@@ -719,8 +814,9 @@ func (this *HoTimeDB) varCond(k string, v interface{}) (string, []interface{}) {
//res=append(res,(v.(Slice))[i])
}
} else if reflect.ValueOf(v).Type().String() == "[]interface {}" {
where += "`" + k + "` IN ("
res = append(res, (v.([]interface{}))...)
where += k + " IN ("
res = append(res, v.([]interface{})...)
for i := 0; i < len(v.([]interface{})); i++ {
if i+1 != len(v.([]interface{})) {
where += "?,"
@@ -731,7 +827,7 @@ func (this *HoTimeDB) varCond(k string, v interface{}) (string, []interface{}) {
}
} else {
where += "`" + k + "`=? "
where += k + "=? "
res = append(res, v)
}
@@ -740,17 +836,17 @@ func (this *HoTimeDB) varCond(k string, v interface{}) (string, []interface{}) {
return where, res
}
// 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{}) {
// that.Db.Update("user",hotime.Map{"ustate":"1"},hotime.Map{"AND":hotime.Map{"OR":hotime.Map{"uid":4,"uname":"dasda"}},"ustate":1})
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 {
where += "`" + k + "` IS NOT NULL "
where += k + " IS NOT NULL "
} else if reflect.ValueOf(v).Type().String() == "hotime.Slice" {
where += "`" + k + "` NOT IN ("
res = append(res, (v.(Slice))...)
} else if reflect.ValueOf(v).Type().String() == "common.Slice" {
where += k + " NOT IN ("
res = append(res, v.(Slice)...)
for i := 0; i < len(v.(Slice)); i++ {
if i+1 != len(v.(Slice)) {
where += "?,"
@@ -760,8 +856,8 @@ func (this *HoTimeDB) notIn(k string, v interface{}, where string, res []interfa
//res=append(res,(v.(Slice))[i])
}
} else if reflect.ValueOf(v).Type().String() == "[]interface {}" {
where += "`" + k + "` NOT IN ("
res = append(res, (v.([]interface{}))...)
where += k + " NOT IN ("
res = append(res, v.([]interface{})...)
for i := 0; i < len(v.([]interface{})); i++ {
if i+1 != len(v.([]interface{})) {
where += "?,"
@@ -772,7 +868,7 @@ func (this *HoTimeDB) notIn(k string, v interface{}, where string, res []interfa
}
} else {
where += "`" + k + "` !=? "
where += k + " !=? "
res = append(res, v)
}
@@ -780,7 +876,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)
@@ -791,7 +887,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 + ") "
@@ -807,7 +903,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 {
@@ -822,10 +918,10 @@ 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 "
query := "UPDATE `" + that.Prefix + table + "` SET "
//UPDATE Person SET Address = 'Zhongshan 23', City = 'Nanjing' WHERE LastName = 'Wilson'
qs := make([]interface{}, 0)
tp := len(data)
@@ -845,13 +941,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 {
@@ -860,22 +956,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.HoTimeCache != nil && table != "cached" {
_ = that.HoTimeCache.Db(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 + " "
query := "DELETE FROM " + that.Prefix + 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()
@@ -883,8 +979,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.HoTimeCache != nil && table != "cached" {
_ = that.HoTimeCache.Db(table+"*", nil)
}
}
//return 0
@@ -892,8 +988,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 := " ("
@@ -913,20 +1009,21 @@ func (this *HoTimeDB) Insert(table string, data map[string]interface{}) int64 {
}
}
query := "INSERT INTO " + table + queryString + "VALUES" + valueString
query := "INSERT INTO `" + that.Prefix + 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()
id1, err := res.LastInsertId()
that.LastErr.SetError(err)
id = id1
}
//如果插入成功,删除缓存
if id != 0 {
if this.DBCached && this.CacheIns != nil {
this.Cache(table+"*", nil)
if that.HoTimeCache != nil && table != "cached" {
_ = that.HoTimeCache.Db(table+"*", nil)
}
}
+134
View File
@@ -0,0 +1,134 @@
package aliyun
import (
. "code.hoteas.com/golang/hotime/common"
"fmt"
"io/ioutil"
"net/http"
//"fmt"
)
type company struct {
ApiCode string
Url string
}
var Company = company{}
func (that *company) Init(apiCode string) {
//"06c6a07e89dd45c88de040ee1489eef7"
that.ApiCode = apiCode
that.Url = "http://api.81api.com"
}
// GetCompanyOtherAll 获取企业基础信息
func (that *company) GetCompanyOtherAll(name string) Map {
res := Map{}
data, e := that.GetCompanyPatentsInfo(name) //获取专利信息
if e != nil {
fmt.Println(e)
} else {
res["PatentsInfo"] = data.GetMap("data")
}
data, e = that.GetCompanyOtherCopyrightsInfo(name) //获取其他专利
if e != nil {
fmt.Println(e)
} else {
res["OtherCopyrightsInfo"] = data.GetMap("data")
}
data, e = that.GetCompanyTrademarksInfo(name) //获取商标
if e != nil {
fmt.Println(e)
} else {
res["TrademarksInfo"] = data.GetMap("data")
}
data, e = that.GetCompanySoftwareCopyrightsInfo(name) //获取软著
if e != nil {
fmt.Println(e)
} else {
res["SoftwareCopyrightsInfo"] = data.GetMap("data")
}
data, e = that.GetCompanyProfileTags(name) //获取大数据标签
if e != nil {
fmt.Println(e)
} else {
res["ProfileTags"] = data.GetSlice("data")
}
return res
}
// GetCompanyBaseInfo 获取企业基础信息
func (that *company) GetCompanyBaseInfo(name string) (Map, error) {
url := "/getCompanyBaseInfo/"
body, err := that.basePost(url, name)
return ObjToMap(body), err
}
// GetCompanyPatentsInfo 获取专利信息
func (that *company) GetCompanyPatentsInfo(name string) (Map, error) {
url := "/getCompanyPatentsInfo/"
body, err := that.basePost(url, name)
return ObjToMap(body), err
}
// GetCompanyTrademarksInfo 获取商标信息
func (that *company) GetCompanyTrademarksInfo(name string) (Map, error) {
url := "/getCompanyTrademarksInfo/"
body, err := that.basePost(url, name)
return ObjToMap(body), err
}
// GetCompanySoftwareCopyrightsInfo 获取软著信息
func (that *company) GetCompanySoftwareCopyrightsInfo(name string) (Map, error) {
url := "/getCompanySoftwareCopyrightsInfo/"
body, err := that.basePost(url, name)
return ObjToMap(body), err
}
// GetCompanyOtherCopyrightsInfo 获取其他著作信息
func (that *company) GetCompanyOtherCopyrightsInfo(name string) (Map, error) {
url := "/getCompanyOtherCopyrightsInfo/"
body, err := that.basePost(url, name)
return ObjToMap(body), err
}
// GetCompanyProfileTags 获取大数据标签
func (that *company) GetCompanyProfileTags(name string) (Map, error) {
url := "/getCompanyProfileTags/"
body, err := that.basePost(url, name)
return ObjToMap(body), err
}
func (that *company) basePost(url string, name string) (string, error) {
client := &http.Client{}
reqest, err := http.NewRequest("GET", that.Url+url+name+"/?isRaiseErrorCode=1", nil)
if err != nil {
fmt.Println("Fatal error ", err.Error())
return "", err
}
reqest.Header.Add("Authorization", "APPCODE "+that.ApiCode)
response, err := client.Do(reqest)
defer response.Body.Close()
if err != nil {
fmt.Println("Fatal error ", err.Error())
return "", err
}
body, err := ioutil.ReadAll(response.Body)
if err != nil {
return "", err
}
res := string(body)
fmt.Println(res)
return res, err
}
+54
View File
@@ -0,0 +1,54 @@
package baidu
import (
"fmt"
"io/ioutil"
"net/http"
"net/url"
)
type baiduMap struct {
Ak string
Url string
}
var BaiDuMap = baiduMap{}
func (that *baiduMap) Init(Ak string) {
//"ak=ZeT902EZvVgIoGVWEFK3osUm"
that.Ak = Ak
that.Url = "https://api.map.baidu.com/place/v2/suggestion?output=json" + "&ak=" + Ak
//query
}
// GetPosition 获取定位列表
func (that *baiduMap) GetPosition(name string, region string) (string, error) {
client := &http.Client{}
if region == "" {
region = "全国"
}
reqest, err := http.NewRequest("GET", that.Url+"&query="+url.PathEscape(name)+"&region="+url.PathEscape(region), nil)
if err != nil {
fmt.Println("Fatal error ", err.Error())
return "", err
}
response, err := client.Do(reqest)
defer response.Body.Close()
if err != nil {
fmt.Println("Fatal error ", err.Error())
return "", err
}
body, err := ioutil.ReadAll(response.Body)
if err != nil {
return "", err
}
//fmt.Println(string(body))
return string(body), err
}
+18 -16
View File
@@ -10,31 +10,33 @@ import (
//"fmt"
)
type DDY struct {
type dingdongyun struct {
ApiKey string
YzmUrl string
TzUrl string
}
func (this *DDY) Init(apikey string) {
this.ApiKey = apikey
this.YzmUrl = "https://api.dingdongcloud.com/v2/sms/single_send"
this.TzUrl = "https://api.dingdongcloud.com/v1/sms/notice/multi_send"
var DDY = dingdongyun{}
func (that *dingdongyun) Init(apikey string) {
that.ApiKey = apikey
that.YzmUrl = "https://api.dingdongcloud.com/v2/sms/captcha/send.json"
that.TzUrl = "https://api.dingdongcloud.com/v2/sms/notice/send.json"
}
//发送短信验证码 code验证码如:123456 返回true表示发送成功flase表示发送失败
func (this *DDY) SendYZM(umoblie string, tpt string, data map[string]string) (bool, error) {
// SendYZM 发送短信验证码 code验证码如:123456 返回true表示发送成功flase表示发送失败
func (that *dingdongyun) SendYZM(umoblie string, tpt string, data map[string]string) (bool, error) {
for k, v := range data {
tpt = strings.Replace(tpt, "{"+k+"}", v, -1)
}
return this.send(this.YzmUrl, umoblie, tpt)
return that.send(that.YzmUrl, umoblie, tpt)
}
//发送通知
func (this *DDY) SendTz(umoblie []string, tpt string, data map[string]string) (bool, error) {
// SendTz 发送通知
func (that *dingdongyun) SendTz(umoblie []string, tpt string, data map[string]string) (bool, error) {
for k, v := range data {
tpt = strings.Replace(tpt, "["+k+"]", v, -1)
tpt = strings.Replace(tpt, "{"+k+"}", v, -1)
}
umobleStr := ""
for i, v := range umoblie {
@@ -44,14 +46,14 @@ func (this *DDY) SendTz(umoblie []string, tpt string, data map[string]string) (b
}
umobleStr += "," + v
}
return this.send(this.TzUrl, umobleStr, tpt)
return that.send(that.TzUrl, umobleStr, tpt)
}
//发送短信
func (this *DDY) send(mUrl string, umoblie string, content string) (bool, error) {
func (that *dingdongyun) send(mUrl string, umoblie string, content string) (bool, error) {
data_send_sms_yzm := url.Values{"apikey": {this.ApiKey}, "mobile": {umoblie}, "content": {content}}
res, err := this.httpsPostForm(mUrl, data_send_sms_yzm)
data_send_sms_yzm := url.Values{"apikey": {that.ApiKey}, "mobile": {umoblie}, "content": {content}}
res, err := that.httpsPostForm(mUrl, data_send_sms_yzm)
if err != nil && res == "" {
return false, errors.New("连接错误")
}
@@ -73,7 +75,7 @@ func (this *DDY) send(mUrl string, umoblie string, content string) (bool, error)
}
//调用url发送短信的连接
func (this *DDY) httpsPostForm(url string, data url.Values) (string, error) {
func (that *dingdongyun) httpsPostForm(url string, data url.Values) (string, error) {
resp, err := http.PostForm(url, data)
if err != nil {
+11 -10
View File
@@ -2,37 +2,38 @@ package download
import (
"bytes"
"code.hoteas.com/golang/hotime"
. "code.hoteas.com/golang/hotime/common"
"io"
"io/ioutil"
"net/http"
"os"
)
//下载文件
func Down(url, path, name string) bool {
// Down 下载文件
func Down(url, path, name string, e ...*Error) bool {
os.MkdirAll(path, os.ModeDir)
if hotime.Substr(path, len(path)-1, len(path)) != "/" {
if Substr(path, len(path)-1, len(path)) != "/" {
path = path + "/"
}
out, err := os.Create(path + name)
e := hotime.Error{}
if err != nil {
e.SetError(err)
if err != nil && e[0] != nil {
e[0].SetError(err)
return false
}
defer out.Close()
resp, err := http.Get(url)
if err != nil {
if err != nil && e[0] != nil {
e[0].SetError(err)
return false
}
defer resp.Body.Close()
pix, err := ioutil.ReadAll(resp.Body)
_, err = io.Copy(out, bytes.NewReader(pix))
if err != nil {
e.SetError(err)
if err != nil && e[0] != nil {
e[0].SetError(err)
return false
}
return true
+143
View File
@@ -0,0 +1,143 @@
package rsa
import (
"crypto/rand"
"crypto/rsa"
"crypto/x509"
"encoding/asn1"
"encoding/pem"
"fmt"
"os"
)
func FileGet(path string) []byte {
file, err := os.Open(path)
if err != nil {
panic(err)
}
defer file.Close()
//读取文件的内容
info, _ := file.Stat()
buf := make([]byte, info.Size())
file.Read(buf)
return buf
}
// RSA_Encrypt RSA加密
// plainText 要加密的数据
// path 公钥匙文件地址
func RSA_Encrypt(plainText []byte, buf []byte) []byte {
//pem解码
block, _ := pem.Decode(buf)
//x509解码
publicKeyInterface, err := x509.ParsePKIXPublicKey(block.Bytes)
if err != nil {
panic(err)
}
//类型断言
publicKey := publicKeyInterface.(*rsa.PublicKey)
//对明文进行加密
cipherText, err := rsa.EncryptPKCS1v15(rand.Reader, publicKey, plainText)
if err != nil {
panic(err)
}
//返回密文
return cipherText
}
// RSA_Decrypt RSA解密
// cipherText 需要解密的byte数据
// path 私钥文件路径
func RSA_Decrypt(cipherText []byte, buf []byte) []byte {
//pem解码
block, _ := pem.Decode(buf)
//X509解码
private, err := x509.ParsePKCS8PrivateKey(block.Bytes)
if err != nil {
panic(err)
}
//对密文进行解密
//plainText,_:=rsa.DecryptPKCS1v15(rand.Reader,privateKey,cipherText)
v, err := rsa.DecryptPKCS1v15(rand.Reader, private.(*rsa.PrivateKey), cipherText)
//返回明文
return v
}
func MarshalPKCS8PrivateKey(key *rsa.PrivateKey) []byte {
info := struct {
Version int
PrivateKeyAlgorithm []asn1.ObjectIdentifier
PrivateKey []byte
}{}
info.Version = 0
info.PrivateKeyAlgorithm = make([]asn1.ObjectIdentifier, 1)
info.PrivateKeyAlgorithm[0] = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 1}
info.PrivateKey = x509.MarshalPKCS1PrivateKey(key)
k, err := asn1.Marshal(info)
if err != nil {
panic(err.Error())
}
return k
}
func Demo() {
//生成密钥对,保存到文件
GenerateRSAKey(2048, "./")
//加密
data := []byte("hello world")
encrypt := RSA_Encrypt(data, FileGet("public.pem"))
fmt.Println(string(encrypt))
// 解密
decrypt := RSA_Decrypt(encrypt, FileGet("private.pem"))
fmt.Println(string(decrypt))
}
// GenerateRSAKey 生成RSA私钥和公钥,保存到文件中
// bits 证书大小
func GenerateRSAKey(bits int, path string) {
//GenerateKey函数使用随机数据生成器random生成一对具有指定字位数的RSA密钥
//Reader是一个全局、共享的密码用强随机数生成器
privateKey, err := rsa.GenerateKey(rand.Reader, bits)
if err != nil {
panic(err)
}
//保存私钥
//通过x509标准将得到的ras私钥序列化为ASN.1 的 DER编码字符串
X509PrivateKey := x509.MarshalPKCS1PrivateKey(privateKey)
//使用pem格式对x509输出的内容进行编码
//创建文件保存私钥
privateFile, err := os.Create(path + "private.pem")
if err != nil {
panic(err)
}
defer privateFile.Close()
//构建一个pem.Block结构体对象
privateBlock := pem.Block{Type: "RSA Private Key", Bytes: X509PrivateKey}
//将数据保存到文件
pem.Encode(privateFile, &privateBlock)
//保存公钥
//获取公钥的数据
publicKey := privateKey.PublicKey
//X509对公钥编码
X509PublicKey, err := x509.MarshalPKIXPublicKey(&publicKey)
if err != nil {
panic(err)
}
//pem格式编码
//创建用于保存公钥的文件
publicFile, err := os.Create(path + "public.pem")
if err != nil {
panic(err)
}
defer publicFile.Close()
//创建一个pem.Block结构体对象
publicBlock := pem.Block{Type: "RSA Public Key", Bytes: X509PublicKey}
//保存到文件
pem.Encode(publicFile, &publicBlock)
}
+119
View File
@@ -0,0 +1,119 @@
package tencent
import (
. "code.hoteas.com/golang/hotime/common"
"crypto/hmac"
"crypto/sha1"
"encoding/base64"
"fmt"
"io"
"io/ioutil"
"net/http"
gourl "net/url"
"strings"
"time"
)
type company struct {
secretId string
secretKey string
}
var Company = company{}
func (that *company) Init(secretId, secretKey string) {
// 云市场分配的密钥Id
//secretId := "xxxx"
//// 云市场分配的密钥Key
//secretKey := "xxxx"
that.secretId = secretId
that.secretKey = secretKey
}
func (that *company) calcAuthorization(source string) (auth string, datetime string, err error) {
timeLocation, _ := time.LoadLocation("Etc/GMT")
datetime = time.Now().In(timeLocation).Format("Mon, 02 Jan 2006 15:04:05 GMT")
signStr := fmt.Sprintf("x-date: %s\nx-source: %s", datetime, source)
// hmac-sha1
mac := hmac.New(sha1.New, []byte(that.secretKey))
mac.Write([]byte(signStr))
sign := base64.StdEncoding.EncodeToString(mac.Sum(nil))
auth = fmt.Sprintf("hmac id=\"%s\", algorithm=\"hmac-sha1\", headers=\"x-date x-source\", signature=\"%s\"",
that.secretId, sign)
return auth, datetime, nil
}
func (that *company) urlencode(params map[string]string) string {
var p = gourl.Values{}
for k, v := range params {
p.Add(k, v)
}
return p.Encode()
}
func (that *company) GetCompany(name string) Map {
// 云市场分配的密钥Id
//secretId := "xxxx"
//// 云市场分配的密钥Key
//secretKey := "xxxx"
source := "market"
// 签名
auth, datetime, _ := that.calcAuthorization(source)
// 请求方法
method := "GET"
// 请求头
headers := map[string]string{"X-Source": source, "X-Date": datetime, "Authorization": auth}
// 查询参数
queryParams := make(map[string]string)
queryParams["keyword"] = name
// body参数
bodyParams := make(map[string]string)
// url参数拼接
url := "https://service-3jnh3ku8-1256140209.gz.apigw.tencentcs.com/release/business4/geet"
if len(queryParams) > 0 {
url = fmt.Sprintf("%s?%s", url, that.urlencode(queryParams))
}
bodyMethods := map[string]bool{"POST": true, "PUT": true, "PATCH": true}
var body io.Reader = nil
if bodyMethods[method] {
body = strings.NewReader(that.urlencode(bodyParams))
headers["Content-Type"] = "application/x-www-form-urlencoded"
}
client := &http.Client{
Timeout: 5 * time.Second,
}
request, err := http.NewRequest(method, url, body)
if err != nil {
fmt.Println(err)
return nil
}
for k, v := range headers {
request.Header.Set(k, v)
}
response, err := client.Do(request)
if err != nil {
fmt.Println(err)
return nil
}
defer response.Body.Close()
bodyBytes, err := ioutil.ReadAll(response.Body)
if err != nil {
fmt.Println(err)
return nil
}
res := string(bodyBytes)
fmt.Println(res)
return ObjToMap(res)
}
+104
View File
@@ -0,0 +1,104 @@
package tencent
import (
"fmt"
"github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common"
"github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common/errors"
"github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common/profile"
ocr "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/ocr/v20181119"
)
type tencent struct {
secretId string
secretKey string
credential *common.Credential
}
var Tencent = tencent{}
func (that *tencent) Init(secretId, secretKey string) {
// 云市场分配的密钥Id
//secretId := "xxxx"
//// 云市场分配的密钥Key
//secretKey := "xxxx"
that.secretId = secretId
that.secretKey = secretKey
that.credential = common.NewCredential(
"AKIDOgT8cKCQksnY7yKATaYO7j9ORJzSYohP",
"GNXgjdN4czA9ya0FNMApVJzTmsmU0KSN",
)
}
func (that *tencent) OCRCOMPANY(base64Str string) string {
cpf := profile.NewClientProfile()
cpf.HttpProfile.Endpoint = "ocr.tencentcloudapi.com"
client, _ := ocr.NewClient(that.credential, "ap-guangzhou", cpf)
request := ocr.NewBizLicenseOCRRequest()
//request.ImageUrl = common.StringPtr("https://img0.baidu.com/it/u=2041013181,3227632688&fm=26&fmt=auto")
request.ImageBase64 = common.StringPtr(base64Str)
response, err := client.BizLicenseOCR(request)
if _, ok := err.(*errors.TencentCloudSDKError); ok {
fmt.Println("An API error has returned: %s", err)
return ""
}
if err != nil {
fmt.Println("An API error has returned: %s", err)
return ""
}
//fmt.Printf("%s", response.ToJsonString())
return response.ToJsonString()
}
func (that *tencent) OCR(base64Str string) string {
cpf := profile.NewClientProfile()
cpf.HttpProfile.Endpoint = "ocr.tencentcloudapi.com"
client, _ := ocr.NewClient(that.credential, "ap-guangzhou", cpf)
request := ocr.NewGeneralAccurateOCRRequest()
//request.ImageUrl = common.StringPtr("https://img0.baidu.com/it/u=2041013181,3227632688&fm=26&fmt=auto")
request.ImageBase64 = common.StringPtr(base64Str)
response, err := client.GeneralAccurateOCR(request)
if _, ok := err.(*errors.TencentCloudSDKError); ok {
fmt.Println("An API error has returned: %s", err)
return ""
}
if err != nil {
fmt.Println("An API error has returned: %s", err)
return ""
}
//fmt.Printf("%s", response.ToJsonString())
return response.ToJsonString()
}
func (that *tencent) Qrcode(base64Str string) string {
cpf := profile.NewClientProfile()
cpf.HttpProfile.Endpoint = "ocr.tencentcloudapi.com"
client, _ := ocr.NewClient(that.credential, "ap-guangzhou", cpf)
request := ocr.NewQrcodeOCRRequest()
request.ImageBase64 = common.StringPtr(base64Str)
response, err := client.QrcodeOCR(request)
if _, ok := err.(*errors.TencentCloudSDKError); ok {
fmt.Println("An API error has returned: %s", err)
return ""
}
if err != nil {
fmt.Println("An API error has returned: %s", err)
return ""
}
//fmt.Printf("%s", response.ToJsonString())
return response.ToJsonString()
}
+5 -5
View File
@@ -1,7 +1,7 @@
package upload
import (
"code.hoteas.com/golang/hotime"
. "code.hoteas.com/golang/hotime/common"
"errors"
"io"
"mime/multipart"
@@ -15,7 +15,7 @@ type Upload struct {
Path string
}
func (this *Upload) UpFile(Request *http.Request, fieldName, savefilepath, savePath string) (string, error) {
func (that *Upload) UpFile(Request *http.Request, fieldName, savefilepath, savePath string) (string, error) {
Request.ParseMultipartForm(32 << 20)
var filePath string
files := Request.MultipartForm.File
@@ -36,7 +36,7 @@ func (this *Upload) UpFile(Request *http.Request, fieldName, savefilepath, saveP
data := time.Unix(int64(t), 0).Format("2006-01")
path := ""
if strings.EqualFold(savefilepath, "") {
path = this.Path + data
path = that.Path + data
} else {
path = savefilepath + data
}
@@ -50,8 +50,8 @@ func (this *Upload) UpFile(Request *http.Request, fieldName, savefilepath, saveP
}
}
}
filename := time.Unix(int64(t), 0).Format("2006-01-02-15-22-25") + hotime.ObjToStr(hotime.Rand(6))
filePath = path + "/" + filename + this.Path
filename := time.Unix(int64(t), 0).Format("2006-01-02-15-22-25") + ObjToStr(Rand(6))
filePath = path + "/" + filename + that.Path
} else {
filePath = savePath
}
-25
View File
@@ -1,25 +0,0 @@
package hotime
//框架层处理错误
type Error struct {
error
err error
}
func (this *Error) GetError() error {
return this.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
return
}
+56
View File
@@ -0,0 +1,56 @@
{
"avatarPath": "avatar/2006/01/02/",
"cache": {
"db": {
"db": false,
"session": true
},
"memory": {
"db": true,
"session": true,
"timeout": 7200
}
},
"codeConfig": {
"admin": "config/app.json"
},
"codeConfig1": {
"admin": {
"config": "config/app.json",
"package": "admin",
"rule": "config/rule.json"
}
},
"crossDomain": "auto",
"db": {
"mysql": {
"host": "192.168.6.253",
"name": "iedc_dev",
"password": "dasda8454456",
"port": "3306",
"prefix": "",
"user": "root"
}
},
"defFile": [
"index.html",
"index.htm"
],
"error": {
"1": "内部系统异常",
"2": "访问权限异常",
"3": "请求参数异常",
"4": "数据处理异常",
"5": "数据结果异常"
},
"imgPath": "img/2006/01/02/",
"mode": 3,
"port": "8081",
"sessionName": "HOTIME",
"smsKey": "b0eb4bf0198b9983cffcb85b69fdf4fa",
"smsLogin": "【政企超链接】您的验证码为:{code},请在5分钟内使用,切勿将验证码泄露于他人,如非本人操作请忽略。",
"tpt": "tpt",
"wechatAppID": "wx2edb802f5c3ae1ae",
"wechatAppSecret": "4ff97e523c3de6bad47051b568522386",
"wxFilePath": "wxfile/2006/01/02/"
}
+72
View File
@@ -0,0 +1,72 @@
{
"cache": {
"db": {
"db": "默认false,非必须,缓存数据库,启用后能减少数据库的读写压力",
"session": "默认true,非必须,缓存web session,同时缓存session保持的用户缓存",
"timeout": "默认60 * 60 * 24 * 30,非必须,过期时间,超时自动删除"
},
"memory": {
"db": "默认true,非必须,缓存数据库,启用后能减少数据库的读写压力",
"session": "默认true,非必须,缓存web session,同时缓存session保持的用户缓存",
"timeout": "默认60 * 60 * 2,非必须,过期时间,超时自动删除"
},
"redis": {
"db": "默认true,非必须,缓存数据库,启用后能减少数据库的读写压力",
"host": "默认服务ip127.0.0.1,必须,如果需要使用redis服务时配置,",
"password": "默认密码空,必须,如果需要使用redis服务时配置,默认密码空",
"port": "默认服务端口:6379,必须,如果需要使用redis服务时配置,",
"session": "默认true,非必须,缓存web session,同时缓存session保持的用户缓存",
"timeout": "默认60 * 60 * 24 * 15,非必须,过期时间,超时自动删除"
},
"注释": "可配置memorydbredis,默认启用memory,默认优先级为memory\u003eredis\u003edb,memory与数据库缓存设置项一致,缓存数据填充会自动反方向反哺,加入memory缓存过期将自动从redis更新,但memory永远不会更新redis,如果是集群建议不要开启memory,配置即启用"
},
"codeConfig": {
"packageName": "默认无,必须,包名称以及应用名,生成代码的配置文件地址,比如config/app.json,数据库有更新时自动更新配置文件以及对应的生成文件",
"注释": "配置即启用,非必须,默认无"
},
"crossDomain": "默认空 非必须,空字符串为不开启,如果需要跨域设置,auto为智能开启所有网站允许跨域,http://www.baidu.com为指定域允许跨域",
"db": {
"mysql": {
"host": "默认127.0.0.1,必须,数据库ip地址",
"name": "默认test,必须,数据库名称",
"password": "默认root,必须,数据库密码",
"port": "默认3306,必须,数据库端口",
"prefix": "默认空,非必须,数据表前缀",
"slave": {
"host": "默认127.0.0.1,必须,数据库ip地址",
"name": "默认test,必须,数据库名称",
"password": "默认root,必须,数据库密码",
"port": "默认3306,必须,数据库端口",
"user": "默认root,必须,数据库用户名",
"注释": "从数据库配置,mysql里配置slave项即启用主从读写,减少数据库压力"
},
"user": "默认root,必须,数据库用户名",
"注释": "除prefix及主从数据库slave项,其他全部必须"
},
"sqlite": {
"path": "默认config/data.db,必须,数据库位置"
},
"注释": "配置即启用,非必须,默认使用sqlite数据库"
},
"defFile": "默认访问index.html或者index.htm文件,必须,默认访问文件类型",
"error": {
"1": "内部系统异常,在环境配置,文件访问权限等基础运行环境条件不足造成严重错误时使用",
"2": "访问权限异常,没有登录或者登录异常等时候使用",
"3": "请求参数异常,request参数不满足要求,比如参数不足,参数类型错误,参数不满足要求等时候使用",
"4": "数据处理异常,数据库操作或者三方请求返回的结果非正常结果,比如数据库突然中断等时候使用",
"5": "数据结果异常,一般用于无法给出response要求的格式要求下使用,比如response需要的是string格式但你只能提供int数据时",
"注释": "web服务内置错误提示,自定义异常建议10开始"
},
"logFile": "无默认,非必须,如果需要存储日志文件时使用,保存格式为:a/b/c/20060102150405.txt,将生成:a/b/c/年月日时分秒.txt,按需设置",
"logLevel": "默认0,必须,0关闭,1打印,日志等级",
"mode": "默认0,非必须,0生产模式,1,测试模式,2开发模式,3内嵌代码模式,在开发模式下会显示更多的数据用于开发测试,并能够辅助研发,自动生成配置文件、代码等功能,web无缓存,数据库不启用缓存",
"modeRouterStrict": "默认false,必须,路由严格模式false,为大小写忽略必须匹配,true必须大小写匹配",
"port": "默认80,必须,web服务开启Http端口,0为不启用http服务,默认80",
"sessionName": "默认HOTIME,必须,设置session的cookie名",
"tlsCert": "默认空,非必须,https证书",
"tlsKey": "默认空,非必须,https密钥",
"tlsPort": "默认空,非必须,web服务https端口,0为不启用https服务",
"tpt": "默认tpt,必须,web静态文件目录,默认为程序目录下tpt目录",
"webConnectLogFile": "无默认,非必须,webConnectLogShow开启之后才能使用,如果需要存储日志文件时使用,保存格式为:a/b/c/20060102150405.txt,将生成:a/b/c/年月日时分秒.txt,按需设置",
"webConnectLogShow": "默认true,非必须,访问日志如果需要web访问链接、访问ip、访问时间打印,false为关闭true开启此功能"
}
Binary file not shown.
Binary file not shown.
+5 -96
View File
@@ -2,105 +2,14 @@ package main
import (
"code.hoteas.com/golang/hotime"
"code.hoteas.com/golang/hotime/tools/db"
"fmt"
//"go.hoteas.com/hotime/cache"
"golang.org/x/net/websocket"
"time"
//"go.hoteas.com/hotime/cache"
)
func main() {
appIns := hotime.Application{}
appIns.SetConnectListener(func(context *hotime.Context) bool {
//fmt.Println(context.HandlerStr + time.Now().Format(" 2006-01-02 15:04 ") + hotime.Substr(context.Req.RemoteAddr, 0, strings.Index(context.Req.RemoteAddr, ":")))
//this.HandlerStr = "/test.html"
return true
})
//手动模式,
appIns.SetConfig("example/config/config.json")
//redis缓存接入
//ca:=hotime.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)
//自动选择数据库
db.SetDB(&appIns)
//appIns.SetConnectDB(func(err ...*hotime.Error) *sql.DB {
// query := appIns.Config.GetString("dbUser") + ":" + appIns.Config.GetString("dbPwd") +
// "@tcp(" + appIns.Config.GetString("dbHost") + ":" + appIns.Config.GetString("dbPort") + ")/" + appIns.Config.GetString("dbName") + "?charset=utf8"
// DB, e := sql.Open("mysql", query)
// if e != nil && len(err) != 0 {
// err[0].SetError(e)
// }
// return DB
//})
//内存缓存数据库数据,错误则删除
// appIns.Db.CacheIns=hotime.CacheIns(&hotime.CacheMemory{})
appIns.SetSession(hotime.CacheIns(&hotime.CacheMemory{}), hotime.CacheIns(&hotime.CacheDb{Db: &appIns.Db, Time: appIns.Config.GetInt64("cacheTime")}))
appIns.SetCache(hotime.CacheIns(&hotime.CacheMemory{}))
//快捷模式
//appIns.SetDefault(func(err ...*hotime.Error) *sql.DB {
// query := appIns.Config.GetString("dbUser") + ":" + appIns.Config.GetString("dbPwd") +
// "@tcp(" + appIns.Config.GetString("dbHost") + ":" + appIns.Config.GetString("dbPort") + ")/" + appIns.Config.GetString("dbName") + "?charset=utf8"
// DB, e := sql.Open("mysql", query)
// if e != nil && len(err) != 0 {
// err[0].SetError(e)
// }
// return DB
//})
appIns.Run(hotime.Router{
"app": hotime.Proj{
"index": hotime.Ctr{
"test": func(this *hotime.Context) {
fmt.Println(this.Db.GetTag())
//x:=this.Db.Action(func(db hotime.HoTimeDB) bool {
//
// db.Insert("user",hotime.Map{"unickname":"dasdas"})
//
// return true
//})
hotime.LogError("dasdasdasdasdas")
this.Display(5, "dsadas")
},
"websocket": func(this *hotime.Context) {
hdler := websocket.Handler(func(ws *websocket.Conn) {
for true {
msg := make([]byte, 5120)
n, err := ws.Read(msg)
go func() {
time.Sleep(time.Second * 5)
ws.Write([]byte("dsadasdasgregergrerge"))
}()
if err != nil {
return
}
fmt.Printf("Receive: %s\n", msg[:n])
send_msg := "[" + string(msg[:n]) + "]"
m, err := ws.Write([]byte(send_msg))
if err != nil {
return
}
fmt.Printf("Send: %s\n", msg[:m])
}
})
hdler.ServeHTTP(this.Resp, this.Req)
},
},
},
})
date, _ := time.Parse("2006-01-02 15:04", time.Now().Format("2006-01-02")+" 14:00")
fmt.Println(date, date.Unix())
//fmt.Println("0123456"[1:7])
appIns := hotime.Init("config/config.json")
appIns.Run(hotime.Router{})
}
-28
View File
@@ -1,28 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8"/>
<title>Sample of websocket with golang</title>
<script src="http://apps.bdimg.com/libs/jquery/2.1.4/jquery.min.js"></script>
<script>
$(function() {
var ws = new WebSocket("ws://localhost:8080/app/index/websocket");
ws.onmessage = function(e) {
$('<li>').text(e.data).appendTo($ul);
};
var $ul = $('#msg-list');
$('#sendBtn').click(function(){
var data = $('#name').val();
ws.send(data);
});
});
</script>
</head>
<body>
<input id="name" type="text"/>
<input type="button" id="sendBtn" value="send"/>
<ul id="msg-list"></ul>
</body>
</html>
+13
View File
@@ -0,0 +1,13 @@
module code.hoteas.com/golang/hotime
go 1.16
require (
github.com/garyburd/redigo v1.6.3
github.com/go-sql-driver/mysql v1.6.0
github.com/mattn/go-sqlite3 v1.14.12
github.com/sirupsen/logrus v1.8.1
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.364
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/ocr v1.0.364
golang.org/x/net v0.0.0-20220225172249-27dd8689420f
)
+27
View File
@@ -0,0 +1,27 @@
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/garyburd/redigo v1.6.3 h1:HCeeRluvAgMusMomi1+6Y5dmFOdYV/JzoRrrbFlkGIc=
github.com/garyburd/redigo v1.6.3/go.mod h1:rTb6epsqigu3kYKBnaF028A7Tf/Aw5s0cqA47doKKqw=
github.com/go-sql-driver/mysql v1.6.0 h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfCHuOE=
github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
github.com/mattn/go-sqlite3 v1.14.12 h1:TJ1bhYJPV44phC+IMu1u2K/i5RriLTPe+yc68XDJ1Z0=
github.com/mattn/go-sqlite3 v1.14.12/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE=
github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.364 h1:X1Jws4XqrTH+p7FBQ7BpjW4qFXObKHWm0/XhW/GvqRs=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.364/go.mod h1:7sCQWVkxcsR38nffDW057DRGk8mUjK1Ing/EFOK8s8Y=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/ocr v1.0.364 h1:kbor60vo37v7Hu+i17gooox9Rw281fVHNna8zwtDG1w=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/ocr v1.0.364/go.mod h1:LeIUBOLhc+Y5YCEpZrULPD9lgoXXV4/EmIcoEvmHz9c=
golang.org/x/net v0.0.0-20220225172249-27dd8689420f h1:oA4XRj0qtSt8Yo1Zms0CUlsT3KG69V2UGQWPBxujDmc=
golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e h1:fLOSk5Q00efkSvAm+4xcoXD+RRmLmmulPn5I3Y9F2EM=
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
+117
View File
@@ -0,0 +1,117 @@
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)
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") {
if file == "common/error.go" {
file, line = getCaller(skip + i + 1)
}
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
}
+6 -6
View File
@@ -44,17 +44,17 @@ func Run() {
appIns.Run(hotime.Router{
"app": hotime.Proj{
"index": hotime.Ctr{
"test": func(this *hotime.Context) {
fmt.Println(this.Db.GetTag())
//x := this.Db.Action(func(db hotime.HoTimeDB) bool {
"test": func(that *hotime.Context) {
fmt.Println(that.Db.GetTag())
//x := that.Db.Action(func(db hotime.HoTimeDB) bool {
//
// db.Insert("user", hotime.Map{"unickname": "dasdas"})
//
// return true
//})
this.Display(0, 1)
that.Display(0, 1)
},
"websocket": func(this *hotime.Context) {
"websocket": func(that *hotime.Context) {
hdler := websocket.Handler(func(ws *websocket.Conn) {
for true {
msg := make([]byte, 5120)
@@ -73,7 +73,7 @@ func Run() {
fmt.Printf("Send: %s\n", msg[:m])
}
})
hdler.ServeHTTP(this.Resp, this.Req)
hdler.ServeHTTP(that.Resp, that.Req)
},
},
},
-155
View File
@@ -1,155 +0,0 @@
package hotime
import (
"encoding/json"
"errors"
"reflect"
)
//hotime的常用map
type Map map[string]interface{}
//获取string
func (this Map) GetString(key string, err ...*Error) string {
if len(err) != 0 {
err[0].SetError(nil)
}
return ObjToStr((this)[key])
}
func (this *Map) Pointer() *Map {
return this
}
//增加接口
func (this Map) Put(key string, value interface{}) {
//if this==nil{
// this=Map{}
//}
this[key] = value
}
//删除接口
func (this Map) Delete(key string) {
delete(this, key)
}
//获取Int
func (this Map) GetInt(key string, err ...*Error) int {
v := ObjToInt((this)[key], err...)
return v
}
//获取Int
func (this Map) GetInt64(key string, err ...*Error) int64 {
v := ObjToInt64((this)[key], err...)
return v
}
//获取向上取整Int64
func (this Map) GetCeilInt64(key string, err ...*Error) int64 {
v := ObjToCeilInt64((this)[key], err...)
return v
}
//获取向上取整Int
func (this Map) GetCeilInt(key string, err ...*Error) int {
v := ObjToCeilInt((this)[key], err...)
return v
}
//获取向上取整float64
func (this Map) GetCeilFloat64(key string, err ...*Error) float64 {
v := ObjToCeilFloat64((this)[key], err...)
return v
}
//获取Float64
func (this Map) GetFloat64(key string, err ...*Error) float64 {
v := ObjToFloat64((this)[key], err...)
return v
}
func (this Map) GetSlice(key string, err ...*Error) Slice {
//var v Slice
v := ObjToSlice((this)[key], err...)
return v
}
func (this Map) GetMap(key string, err ...*Error) Map {
//var data Slice
v := ObjToMap((this)[key], err...)
return v
}
func (this Map) Get(key string, err ...*Error) interface{} {
if v, ok := (this)[key]; ok {
return v
}
e := errors.New("没有存储key及对应的数据")
if len(err) != 0 {
err[0].SetError(e)
}
return nil
}
//请传递指针过来
func (this Map) ToStruct(stct interface{}) {
data := reflect.ValueOf(stct).Elem()
for k, v := range this {
ks := StrFirstToUpper(k)
dkey := data.FieldByName(ks)
if !dkey.IsValid() {
continue
}
switch dkey.Type().String() {
case "int":
dkey.SetInt(this.GetInt64(k))
case "int64":
dkey.Set(reflect.ValueOf(this.GetInt64(k)))
case "float64":
dkey.Set(reflect.ValueOf(this.GetFloat64(k)))
case "string":
dkey.Set(reflect.ValueOf(this.GetString(k)))
case "interface{}":
dkey.Set(reflect.ValueOf(v))
}
}
}
func (this Map) ToJsonString() string {
return ObjToStr(this)
}
func (this Map) JsonToMap(jsonStr string, err ...*Error) {
e := json.Unmarshal([]byte(jsonStr), &this)
if e != nil && len(err) != 0 {
err[0].SetError(e)
}
}
-93
View File
@@ -1,93 +0,0 @@
package hotime
//对象封装方便取用
type Obj struct {
Data interface{}
contextBase
}
func (this *Obj) Put(data interface{}) {
this.Data = data
}
func (this *Obj) ToInt(err ...Error) int {
if len(err) != 0 {
this.Error = err[0]
}
return ObjToInt(this.Data, &this.Error)
}
func (this *Obj) ToInt64(err ...Error) int64 {
if len(err) != 0 {
this.Error = err[0]
}
return ObjToInt64(this.Data, &this.Error)
}
func (this *Obj) ToFloat64(err ...Error) float64 {
if len(err) != 0 {
this.Error = err[0]
}
return ObjToFloat64(this.Data, &this.Error)
}
//获取向上取整float64
func (this *Obj) ToCeilFloat64(err ...*Error) float64 {
if len(err) != 0 {
this.Error = *err[0]
}
v := ObjToCeilFloat64(this.Data, err...)
return v
}
func (this *Obj) ToStr() string {
return ObjToStr(this.Data)
}
func (this *Obj) ToMap(err ...Error) Map {
if len(err) != 0 {
this.Error = err[0]
}
return ObjToMap(this.Data, &this.Error)
}
func (this *Obj) ToSlice(err ...Error) Slice {
if len(err) != 0 {
this.Error = err[0]
}
return ObjToSlice(this.Data, &this.Error)
}
func (this *Obj) ToMapArray(err ...Error) []Map {
if len(err) != 0 {
this.Error = err[0]
}
return ObjToMapArray(this.Data, &this.Error)
}
func (this *Obj) ToObj() interface{} {
return this.Data
}
//获取向上取整Int64
func (this *Obj) ToCeilInt64(err ...*Error) int64 {
if len(err) != 0 {
this.Error = *err[0]
}
v := ObjToCeilInt64(this.Data, err...)
return v
}
//获取向上取整Int
func (this *Obj) ToCeilInt(err ...*Error) int {
if len(err) != 0 {
this.Error = *err[0]
}
v := ObjToCeilInt(this.Data, err...)
return v
}
+26 -41
View File
@@ -1,71 +1,56 @@
package hotime
import (
. "code.hoteas.com/golang/hotime/cache"
. "code.hoteas.com/golang/hotime/common"
)
//session对象
type SessionIns struct {
ShortCache CacheIns
LongCache CacheIns
SessionId string
*HoTimeCache
SessionId string
Map
contextBase
ContextBase
}
func (this *SessionIns) set() {
if this.ShortCache != nil {
this.ShortCache.Cache(HEAD_SESSION_ADD+this.SessionId, this.Map)
}
if this.LongCache != nil {
this.LongCache.Cache(HEAD_SESSION_ADD+this.SessionId, this.Map)
}
func (that *SessionIns) set() {
that.HoTimeCache.Session(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 {
return
}
that.Map = that.HoTimeCache.Session(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)
}
return
}
}
this.Map = Map{}
this.ShortCache.Cache(HEAD_SESSION_ADD+this.SessionId, this.Map)
that.Map = Map{}
that.HoTimeCache.Session(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(cache *HoTimeCache) {
that.HoTimeCache = cache
}
-87
View File
@@ -1,87 +0,0 @@
package hotime
import (
"errors"
)
type Slice []interface{}
//获取string
func (this Slice) GetString(key int, err ...*Error) string {
if len(err) != 0 {
err[0].SetError(nil)
}
return ObjToStr((this)[key])
}
//获取Int
func (this Slice) GetInt(key int, err ...*Error) int {
v := ObjToInt((this)[key], err...)
return v
}
//获取Int
func (this Slice) GetInt64(key int, err ...*Error) int64 {
v := ObjToInt64((this)[key], err...)
return v
}
//获取向上取整Int64
func (this Slice) GetCeilInt64(key int, err ...*Error) int64 {
v := ObjToCeilInt64((this)[key], err...)
return v
}
//获取向上取整Int
func (this Slice) GetCeilInt(key int, err ...*Error) int {
v := ObjToCeilInt((this)[key], err...)
return v
}
//获取向上取整float64
func (this Slice) GetCeilFloat64(key int, err ...*Error) float64 {
v := ObjToCeilFloat64((this)[key], err...)
return v
}
//获取Float64
func (this Slice) GetFloat64(key int, err ...*Error) float64 {
v := ObjToFloat64((this)[key], err...)
return v
}
func (this Slice) GetSlice(key int, err ...*Error) Slice {
v := ObjToSlice((this)[key], err...)
return v
}
func (this Slice) GetMap(key int, err ...*Error) Map {
//var v Map
v := ObjToMap((this)[key], err...)
return v
}
func (this Slice) Get(key int, err ...*Error) interface{} {
if key < len(this) {
return this[key]
}
e := errors.New("没有存储key及对应的数据")
if len(err) != 0 {
err[0].SetError(e)
}
return nil
}
func (this Slice) Put(key int, value interface{}) {
this[key] = value
}
func (this Slice) ToJsonString() string {
return ObjToStr(this)
}
-18
View File
@@ -1,18 +0,0 @@
package db
import (
"code.hoteas.com/golang/hotime"
"code.hoteas.com/golang/hotime/tools/mysql"
"code.hoteas.com/golang/hotime/tools/sqlite"
"strings"
)
func SetDB(appIns *hotime.Application) {
if appIns.Config.GetString("dbType") == "sqlite" || strings.Index(appIns.Config.GetString("dbName"), ".db") == len(appIns.Config.GetString("dbName"))-3 {
appIns.Config["dbType"] = "sqlite"
sqlite.SetDB(appIns)
} else {
appIns.Config["dbType"] = "mysql"
mysql.SetDB(appIns)
}
}
-19
View File
@@ -1,19 +0,0 @@
package mysql
import (
"code.hoteas.com/golang/hotime"
"database/sql"
_ "github.com/go-sql-driver/mysql"
)
func SetDB(appIns *hotime.Application) {
appIns.SetConnectDB(func(err ...*hotime.Error) *sql.DB {
query := appIns.Config.GetString("dbUser") + ":" + appIns.Config.GetString("dbPwd") +
"@tcp(" + appIns.Config.GetString("dbHost") + ":" + appIns.Config.GetString("dbPort") + ")/" + appIns.Config.GetString("dbName") + "?charset=utf8"
DB, e := sql.Open("mysql", query)
if e != nil && len(err) != 0 {
err[0].SetError(e)
}
return DB
})
}
-17
View File
@@ -1,17 +0,0 @@
package sqlite
import (
"code.hoteas.com/golang/hotime"
"database/sql"
_ "github.com/mattn/go-sqlite3"
)
func SetDB(appIns *hotime.Application) {
appIns.SetConnectDB(func(err ...*hotime.Error) *sql.DB {
db, e := sql.Open("sqlite3", appIns.Config.GetString("dbName"))
if e != nil && len(err) != 0 {
err[0].SetError(e)
}
return db
})
}
+2 -15
View File
@@ -1,21 +1,8 @@
package hotime
//控制器
// Ctr 控制器
type Ctr map[string]Method
type Proj map[string]Ctr
type Router map[string]Proj
type MethodRouter map[string]Method //直接字符串关联函数
type Method func(this *Context)
type CacheIns interface {
//set(key string, value interface{}, time int64)
//get(key string) interface{}
//delete(key string)
Cache(key string, data ...interface{}) *Obj
}
//单条缓存数据
type cacheData struct {
time int64
data interface{}
}
type Method func(that *Context)
+96 -43
View File
@@ -1,21 +1,38 @@
package hotime
import (
. "code.hoteas.com/golang/hotime/common"
)
var IsRun = false //当前状态
var App = map[string]*Application{} //整个项目
//var Db = HoTimeDB{} //数据库实例
var Config = Map{
"debug": 1, //debug 0关闭1开启
"logLevel": LOG_FMT,
"dbHost": "127.0.0.1",
"dbName": "test",
"dbUser": "root",
"dbPwd": "root",
"dbPort": "3306",
"dbCached": 0, //0不开启缓存
"cacheShortTime": 60 * 60 * 2,
"cacheLongTime": 60 * 60 * 24 * 30,
"mode": 3, //模式 0生产模式,1,测试模式,2,开发模式,3,内嵌代码模式
"codeConfig": Map{
"admin": "config/app.json",
},
"codeConfig1": Map{
"admin": Map{ //默认无,必须,接口类别名称
"package": "admin", //默认admin,非必须,有则生成代码到此目录,无则采用缺省模式不生成代码只生成接口
"config": "config/app.json", //默认config/app.json,必须,接口描述配置文件
"rule": "config/rule.json", //默认config/rule.json,非必须,有则按改规则生成接口,无则按系统内嵌方式生成
},
},
"db": Map{
"sqlite": Map{
"path": "config/data.db",
},
},
"cache": Map{
"memory": Map{
"timeout": 60 * 60 * 2,
"db": true,
"session": true,
},
},
"error": Map{
"1": "内部系统异常",
"2": "访问权限异常",
@@ -23,32 +40,69 @@ var Config = Map{
"4": "数据处理异常",
"5": "数据结果异常",
},
"tpt": "tpt",
"defFile": []string{"index.html", "index.htm"},
"modeRouterStrict": false, //路由严格模式/a/b/c
"port": "80",
"sessionName": "HOTIME",
"tlsPort": "0",
"tlsKey": "",
"tlsCert": "",
"tpt": "tpt",
"defFile": []string{"index.html", "index.htm"},
"port": "80",
"sessionName": "HOTIME",
}
var ConfigNote = Map{
"logLevel": "日志等级0关闭,1打印",
"logFile": "如果需要存储日志文件时使用,保存格式为:a/b/c/20060102150405.txt,将生成:a/b/c/年月日时分秒.txt,按需设置",
"debug": "是否开启debug模式,0关闭,其他开启,debug模式下日志展示更全", //debug 0关闭1开启
"dbHost": "数据库ip地址默认127.0.0.1",
"dbName": "数据库名称,sqlite为文件路径比如a/x.db",
"dbUser": "数据库用户名",
"dbPwd": "数据库密码",
"dbPort": "数据库端口",
"dbType": "如果需要使用自动数据库配置,请设置此项,手动配置数据库不需要,目前支持mysql,sqlite",
"dbCached": "是否开启数据库缓存0为关闭,其他开启", //0不开启缓存
"redisHost": "如果需要使用redis服务时配置,默认服务ip127.0.0.1",
"redisPort": "如果需要使用redis服务时配置,默认服务端口:6379",
"redisPwd": "如果需要使用redis服务时配置,默认服务密码:123456",
"cacheShortTime": "两级缓存,短缓存存储时间60 * 60 * 2,一般为内存缓存",
"cacheLongTime": "两级缓存,长缓存存储时间60 * 60 * 24 * 30,一般为数据库或者redis缓存",
"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,按需设置",
"mode": "默认0,非必须,0生产模式,1,测试模式,2开发模式,3内嵌代码模式,在开发模式下会显示更多的数据用于开发测试,并能够辅助研发,自动生成配置文件、代码等功能,web无缓存,数据库不启用缓存", //debug 0关闭1开启
"codeConfig": Map{
"注释": "配置即启用,非必须,默认无",
//"package":"默认admin,必须,mode模式为2时会自动生成包文件夹和代码文件",
//"path":""
"packageName": "默认无,必须,包名称以及应用名,生成代码的配置文件地址,比如config/app.json,数据库有更新时自动更新配置文件以及对应的生成文件",
},
"db": Map{
"注释": "配置即启用,非必须,默认使用sqlite数据库",
"mysql": Map{
"注释": "除prefix及主从数据库slave项,其他全部必须",
"host": "默认127.0.0.1,必须,数据库ip地址",
"name": "默认test,必须,数据库名称",
"user": "默认root,必须,数据库用户名",
"password": "默认root,必须,数据库密码",
"port": "默认3306,必须,数据库端口",
"prefix": "默认空,非必须,数据表前缀",
"slave": Map{
"注释": "从数据库配置,mysql里配置slave项即启用主从读写,减少数据库压力",
"host": "默认127.0.0.1,必须,数据库ip地址",
"name": "默认test,必须,数据库名称",
"user": "默认root,必须,数据库用户名",
"password": "默认root,必须,数据库密码",
"port": "默认3306,必须,数据库端口",
},
},
"sqlite": Map{
"path": "默认config/data.db,必须,数据库位置",
},
},
"cache": Map{
"注释": "可配置memorydbredis,默认启用memory,默认优先级为memory>redis>db,memory与数据库缓存设置项一致,缓存数据填充会自动反方向反哺,加入memory缓存过期将自动从redis更新,但memory永远不会更新redis,如果是集群建议不要开启memory,配置即启用",
"memory": Map{
"timeout": "默认60 * 60 * 2,非必须,过期时间,超时自动删除",
"db": "默认true,非必须,缓存数据库,启用后能减少数据库的读写压力",
"session": "默认true,非必须,缓存web session,同时缓存session保持的用户缓存",
},
"db": Map{
"timeout": "默认60 * 60 * 24 * 30,非必须,过期时间,超时自动删除",
"db": "默认false,非必须,缓存数据库,启用后能减少数据库的读写压力",
"session": "默认true,非必须,缓存web session,同时缓存session保持的用户缓存",
},
"redis": Map{
"host": "默认服务ip127.0.0.1,必须,如果需要使用redis服务时配置,",
"port": "默认服务端口:6379,必须,如果需要使用redis服务时配置,",
"password": "默认密码空,必须,如果需要使用redis服务时配置,默认密码空",
"timeout": "默认60 * 60 * 24 * 15,非必须,过期时间,超时自动删除",
"db": "默认true,非必须,缓存数据库,启用后能减少数据库的读写压力",
"session": "默认true,非必须,缓存web session,同时缓存session保持的用户缓存",
},
},
"error": Map{
"1": "内部系统异常,在环境配置,文件访问权限等基础运行环境条件不足造成严重错误时使用",
"2": "访问权限异常,没有登录或者登录异常等时候使用",
@@ -57,14 +111,13 @@ var ConfigNote = Map{
"5": "数据结果异常,一般用于无法给出response要求的格式要求下使用,比如response需要的是string格式但你只能提供int数据时",
"注释": "web服务内置错误提示,自定义异常建议10开始",
},
"tpt": "静态文件目录,默认为程序目录下tpt目录",
"defFile": "默认访问文件,默认访问index.html或者index.htm文件",
"crossDomain": "如果需要跨域设置,空字符串为不开启,*为开启所有网站允许跨域,http://www.baidu.com为指定域允许跨域", //是否开启跨域
"modeRouterStrict": "路由严格模式false,为大小写忽略必须匹配,true必须大小写匹配", //路由严格模式/a/b/c
"connectLogShow": "如果需要web访问链接、访问ip、访问时间打印,0为关闭其他数字开启此功能",
"sessionName": "设置session的cookie名默认HOTIME",
"port": "web服务开启Http端口,0为不启用http服务,默认80",
"tlsPort": "web服务https端口,0为不启用https服务",
"tlsKey": "https密钥",
"tlsCert": "https证书",
"tpt": "默认tpt,必须,web静态文件目录,默认为程序目录下tpt目录",
"defFile": "默认访问index.html或者index.htm文件,必须,默认访问文件类型",
"crossDomain": "默认空 非必须,空字符串为不开启,如果需要跨域设置,auto为智能开启所有网站允许跨域,http://www.baidu.com为指定域允许跨域", //是否开启跨域
"modeRouterStrict": "默认false,必须,路由严格模式false,为大小写忽略必须匹配,true必须大小写匹配", //路由严格模式/a/b/c
"sessionName": "默认HOTIME,必须,设置session的cookie名",
"port": "默认80,必须,web服务开启Http端口,0为不启用http服务,默认80",
"tlsPort": "默认空,非必须,web服务https端口,0为不启用https服务",
"tlsKey": "默认空,非必须,https密钥",
"tlsCert": "默认空,非必须,https证书",
}