Skip to content

duanchi/min

Repository files navigation

Min-Go

项目初始化

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

推荐使用配置变量直接获取配置, 既可以准确定位配置元素, 又可以省去类型强制转换。

通过Get方法获取配置

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中注入配置值

在Bean(可参考IOC容器章节)中, 可以使用value标签以类似配置文件中获取环境变量的方式获取配置值

struct Sample struct {
  Expires string `value:"${Jwt.Expires}"`
}

为保证值可以正确注入, 需要将被注入的属性或字段设置为可导出

项目文件结构

建议采用三层分离的文件结构,即控制器业务逻辑服务实体关系映射三层,分别对应controllersevicemapper三个包。

root

  • main.go
  • config.go
  • controller
    • xxx.go 控制器文件
  • service
    • xxx.go 业务逻辑文件
  • mapper
    • xxx.go 数据库mapper文件

IOC容器

借鉴于Java SpringIOC容器概念,可以通过定义Bean进行项目中实体实例的管理,在初始化后可在任何位置调用。

Bean定义

使用类似配置文件定义时使用的自定义结构体进行Bean的定义,字段名为Beanname, 字段类型为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.RestControllermin.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初始化

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初始化切面

可通过实现Bean类型的Init方法实现Bean初始化后的操作

[bean name]

用于标识当前Beanname,可在min.GetBean方法参数中使用

[bean struct]

用于当前Bean类型或类的初始化,初始化后,将生成一个当前类型的实例

[bean tags]

用于描述当前Bean的特定属性,可在初始化后进行扩展操作

bean tag的可取值如下

value

用于设置当前属性或字段的值,可以使用${[config-stack]}来进行配置文件的读取,读取的值将自动转换为当前字段的类型,支持的类型有intint64float64stringboolstruct

autowired

用于在Bean初始化后,将含有当前字段类型的Bean自动装载至当前的字段中,装载时将装载对象的引用类型。

自动装载时,字段类型需设置为将要装载类型Bean的指针类型,并将autowired值设置为true

routerestmethod

详见Http服务章节中的路由配置

middleware

用于定义基于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的各种特性, 如自动初始化、全局对象、自动注入等特性

Http服务

项目初始化后,可以使用min.HttpServer进行Http服务器的相关操作

服务器端口配置可以使用配置ServerPort 指定

Http服务器使用Gin

路由配置

请求路由目前可根据资源进行路由配置,是通过扩展Bean定义实现的,因此只需在Bean变量中添加名为routerestrestful的标签, 并设置其属性值为绑定路径或资源路径即可,Bean字段类型为相应的处理结构体。

另外还可以追加使用method方法限定该路由处理方法可以处理的HTTP请求类型, 多个类型以,分割

rest路由配置完成后,可自动配置[resource], [resource]/:id[resource]/的路由解析

Restful控制器

创建Restful控制器只需新建一个结构体,组合abstract.RestController,并实现当前控制器关心的处理方法即可。

若不组合abstract.RestController,则需实现所有min.interface.RestControllerInterface方法

可实现的方法有

Fetch(获取) - GET

func (controller RestController)
Fetch (
    id string,
    resource string,
    parameters *gin.Params,
    ctx *gin.Context
) (result interface{}, err types.Error) {}

Create(创建) - POST

func (controller RestController)
Create (
    id string,
    resource string,
    parameters *gin.Params,
    ctx *gin.Context
) (result interface{}, err types.Error) {}

Update(更新) - PUT

func (controller RestController)
Update (
    id string,
    resource string,
    parameters *gin.Params,
    ctx *gin.Context
) (result interface{}, err types.Error) {}

Remove(删除) - DELETE

func (controller RestController)
Remove (
    id string,
    resource string,
    parameters *gin.Params,
    ctx *gin.Context
) (result interface{}, err types.Error) {}

Communicate(通信-基于websocket) - WEBSOCKET

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类型,并通过MessageCode字段定义异常

Code需使用HTTP协议支持的错误码。

运行

main.go 必须包含以下结构

min.Bootstrap(&Config, &Beans)

其中, Config为实际定义配置的变量,Beans为实际定义Bean的变量。项目初始化完成后,可通过引用调用配置和Bean的实际值。

项目开发环境可以使用 fresh 等hot-reload热加载方案。

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Packages

No packages published

Languages