完成gmvc基本开发及测试

This commit is contained in:
John 2017-12-20 12:05:36 +08:00
parent 03109055c1
commit aacb6abb9a
13 changed files with 279 additions and 170 deletions

View File

@ -20,7 +20,7 @@ import "gitee.com/johng/gf/g/xxx/xxx"
│   │   └── gset 并发安全的集合
│   │  
│   ├── database 【数据库操作】
│   │   └── gdb MySQL、PostgreSQL的操作封装
│   │   └── gdb 通用关系型数据库操作封装(目前仅支持MySQL、PostgreSQL)
│   │  
│   ├── encoding 【数据编码】
│   │   ├── gbase64 BASE64
@ -34,10 +34,16 @@ import "gitee.com/johng/gf/g/xxx/xxx"
│   │   ├── gsha1 SHA1
│   │   └── gurl URL
│   │  
│   ├── frame 【开发框架】
│   │   ├── gconfig 通用配置管理
│   │   ├── ginstance 单例对象管理
│   │   └── gmvc MVC模式封装基类
│   │  
│   ├── net 【网络通信】
│   │   ├── ghttp HTTP客户端及服务端
│   │   ├── gip IP操作
│   │   ├── gipv4 IP操作
│   │   ├── gscanner 端口扫描
│   │   ├── gsession SESSION会话管理
│   │   ├── gsmtp SMTP邮件管理
│   │   ├── gtcp TCP服务端
│   │   └── gudp UDP服务端
@ -45,12 +51,14 @@ import "gitee.com/johng/gf/g/xxx/xxx"
│   ├── os 【系统管理】
│   │   ├── gcache 本地缓存管理
│   │   ├── gconsole 命令行控制
│   │   ├── genv 环境变量管理
│   │   ├── gfile 文件管理
│   │   ├── gfilepool 文件指针池
│   │   ├── gfilespace 文件碎片管理
│   │   ├── glog 日志管理
│   │ ├── gmmap MMAP文件内存映射
│   │   └── gtime 时间管理
│   │   ├── gtime 时间管理
│   │   └── gview 视图管理(通用的模板管理对象独立于MVC模块)
│   │  
│   └── util 【常用工具】
│   ├── gpage 分页
@ -65,3 +73,70 @@ import "gitee.com/johng/gf/g/xxx/xxx"
## 配置
1. 默认读取文件运行目录的config.json文件
1. 支持多配置文件管理,默认配置文件目录为当前运行目录;
1. config.json配置文件说明
```json
{
"viewpath" : "视图文件存放路径",
"database" : {
"数据库分组名称" : [
{
"host" : "地址",
"port" : "端口",
"user" : "账号",
"pass" : "密码",
"name" : "数据库名称",
"type" : "数据库类型(mysql|pgsql)",
"role" : "数据库角色(master|slave)",
"charset" : "字符编码",
"priority" : "数据库优先级(负载均衡处理)"
}
]
}
}
```
1. config.json示例文件
```json
{
"viewpath" : "/home/john/Workspace/Go/gitee.com/johng/gf/geg/frame/mvc/view",
"database" : {
"default" : [
{
"host" : "127.0.0.1",
"port" : "3306",
"user" : "root",
"pass" : "123456",
"name" : "test",
"type" : "mysql",
"role" : "master",
"charset" : "utf8",
"priority" : "100"
},
{
"host" : "127.0.0.1",
"port" : "3306",
"user" : "root",
"pass" : "123456",
"name" : "test",
"type" : "mysql",
"role" : "slave",
"charset" : "utf8",
"priority" : "100"
}
],
"ucenter" : [
{
"host" : "127.0.0.1",
"port" : "3306",
"user" : "root",
"pass" : "123456",
"name" : "ucenter",
"type" : "mysql",
"role" : "master",
"charset" : "utf8",
"priority" : "100"
}
]
}
}
```

View File

