min-go 支持go mod
初始化
require (
github.com/duanchi/min v1.6.14
)
项目中所有的配置可以通过定义一个struct
类型的变量, 并由config/application.yaml填充配置项内容, 该变量可以引用github.com/duanchi/min/types
下的Config
结构体进行组合。
package config
import "github.com/duanchi/min/types"
var Config = struct {
types.Config `yaml:",inline"`
Jwt struct {
SignatureKey string `yaml:"jwt_signature_key" default:"${JWT_SIGNATURE_KEY}"`
ExpiresIn int64 `yaml:"jwt_expires_in" default:"${JWT_EXPIRES_IN:7200}"`
} // 自定义配置
Beans struct {} // IOC容器初始化
}{}
在配置结构体中, 需要定义yaml
的标签指明扩展配置文件的对应位置, 也可以通过default
标签来指定配置的默认值
配置文件、默认值中可以使用
${}
的方式指定对应的环境变量, 也可以使用${ENV_KEY:default_value}
的方式指定当未找到该环境变量时赋予的默认值
配置字段中的实际赋值可根据字段基本类型自动进行类型转换, 支持的基本类型有
int/int64
float64
string
bool
配置yaml文件默认配置在
config/application.yaml
, 可以通过Bootstrap方法更改配置文件位置
env: "${ENV:development}"
#服务配置
application:
server_port: "${SERVER_PORT:9801}"
jwt_signature_key: "${JWT_SIGNATURE_KEY}"
jwt_expire_in: "${JWT_EXPIRE_IN:7200}"
db:
enabled: true
dsn: "${DB_DSN:postgres://postgres:shvEVodOcqqTCWJ0@61.55.158.34:58932/cloud?sslmode=disable&prefix=dp_}"
func main() {
heron.SetConfigFile("./config/dashboard.yaml")
heron.Bootstrap(&Config)
return
}
在项目初始化后,可以直接引入该变量读取初始化后的配置。也可以通过配置获取方法config.Get
获取配置
import xxx/config
Dsn := Config.Db.Dsn
// host=172.31.16.1 port=3308 user=tb_cloud password=123456 dbname=thingsboard sslmode=disable
推荐使用配置变量直接获取配置, 既可以准确定位配置元素, 又可以省去类型强制转换。
package config
func Get(key string) interface{} {}
其中key
是以.
分割的配置定义层级,获取配置后,需要进行强制类型转换。
import "heurd.com/config"
func getConfig () {
fmt.Println(config.Get("Db.Enabled").(bool))
fmt.Println(config.Get("Db.Dsn").(string))
}
// true
// host=172.31.16.1 port=3308 user=tb_cloud password=123456 dbname=thingsboard sslmode=disable
读取配置后, 需手动进行类型转换
在Bean(可参考IOC容器章节)中, 可以使用value
标签以类似配置文件中获取环境变量的方式获取配置值
struct Sample struct {
Expires string `value:"${Jwt.Expires}"`
}
为保证值可以正确注入, 需要将被注入的属性或字段设置为
可导出
的
建议采用三层分离的文件结构,即控制器
、业务逻辑服务
、实体关系映射
三层,分别对应controller
、sevice
、mapper
三个包。
root
- main.go
- config.go
- controller
- xxx.go
控制器文件
- xxx.go
- service
- xxx.go
业务逻辑文件
- xxx.go
- mapper
- xxx.go
数据库mapper文件
- xxx.go
借鉴于Java Spring
的IOC容器
概念,可以通过定义Bean
进行项目中实体实例的管理,在初始化后可在任何位置调用。
使用类似配置文件定义时使用的自定义结构体进行Bean
的定义,字段名为Bean
的name
, 字段类型为Bean
实例的类型, 可通过标签配置扩展Bean
配置信息
package config
var Beans = struct {
DataDevices controller.DevicesController `route:"data/devices"`
[bean name] [bean struct] `[bean tags]`
}{}
若需实现上述Bean的IOC/DI,需继承min.abstract.Bean
类型,并实现 Init
方法
min.abstract.Bean
已经实现了空的Init
方法,若初始化时不需任何额外操作,可不进行方法重写。
预定义的抽象基础类
min.abstract.RestController
和min.abstract.Service
已经继承了min.abstract.Bean
类型,可以直接使用并在Bean
定义文件中引用
type Devices struct {
abstract.Service
Config string `value:"${Db.Dsn,172.31.128.5}"`
Data *data.Devices `autowired:"true"`
}
func (service *Devices) Init() {
fmt.Println("Inited!") // 初始化时将打印 'Inited!'
}
Bean定义完成后, 通过加入到Config
文件的 Beans
结构中, 可以实现Bean的自动初始化
var Config = struct {
types.Config `yaml:",inline"`
// ...
Beans struct {
GatewayMiddleware middleware.GatewayMiddleware `middleware:"true"`
AuthorizationToken authorization.TokenController `rest:"authorization/token"`
AccountService authorization2.AccountService
TokenService authorization2.TokenService
}
}{}
可通过实现Bean
类型的Init
方法实现Bean
初始化后的操作
用于标识当前Bean
的name
,可在min.GetBean方法参数中使用
用于当前Bean
类型或类的初始化,初始化后,将生成一个当前类型的实例
用于描述当前Bean
的特定属性,可在初始化后进行扩展操作
bean tag
的可取值如下
用于设置当前属性或字段的值,可以使用${[config-stack]}
来进行配置文件的读取,读取的值将自动转换为当前字段的类型,支持的类型有int
、int64
、float64
、string
、bool
、struct
用于在Bean
初始化后,将含有当前字段类型的Bean
自动装载至当前的字段中,装载时将装载对象的引用类型。
自动装载时,字段类型需设置为将要装载类型
Bean
的指针类型,并将autowired
值设置为true
详见Http服务
章节中的路由配置
用于定义基于HTTP服务的中间件处理方法, 如定义一个登录或者令牌授权认证、请求日志记录等, 通过继承abstract.middlewire
定义一个中间件处理方法
type AuthorizationMiddleware struct {
abstract.Middleware
TokenService *service.TokenService `autowired:"true"`
}
func (this *AuthorizationMiddleware) AfterRoute (ctx *gin.Context) {
// 具体处理方法
ctx.Next()
return
}
提供可自定义的tag
标签,并通过扩展方法执行Bean
初始化时的扩展操作。
可通过继承types.BeanParser
来实现一个自定义的Bean处理扩展, 类似Java Spring中的注解定义
type NativeApiBeanParser struct {
types.BeanParser
}
func (parser NativeApiBeanParser) Parse (tag reflect.StructTag, bean reflect.Value, definition reflect.Type, beanName string) {
resource := tag.Get("native_api")
if resource != "" {
NativeApiBeans[resource] = bean
}
}
在Config结构体中加入配置
var Config = struct {
config.Config `yaml:",inline"`
// ...
Beans struct {
NativeApiRoutesController native_api.RoutesController `native_api:"routes"`
NativeApiServicesController native_api.ServicesController `native_api:"services"`
}
}{
Config: config.Config{
Config: types.Config{
BeanParsers: []_interface.BeanParserInterface{
&native_api.NativeApiBeanParser{},
},
},
},
}
项目初始化后可通过min.GetBean
方法获取Bean
import min
func Test() {
min.GetBean("Fetch").(Fetch).Get()
}
只有在
Config
中定义的Bean才可以使用Bean的各种特性, 如自动初始化、全局对象、自动注入等特性
项目初始化后,可以使用min.HttpServer
进行Http服务器的相关操作
服务器端口配置可以使用配置ServerPort
指定
Http服务器使用Gin
请求路由目前可根据资源进行路由配置,是通过扩展Bean
定义实现的,因此只需在Bean
变量中添加名为route
或rest
或restful
的标签, 并设置其属性值为绑定路径或资源路径即可,Bean
字段类型为相应的处理结构体。
另外还可以追加使用method
方法限定该路由处理方法可以处理的HTTP请求类型, 多个类型以,
分割
rest
路由配置完成后,可自动配置[resource]
,[resource]/:id
和[resource]/
的路由解析
创建Restful控制器只需新建一个结构体,组合abstract.RestController
,并实现当前控制器关心的处理方法即可。
若不组合
abstract.RestController
,则需实现所有min.interface.RestControllerInterface
方法
可实现的方法有
func (controller RestController)
Fetch (
id string,
resource string,
parameters *gin.Params,
ctx *gin.Context
) (result interface{}, err types.Error) {}
func (controller RestController)
Create (
id string,
resource string,
parameters *gin.Params,
ctx *gin.Context
) (result interface{}, err types.Error) {}
func (controller RestController)
Update (
id string,
resource string,
parameters *gin.Params,
ctx *gin.Context
) (result interface{}, err types.Error) {}
func (controller RestController)
Remove (
id string,
resource string,
parameters *gin.Params,
ctx *gin.Context
) (result interface{}, err types.Error) {}
func (controller RestController)
Communicate (
connection *websocket.Conn,
id string, resource string,
parameters *gin.Params,
ctx *gin.Context
) (err types.Error) {}
方法返回值可以是任意可转换为
json
的数据格式
其余方法未完成
若设置配置 Db.Enabled=true
,则可开始数据库支持。在项目中可以使用min.Db
进行和数据库有关的操作。
数据库使用xorm
人为抛出异常时,建议使用min.types.Error
类型,并通过Message
和Code
字段定义异常
Code需使用HTTP协议支持的错误码。
main.go 必须包含以下结构
min.Bootstrap(&Config, &Beans)
其中, Config
为实际定义配置的变量,Beans
为实际定义Bean
的变量。项目初始化完成后,可通过引用调用配置和Bean
的实际值。
项目开发环境可以使用 fresh 等hot-reload热加载方案。