记录版本
安装
# 安装spring核心包
go get -u github.com/go-spring/spring-core@v1.1.0-rc2
# 安装web starter
# gin
go get -u github.com/go-spring/starter-gin@v1.1.0-rc2
# echo
go get -u github.com/go-spring/starter-echo@v1.1.0-rc2
最小化Web应用
package main
import (
"github.com/go-spring/spring-core/gs"
"github.com/go-spring/spring-core/web"
// 这里必须引入web starter, 也可改为 "github.com/go-spring/starter-echo"
_ "github.com/go-spring/starter-gin"
"log"
)
func init() {
// 创建一个GET方法的访问端点/hello-go-spring, 同Java SpringBoot 的 @GetMapping 注解
// 访问http://127.0.0.1:8080/hello-go-spring 将看到返回{"code": 200, "msg": "SUCCESS", "data": "Hello Go-Spring!"}
gs.GetMapping("/hello-go-spring", func(ctx web.Context) {
// 回调形式返回结果
ctx.JSON(web.SUCCESS.Data("Hello Go-Spring!"))
})
}
func main() {
// 启动应用程序, 同Java SpringBoot 的 SpringApplication.run(...)
log.Fatal(gs.Run())
}
Go-Spring常用语法
1.对象注入spring bean
package main
import (
"fmt"
"github.com/go-spring/spring-core/gs"
"github.com/go-spring/spring-core/gs/cond"
"log"
)
type testA struct {
path string `value:"${GOPATH}"`
}
func (t *testA) String() string {
return "testA: " + t.path
}
type testB struct {
a *testA
}
func (t *testB) String() string {
return "testB: " + t.a.String()
}
func newTestB(a *testA) *testB {
return &testB{a: a}
}
func init() {
// 创建bean, 并将bean设置为primary
// Primary() 方法 => 将bean设置为该类型的默认bean
gs.Object(new(testA)).Primary().Init(func(a *testA) {
fmt.Println("1." + a.String())
})
// gs.Provide方法将对象注入spring bean中, Provide方法与Object方法相似, Provide方法还支持方法创建bean的形式, 参见示例6
// Name(string) 方法 => 更改bean的名称
gs.Provide(new(testA)).Name("testA2").Init(func(a *testA) {
a.path = "newPath"
fmt.Println("2." + a.String())
})
// 创建bean并绑定销毁方法
// Destroy(func(interface{})) => 添加bean销毁时的方法
gs.Object(new(testA)).Name("testA3").Destroy(func(a *testA) {
// 程序停止时将打印该内容
fmt.Println("destroy 3." + a.String())
}).Init(func(a *testA) {
fmt.Println("3." + a.String())
})
// 指定创建bean的条件, 与Java Spring @Condition系列注解相同
// On(cond.Condition) => 添加创建bean的条件. 多个条件使用 cond.OnBean("bean1").OnBean("bean2").OnProperty(..) 方式创建
gs.Object(new(testA)).Name("testA4").On(cond.OnBean("testA3")).Init(func(a *testA) {
fmt.Println("4." + a.String())
})
// 设置bean的排序顺序, 优先级从小到大, 同Java Spring @Order注解
// Order(int) => 设置bean的排序顺序
gs.Object(new(testA)).Name("testA5").Order(1).Init(func(a *testA) {
fmt.Println("5." + a.String())
})
// 将方法返回的对象注入至spring bean中, 参数从spring容器中获取
// 当有多个依赖类型且无Primary时, 需指定bean名称,例如: gs.Privide(newTestB, "testA2")...
gs.Provide(newTestB).Init(func(b *testB) {
fmt.Println("6." + b.String())
})
}
func main() {
log.Fatal(gs.Run())
}
2.创建属性监听器
package main
import (
"fmt"
"github.com/go-spring/spring-core/gs"
"log"
)
type user struct {
// 需与配置文件字段名相同
Name string `value:"${name}"`
Age int `value:"${age}"`
}
func init() {
// 创建属性监听器, 当属性装载后会执行自定义方法, 方法签名 func(interface{})
gs.OnProperty("GOPATH", func(s string) {
fmt.Println("4." + s)
})
// 设置环境变量
gs.Setenv("user.name", "dragons")
gs.Setenv("user.age", "24")
// 设置属性(与环境变量的区别在于env是进程全局生效, 而Property仅在一个web容器中生效)
gs.Property("xxx", "value")
// 创建属性监控器, 属性绑定struct, struct的value需与属性名一致
gs.OnProperty("user", func(u user) {
fmt.Printf("5.%v\n", u)
})
/*
创建属性监控器, 数组结构
config/application.yml
users:
- name: dragons
age: 24
- name: xxj
age: 16
*/
gs.OnProperty("users", func(u []user) {
fmt.Printf("6.%v\n", u)
})
}
func main() {
log.Fatal(gs.Run())
}
Web应用常用语法
1.创建Web端点(Path)
1.1 Mapping方式
package main
import (
"github.com/go-spring/spring-core/gs"
"github.com/go-spring/spring-core/web"
// 引入web引擎starter
_ "github.com/go-spring/starter-gin"
"log"
)
func init() {
// gs.*Mapping(path, func(web.Context))
// GET 请求
gs.GetMapping("/get", func(ctx web.Context) {
// 获取参数-------------------------------------
// 获取请求头参数
ctx.GetHeader("user-agent")
// 获取query参数
ctx.QueryParam("")
// 获取raw参数
_, _ = ctx.GetRawData()
// 返回结果-------------------------------------
// 返回json结构对象或map
/**
{"code": 200, "msg": "SUCCESS"}
*/
ctx.JSON(web.SUCCESS)
ctx.JSON(map[string]interface{}{"code": 200, "msg": "SUCCESS"})
ctx.JSON(struct {
Code int `json:"code"`
Msg string `json:"msg"`
}{200, "SUCCESS"})
// 返回原始串
/* message */
ctx.String("message")
// 返回文件内容
/**
name: dragons
age: 24
*/
ctx.File("./config/application.yml")
})
// POST 请求
gs.PostMapping("/post", func(ctx web.Context) {
// ctx方法与GET请求一致
// 获取表单数据 from-data
ctx.FormValue("name")
})
// PUT 请求
gs.PutMapping("/put", func(ctx web.Context) {
})
// DELETE 请求
gs.DeleteMapping("/delete", func(ctx web.Context) {
})
}
func main() {
log.Fatal(gs.Run())
}
1.2 Binding方式
package main
import (
"context"
"github.com/go-spring/spring-core/gs"
// 引入web引擎starter
_ "github.com/go-spring/starter-gin"
"log"
)
// 示例Bind请求类型
type req struct {
/**
常用tags:
json => 输入、输出 json 结构时的参数名称
xml => 输入、输出 xml 结构时的参数名称
bson => 输入、输出 bson 结构时的参数名称
yaml => 输入、输出 yaml 结构时的参数名称
form => query、form-data 参数名称
...
*/
Name string `json:"name" form:"name" xml:"name" yaml:"name" bson:"name"`
}
// 示例Bind返回类型
type resp struct {
Code int `json:"code"`
Msg string `json:"msg"`
Data string `json:"data"`
}
func init() {
// gs.*Binding(path, func(context.Context, interface{}) interface{})
// GET 请求
// 其中Binding的fn参数必须是func且只能有两个参数一个返回值, 第一个参数是context.Context而不是web.Context, 第二个参数返回值必须为指针类型
gs.GetBinding("/get", func(ctx context.Context, r *req) *resp {
return &resp{200, "请求成功", r.Name}
})
// POST 请求
gs.PostBinding("/post", func(ctx context.Context, r *req) *resp {
return &resp{200, "请求成功", r.Name}
})
// PUT 请求
gs.PutBinding("/put", func(ctx context.Context, r *req) *resp {
return &resp{200, "请求成功", r.Name}
})
// DELETE请求
gs.DeleteBinding("/delete", func(ctx context.Context, r *req) *resp {
return &resp{200, "请求成功", r.Name}
})
}
func main() {
log.Fatal(gs.Run())
}
1.3 Handle方式
package main
import (
"github.com/go-spring/spring-base/util"
"github.com/go-spring/spring-core/gs"
"github.com/go-spring/spring-core/web"
// 引入web引擎starter
_ "github.com/go-spring/starter-gin"
"log"
)
// 测试handler, 实现web.Handler接口
type testHandler struct {
}
func (t *testHandler) Invoke(ctx web.Context) {
ctx.JSON(web.SUCCESS)
}
func (t *testHandler) FileLine() (file string, line int, fnName string) {
return util.FileLine(t.Invoke)
}
func init() {
// GET 请求
// 传入一个实现web.Handler接口的对象
// 与 gs.*Mapping区别在于web.Handler接口多了一个FileLine方法, 用于获取用户函数的文件名、行号以及函数名称
gs.HandleGet("/get", &testHandler{})
// POST 请求
gs.HandlePost("/post", &testHandler{})
// PUT 请求
gs.HandlePut("/put", &testHandler{})
// DELETE 请求
gs.HandleDelete("/delete", &testHandler{})
}
func main() {
log.Fatal(gs.Run())
}
配置应用
多环境配置(以yml文件为例)
1.application-dev.yml
user:
name: dragons
age: 24
2.application-test.yml
user:
name: xxl
age: 14
3.main.go
package main
import (
"github.com/go-spring/spring-core/gs"
"github.com/go-spring/spring-core/web"
_ "github.com/go-spring/starter-gin"
"log"
)
type user struct {
Name string `value:"${name}"`
Age int `value:"${age}"`
}
func init() {
// 设置配置目录
gs.Setenv("GS_SPRING_CONFIG_LOCATIONS", "config/")
// 设置dev环境配置值, 两种方式均可
gs.Setenv("GS_SPRING_PROFILES_ACTIVE", "dev")
// gs.Setenv("spring.profiles.active", "dev")
gs.OnProperty("user", func(u user) {
gs.GetMapping("/user", func(ctx web.Context) {
ctx.JSON(web.SUCCESS.Data(u))
})
})
}
func main() {
log.Fatal(gs.Run())
}
配置方式
配置方式一:Tag value + autowire注入
1.config/application.yml
# 默认情况下自动加载项目路径下的 conifg/application.yml 或 config/application.properties 文件配置
# 这里以application.yml为例, config/application.yml 文件
name: dragons
age: 24
2.main.go
// code
package main
import (
"github.com/go-spring/spring-core/gs"
"github.com/go-spring/spring-core/web"
_ "github.com/go-spring/starter-gin"
"log"
)
// 定义model
type user struct {
// 加载环境变量中的 name 属性, ":=" 语法用于设置默认值, 同Java Spring @Value("${name:}")
Name string `json:"name" value:"${name:=}"`
// 加载环境变量中的 age 属性
Age int `json:"age" value:"${age:=0}"`
}
// 定义控制器
type userController struct {
// 自动注入*user实例, 也可将?改为具体beanName, 例如当前测试 ? 可改为 user
u *user `autowire:"?"`
}
// 定义控制器端点方法, 控制器端点方法签名为 func(..) ...(ctx web.Context)
func (c *userController) echoUser(ctx web.Context) {
// 这里直接返回model对象, 指针类型与值类型最终都将转为值类型
ctx.JSON(c.u)
}
func init() {
// 创建user类型的bean实例, 自动装载user配置
gs.Object(new(user))
// 创建userController控制器bean实例, 并在控制器实例创建后添加初始化方法
// 访问http://127.0.0.1:8080/echo-user 将看到返回{"name": "dragons", "age": 24}
gs.Object(new(userController)).Init(func(c *userController) {
// 初始化web端点/echo-user, 将该端点绑定至userController控制器的echoUser方法上
gs.GetMapping("/echo-user", c.echoUser)
})
}
func main() {
log.Fatal(gs.Run())
}
配置方式二: Tag value 属性直接注入
1.config/application.yml
users:
- name: dragons
age: 24
- name: xxy
age: 14
2.main.go
package main
import (
"github.com/go-spring/spring-core/gs"
"github.com/go-spring/spring-core/web"
_ "github.com/go-spring/starter-gin"
"log"
)
// 定义model
type user struct {
// 设置tag value对应的配置名, users下的属性名为name, 因此这里填写${name}即可注入
Name string `json:"name" form:"name" yaml:"name" value:"${name}"`
// 设置tag value对应的配置名
Age int `json:"age" form:"age" yaml:"age" value:"${age}"`
}
// 定义controller
type userController struct {
// 使用application.yml中的users属性直接注入
users []user `value:"${users}"`
}
// 控制器端点方法
func (c *userController) echoUsers(ctx web.Context) {
ctx.JSON(c.users)
}
func init() {
// 创建userController控制器bean实例, 并在控制器实例创建后添加初始化方法
gs.Object(new(userController)).Init(func(controller * userController) {
// 初始化web端点/echo-users, 将该端点绑定至userController控制器的echoUser方法上
gs.GetMapping("/echo-users", controller.echoUsers)
})
}
func main() {
log.Fatal(gs.Run())
}