@ -27,8 +27,8 @@ type Link interface {
Exec(q string, args ...interface{}) (sql.Result, error)
Prepare(q string) (*sql.Stmt, error)
GetAll(q string, args ...interface{}) (*List, error)
GetOne(q string, args ...interface{}) (*Map, error)
GetAll(q string, args ...interface{}) (List, error)
GetOne(q string, args ...interface{}) (Map, error)
GetValue(q string, args ...interface{}) (interface{}, error)
PingMaster() error
@ -49,15 +49,15 @@ type Link interface {
Commit() error
Rollback() error
insert(table string, data *Map, option uint8) (sql.Result, error)
Insert(table string, data *Map) (sql.Result, error)
Replace(table string, data *Map) (sql.Result, error)
Save(table string, data *Map) (sql.Result, error)
insert(table string, data Map, option uint8) (sql.Result, error)
Insert(table string, data Map) (sql.Result, error)
Replace(table string, data Map) (sql.Result, error)
Save(table string, data Map) (sql.Result, error)
batchInsert(table string, list *List, batch int, option uint8) error
BatchInsert(table string, list *List, batch int) error
BatchReplace(table string, list *List, batch int) error
BatchSave(table string, list *List, batch int) error
batchInsert(table string, list List, batch int, option uint8) error
BatchInsert(table string, list List, batch int) error
BatchReplace(table string, list List, batch int) error
BatchSave(table string, list List, batch int) error
Update(table string, data interface{}, condition interface{}, args ...interface{}) (sql.Result, error)
Delete(table string, condition interface{}, args ...interface{}) (sql.Result, error)
@ -136,7 +136,6 @@ func NewByGroup(groupName string) (Link, error) {
if len(masterList) < 1 {
return nil, errors.New("at least one master node configuration's need to make sense")
}
fmt.Println(masterList)
masterNode := getConfigNodeByPriority(&masterList)
var slaveNode *ConfigNode
if len(slaveList) > 0 {

View File

@ -67,7 +67,7 @@ func (l *dbLink) formatError(err error, q *string, args ...interface{}) error {
// 数据库查询,获取查询结果集,以列表结构返回
func (l *dbLink) GetAll(q string, args ...interface{}) (*List, error) {
func (l *dbLink) GetAll(q string, args ...interface{}) (List, error) {
// 执行sql
rows, err := l.Query(q, args ...)
if err != nil || rows == nil {
@ -88,7 +88,7 @@ func (l *dbLink) GetAll(q string, args ...interface{}) (*List, error) {
for rows.Next() {
err = rows.Scan(scanArgs...)
if err != nil {
return &list, err
return list, err
}
row := make(Map)
for i, col := range values {
@ -96,16 +96,16 @@ func (l *dbLink) GetAll(q string, args ...interface{}) (*List, error) {
}
list = append(list, row)
}
return &list, nil
return list, nil
}
// 数据库查询,获取查询结果集,以关联数组结构返回
func (l *dbLink) GetOne(q string, args ...interface{}) (*Map, error) {
func (l *dbLink) GetOne(q string, args ...interface{}) (Map, error) {
list, err := l.GetAll(q, args ...)
if err != nil {
return nil, err
}
return &(*list)[0], nil
return list[0], nil
}
// 数据库查询,获取查询字段值
@ -114,7 +114,7 @@ func (l *dbLink) GetValue(q string, args ...interface{}) (interface{}, error) {
if err != nil {
return "", err
}
for _, v := range *one {
for _, v := range one {
return v, nil
}
return "", nil
@ -194,11 +194,11 @@ func (l *dbLink) getInsertOperationByOption(option uint8) string {
// 1: replace: 如果数据存在(主键或者唯一索引),那么删除后重新写入一条
// 2: save: 如果数据存在(主键或者唯一索引),那么更新,否则写入一条新数据
// 3: ignore: 如果数据存在(主键或者唯一索引),那么什么也不做
func (l *dbLink) insert(table string, data *Map, option uint8) (sql.Result, error) {
func (l *dbLink) insert(table string, data Map, option uint8) (sql.Result, error) {
var keys []string
var values []string
var params []interface{}
for k, v := range *data {
for k, v := range data {
keys = append(keys, l.charl + k + l.charr)
values = append(values, "?")
params = append(params, v)
@ -207,7 +207,7 @@ func (l *dbLink) insert(table string, data *Map, option uint8) (sql.Result, erro
updatestr := ""
if option == OPTION_SAVE {
var updates []string
for k, _ := range *data {
for k, _ := range data {
updates = append(updates, fmt.Sprintf("%s%s%s=VALUES(%s)", l.charl, k, l.charr, k))
}
updatestr = fmt.Sprintf(" ON DUPLICATE KEY UPDATE %s", strings.Join(updates, ","))
@ -219,33 +219,33 @@ func (l *dbLink) insert(table string, data *Map, option uint8) (sql.Result, erro
}
// CURD操作:单条数据写入, 仅仅执行写入操作,如果存在冲突的主键或者唯一索引,那么报错返回
func (l *dbLink) Insert(table string, data *Map) (sql.Result, error) {
func (l *dbLink) Insert(table string, data Map) (sql.Result, error) {
return l.link.insert(table, data, OPTION_INSERT)
}
// CURD操作:单条数据写入, 如果数据存在(主键或者唯一索引),那么删除后重新写入一条
func (l *dbLink) Replace(table string, data *Map) (sql.Result, error) {
func (l *dbLink) Replace(table string, data Map) (sql.Result, error) {
return l.link.insert(table, data, OPTION_REPLACE)
}
// CURD操作:单条数据写入, 如果数据存在(主键或者唯一索引),那么更新,否则写入一条新数据
func (l *dbLink) Save(table string, data *Map) (sql.Result, error) {
func (l *dbLink) Save(table string, data Map) (sql.Result, error) {
return l.link.insert(table, data, OPTION_SAVE)
}
// 批量写入数据
func (l *dbLink) batchInsert(table string, list *List, batch int, option uint8) error {
func (l *dbLink) batchInsert(table string, list List, batch int, option uint8) error {
var keys []string
var values []string
var bvalues []string
var params []interface{}
var size int = len(*list)
var size int = len(list)
// 判断长度
if size < 1 {
return errors.New("empty data list")
}
// 首先获取字段名称及记录长度
for k, _ := range (*list)[0] {
for k, _ := range list[0] {
keys = append(keys, k)
values = append(values, "?")
}
@ -263,7 +263,7 @@ func (l *dbLink) batchInsert(table string, list *List, batch int, option uint8)
// 构造批量写入数据格式(注意map的遍历是无序的)
for i := 0; i < size; i++ {
for _, k := range keys {
params = append(params, (*list)[i][k])
params = append(params, list[i][k])
}
bvalues = append(bvalues, "(" + strings.Join(values, ",") + ")")
if len(bvalues) == batch {
@ -285,17 +285,17 @@ func (l *dbLink) batchInsert(table string, list *List, batch int, option uint8)
}
// CURD操作:批量数据指定批次量写入
func (l *dbLink) BatchInsert(table string, list *List, batch int) error {
func (l *dbLink) BatchInsert(table string, list List, batch int) error {
return l.link.batchInsert(table, list, batch, OPTION_INSERT)
}
// CURD操作:批量数据指定批次量写入, 如果数据存在(主键或者唯一索引),那么删除后重新写入一条
func (l *dbLink) BatchReplace(table string, list *List, batch int) error {
func (l *dbLink) BatchReplace(table string, list List, batch int) error {
return l.link.batchInsert(table, list, batch, OPTION_REPLACE)
}
// CURD操作:批量数据指定批次量写入, 如果数据存在(主键或者唯一索引),那么更新,否则写入一条新数据
func (l *dbLink) BatchSave(table string, list *List, batch int) error {
func (l *dbLink) BatchSave(table string, list List, batch int) error {
return l.link.batchInsert(table, list, batch, OPTION_SAVE)
}
@ -307,16 +307,16 @@ func (l *dbLink) Update(table string, data interface{}, condition interface{}, a
switch data.(type) {
case string:
updates = data.(string)
case *Map:
case Map:
var keys []string
for k, v := range *data.(*Map) {
for k, v := range data.(Map) {
keys = append(keys, fmt.Sprintf("%s%s%s=?", l.charl, k, l.charr))
params = append(params, v)
}
updates = strings.Join(keys, ",")
default:
return nil, errors.New("invalid data type for 'data' field, string or *Map expected")
return nil, errors.New("invalid data type for 'data' field, string or Map expected")
}
for _, v := range args {
if r, ok := v.(string); ok {

View File

@ -3,9 +3,6 @@ package gdb
import (
"sync"
"regexp"
"strings"
"strconv"
)
const (
@ -99,42 +96,42 @@ func AddConfigNode (group string, node ConfigNode) {
// 添加一台数据库服务器配置,通过解析规范的字符串配置实现
// 配置格式:账号@地址:端口,密码,数据库名称,数据库类型[,集群角色(master|slave),字符编码,负载均衡优先级,自定义链接]
func AddConfigNodeByString (group string, nodestr string) {
reg, _ := regexp.Compile(`(.+)@(.+):([^,]+),([^,]+),([^,]+),([^,]+)`)
match := reg.FindStringSubmatch(nodestr)
if match != nil {
node := ConfigNode{
User : strings.TrimSpace(match[1]),
Host : strings.TrimSpace(match[2]),
Port : strings.TrimSpace(match[3]),
Pass : strings.TrimSpace(match[4]),
Name : strings.TrimSpace(match[5]),
Type : strings.TrimSpace(match[6]),
}
if len(match[0]) + 1 < len(nodestr) {
extra := strings.Split(nodestr[len(match[0]) + 1:], ",")
if len(extra) > 0 {
node.Role = strings.TrimSpace(extra[0])
}
if len(extra) > 1 {
node.Charset = strings.TrimSpace(extra[1])
}
if len(extra) > 2 {
node.Priority, _ = strconv.Atoi(strings.TrimSpace(extra[2]))
}
if len(extra) > 3 {
index := len(extra[0]) + len(extra[1]) + len(extra[2]) + 3
node.Linkinfo = strings.TrimSpace(nodestr[len(match[0]) + 1 + index:])
}
}
AddConfigNode(group, node)
}
}
//func AddConfigNodeByString (group string, nodestr string) {
// reg, _ := regexp.Compile(`(.+)@(.+):([^,]+),([^,]+),([^,]+),([^,]+)`)
// match := reg.FindStringSubmatch(nodestr)
// if match != nil {
// node := ConfigNode{
// User : strings.TrimSpace(match[1]),
// Host : strings.TrimSpace(match[2]),
// Port : strings.TrimSpace(match[3]),
// Pass : strings.TrimSpace(match[4]),
// Name : strings.TrimSpace(match[5]),
// Type : strings.TrimSpace(match[6]),
// }
// if len(match[0]) + 1 < len(nodestr) {
// extra := strings.Split(nodestr[len(match[0]) + 1:], ",")
// if len(extra) > 0 {
// node.Role = strings.TrimSpace(extra[0])
// }
// if len(extra) > 1 {
// node.Charset = strings.TrimSpace(extra[1])
// }
// if len(extra) > 2 {
// node.Priority, _ = strconv.Atoi(strings.TrimSpace(extra[2]))
// }
// if len(extra) > 3 {
// index := len(extra[0]) + len(extra[1]) + len(extra[2]) + 3
// node.Linkinfo = strings.TrimSpace(nodestr[len(match[0]) + 1 + index:])
// }
// }
// AddConfigNode(group, node)
// }
//}
// 添加默认链接的一台数据库服务器配置,通过解析规范的字符串配置实现
func AddDefaultConfigNodeByString (nodestr string) {
AddConfigNodeByString(gDEFAULT_CONFIG_GROUP_NAME, nodestr)
}
//func AddDefaultConfigNodeByString (nodestr string) {
// AddConfigNodeByString(gDEFAULT_CONFIG_GROUP_NAME, nodestr)
//}
// 添加默认链接的一台数据库服务器配置
func AddDefaultConfigNode (node ConfigNode) {

View File

@ -19,7 +19,7 @@ type gLinkOp struct {
start int
limit int
data interface{}
dataList *List
dataList List
batch int
}
@ -88,7 +88,7 @@ func (op *gLinkOp) Data(data interface{}) (*gLinkOp) {
}
// 链式操作,操作数据记录项列表
func (op *gLinkOp) List(list *List) (*gLinkOp) {
func (op *gLinkOp) List(list List) (*gLinkOp) {
op.dataList = list
return op
}
@ -98,7 +98,7 @@ func (op *gLinkOp) Insert() (sql.Result, error) {
if op.data == nil {
return nil, errors.New("inserting into table with empty data")
}
if d, ok := op.data.(*Map); ok {
if d, ok := op.data.(Map); ok {
return op.link.Insert(op.tables, d)
}
return nil, errors.New("inserting into table with invalid data type")
@ -109,7 +109,7 @@ func (op *gLinkOp) Replace() (sql.Result, error) {
if op.data == nil {
return nil, errors.New("replacing into table with empty data")
}
if d, ok := op.data.(*Map); ok {
if d, ok := op.data.(Map); ok {
return op.link.Insert(op.tables, d)
}
return nil, errors.New("replacing into table with invalid data type")
@ -120,7 +120,7 @@ func (op *gLinkOp) Save() (sql.Result, error) {
if op.data == nil {
return nil, errors.New("saving into table with empty data")
}
if d, ok := op.data.(*Map); ok {
if d, ok := op.data.(Map); ok {
return op.link.Insert(op.tables, d)
}
return nil, errors.New("saving into table with invalid data type")
@ -134,7 +134,7 @@ func (op *gLinkOp) Batch(batch int) *gLinkOp {
// 链式操作, CURD - BatchInsert
func (op *gLinkOp) BatchInsert() error {
if op.dataList == nil || len(*op.dataList) < 1 {
if op.dataList == nil || len(op.dataList) < 1 {
return errors.New("batch inserting into table with empty data list")
}
batch := 10
@ -146,7 +146,7 @@ func (op *gLinkOp) BatchInsert() error {
// 链式操作, CURD - BatchReplace
func (op *gLinkOp) BatchReplace() error {
if op.dataList == nil || len(*op.dataList) < 1 {
if op.dataList == nil || len(op.dataList) < 1 {
return errors.New("batch replacing into table with empty data list")
}
batch := 10
@ -158,7 +158,7 @@ func (op *gLinkOp) BatchReplace() error {
// 链式操作, CURD - BatchSave
func (op *gLinkOp) BatchSave() error {
if op.dataList == nil || len(*op.dataList) < 1 {
if op.dataList == nil || len(op.dataList) < 1 {
return errors.New("batch saving into table with empty data list")
}
batch := 10
@ -185,7 +185,7 @@ func (op *gLinkOp) Delete() (sql.Result, error) {
}
// 链式操作select
func (op *gLinkOp) Select() (*List, error) {
func (op *gLinkOp) Select() (List, error) {
if op.fields == "" {
op.fields = "*"
}
@ -206,17 +206,17 @@ func (op *gLinkOp) Select() (*List, error) {
}
// 链式操作,查询所有记录
func (op *gLinkOp) All() (*List, error) {
func (op *gLinkOp) All() (List, error) {
return op.Select()
}
// 链式操作,查询单条记录
func (op *gLinkOp) One() (*Map, error) {
func (op *gLinkOp) One() (Map, error) {
list, err := op.All()
if err != nil {
return nil, err
}
return &(*list)[0], nil
return list[0], nil
}
// 链式操作,查询字段值
@ -225,7 +225,7 @@ func (op *gLinkOp) Value() (interface{}, error) {
if err != nil {
return "", err
}
for _, v := range *one {
for _, v := range one {
return v, nil
}
return "", nil

View File

@ -1,58 +0,0 @@
// 基类
package gbase
import (
"gitee.com/johng/gf/g/os/gfile"
"gitee.com/johng/gf/g/os/gconsole"
"gitee.com/johng/gf/g/database/gdb"
"gitee.com/johng/gf/g/frame/gconfig"
"gitee.com/johng/gf/g/frame/ginstance"
)
// 框架基类所有的基于gf框架的类对象都继承于此以便使用框架的一些封装的核心组件
type Base struct {
Db gdb.Link // 数据库操作对象
Config *gconfig.Config // 配置管理对象
}
// 基类初始化,如若需要自定义初始化内置核心对象组件,可在继承子类中覆盖此方法
func (b *Base) Init() {
// 配置文件目录查找依次为启动参数cfgpath、当前程序运行目录
if b.Config == nil {
path := gconsole.Option.Get("cfgpath")
if path == "" {
path = gfile.SelfDir()
}
ckey := "gf_config_with_path_" + path
result := ginstance.Get(ckey)
if result != nil {
b.Config = result.(*gconfig.Config)
} else {
b.Config = gconfig.New(path)
ginstance.Set(ckey, b.Config)
}
}
// 数据库操作对象初始化
// 全局只有一个数据库单例对象,可以配置不同分组的配置进行使用
if b.Db == nil {
ckey := "gf_database"
result := ginstance.Get(ckey)
if result != nil {
b.Db = result.(gdb.Link)
} else {
if m := b.Config.GetMap("database"); m != nil {
for group, v := range m {
if list, ok := v.([]interface{}); ok {
for _, nodei := range list {
gdb.AddConfigNodeByString(group, nodei.(string))
}
}
}
if link, err := gdb.Instance(); err != nil {
b.Db = link
ginstance.Set(ckey, b.Db)
}
}
}
}
}

View File

@ -1,7 +1,21 @@
// 单例对象管理工具
// 框架内置了一些核心对象并且可以通过Set和Get方法实现IoC以及对内置核心对象的自定义替换
package ginstance
import "gitee.com/johng/gf/g/container/gmap"
import (
"strconv"
"gitee.com/johng/gf/g/os/gfile"
"gitee.com/johng/gf/g/os/gconsole"
"gitee.com/johng/gf/g/database/gdb"
"gitee.com/johng/gf/g/frame/gconfig"
"gitee.com/johng/gf/g/container/gmap"
"gitee.com/johng/gf/g/os/glog"
)
const (
FRAME_CORE_COMPONENT_NAME_CONFIG = "gf.component.config"
FRAME_CORE_COMPONENT_NAME_DATABASE = "gf.component.database"
)
// 单例对象存储器
var instances = gmap.NewStringInterfaceMap()
@ -15,3 +29,92 @@ func Get(k string) interface{} {
func Set(k string, v interface{}) {
instances.Set(k, v)
}
// 核心对象Config
// 配置文件目录查找依次为启动参数cfgpath、当前程序运行目录
func Config() *gconfig.Config {
result := Get(FRAME_CORE_COMPONENT_NAME_CONFIG)
if result != nil {
return result.(*gconfig.Config)
} else {
path := gconsole.Option.Get("cfgpath")
if path == "" {
path = gfile.SelfDir()
}
config := gconfig.New(path)
Set(FRAME_CORE_COMPONENT_NAME_CONFIG, config)
return config
}
return nil
}
// 核心对象Database
func Database(names...string) gdb.Link {
result := Get(FRAME_CORE_COMPONENT_NAME_DATABASE)
if result != nil {
return result.(gdb.Link)
} else {
config := Config()
if config == nil {
return nil
}
if m := config.GetMap("database"); m != nil {
for group, v := range m {
if list, ok := v.([]interface{}); ok {
for _, nodev := range list {
node := gdb.ConfigNode{}
nodem := nodev.(map[string]interface{})
if value, ok := nodem["host"]; ok {
node.Host = value.(string)
}
if value, ok := nodem["port"]; ok {
node.Port = value.(string)
}
if value, ok := nodem["user"]; ok {
node.User = value.(string)
}
if value, ok := nodem["pass"]; ok {
node.Pass = value.(string)
}
if value, ok := nodem["name"]; ok {
node.Name = value.(string)
}
if value, ok := nodem["type"]; ok {
node.Type = value.(string)
}
if value, ok := nodem["role"]; ok {
node.Role = value.(string)
}
if value, ok := nodem["charset"]; ok {
node.Charset = value.(string)
}
if value, ok := nodem["priority"]; ok {
node.Priority, _ = strconv.Atoi(value.(string))
}
gdb.AddConfigNode(group, node)
}
}
}
var db gdb.Link = nil
if len(names) == 0 {
if link, err := gdb.Instance(); err == nil {
db = link
} else {
glog.Error(err)
}
} else {
if link, err := gdb.InstanceByGroup(names[0]); err == nil {
db = link
} else {
glog.Error(err)
}
}
if db != nil {
Set(FRAME_CORE_COMPONENT_NAME_DATABASE, db)
return db
}
}
}
return nil
}

View File

@ -3,7 +3,6 @@ package gmvc
import (
"gitee.com/johng/gf/g/net/ghttp"
"gitee.com/johng/gf/g/frame/gbase"
"gitee.com/johng/gf/g/net/gsession"
)
@ -13,7 +12,6 @@ const (
// 控制器基类
type Controller struct {
gbase.Base
Server *ghttp.Server // Web Server对象
Request *ghttp.ClientRequest // 请求数据对象
Response *ghttp.ServerResponse // 返回数据对象
@ -24,7 +22,6 @@ type Controller struct {
// 控制器初始化接口方法
func (c *Controller) Init(s *ghttp.Server, r *ghttp.ClientRequest, w *ghttp.ServerResponse) {
c.Base.Init()
c.Server = s
c.Request = r
c.Response = w

View File

@ -1,8 +1,6 @@
// 模型基类
package gmvc
import "gitee.com/johng/gf/g/frame/gbase"
type Model struct {
gbase.Base
}

View File

@ -4,14 +4,13 @@ import (
"sync"
"html/template"
"gitee.com/johng/gf/g/os/gview"
"gitee.com/johng/gf/g/frame/gbase"
"gitee.com/johng/gf/g/os/gfile"
"gitee.com/johng/gf/g/os/gconsole"
"gitee.com/johng/gf/g/frame/ginstance"
)
// 视图对象(一个请求一个视图对象,用完即销毁)
type View struct {
gbase.Base
mu sync.RWMutex // 并发互斥锁
ctl *Controller // 所属控制器
view *gview.View // 底层视图对象
@ -25,9 +24,11 @@ func NewView(c *Controller) *View {
if path == "" {
path = gfile.SelfDir()
}
if r := c.Config.Get("viewpath"); r != nil {
if config := ginstance.Config(); config != nil {
if r := config.Get("viewpath"); r != nil {
path = r.(string)
}
}
return &View{
ctl : c,
view : gview.GetView(path),
@ -52,7 +53,11 @@ func (view *View) Assign(key string, value interface{}) {
}
// 解析指定模板
func (view *View) Display(file string) error {
func (view *View) Display(files...string) error {
file := "default"
if len(files) > 0 {
file = files[0]
}
// 查询模板
tpl, err := view.view.Template(file)
if err != nil {

View File

@ -6,7 +6,7 @@
"host" : "127.0.0.1",
"port" : "3306",
"user" : "root",
"pass" : "127456",
"pass" : "123456",
"name" : "test",
"type" : "mysql",
"role" : "master",
@ -17,7 +17,7 @@
"host" : "127.0.0.1",
"port" : "3306",
"user" : "root",
"pass" : "127456",
"pass" : "123456",
"name" : "test",
"type" : "mysql",
"role" : "master",

View File

@ -1,18 +1,11 @@
package main
import (
"fmt"
"os"
"gitee.com/johng/gf/g/frame/ginstance"
)
func Add(path string, name ... string) {
fmt.Println(name)
}
func main() {
for _, e := range os.Environ() {
fmt.Println(e)
}
db := ginstance.Database()
list, _ := db.Table("test").Select()
fmt.Println(list[0])
}

View File

@ -1,6 +1,6 @@
package gf
// 框架信息
const VERSION = "0.60"
const VERSION = "0.80"
const AUTHORS = "john<john@johng.cn>"