YoyoGo微服务框架入门系列-快速编写WEB API
前言
YoyoGo是一个使用Golang编写的一个简单、轻量、快速、基于依赖注入的微服务框架,目前依然在研发阶段,欢迎Star以及一起参与到框架的研发
GitHub地址:https://github.com/yoyofx/yoyogo
正在为YoyoGo写第一个博客应用,感谢Tassdar的加入,源代码:https://github.com/yoyofxteam/YoyoBlog.git 请先Clone Star,项目会持续更新,~
本文通过一套最为基本的增删改查,来实例应该如何在最短的时间内最轻松的使用YoyoGo创建出一个自己的Web应用
开发工具与环境
本文开发环境及依赖版本:
- OS: macOS Big Sur v11.0.1
- GoLang SDK: go1.15.5 windows/amd64
- IDE: GoLand 2020
- YoyoGo: v1.5.8
- MySQL: 5.7
- MySQL_Deiver: v1.5.0
现在开始我们的造物之旅 o(////▽////)q
安装框架
go为我们自带了包管理 go get ,会从github帮我们下载依赖,但是由于总所周知的复杂原因,我们需要为自己的本地配置一下代理加速:
go env -w GOPROXY=https://goproxy.cn,direct
创建项目
打开GoLand ->new Project -->go modules

打开命令行,输入:
go get github.com/yoyofx/yoyogo

成功的话会出现上图的结果,如果超时请检查自己是否成功的配置了加速,检查方式为:go env 查看GOPRIXY选项

Hello World跑起来
package main
import (
YoyoGo "github.com/yoyofx/yoyogo/WebFramework"
"github.com/yoyofx/yoyogo/WebFramework/Context"
"github.com/yoyofx/yoyogo/WebFramework/Router"
)
func main() {
YoyoGo.CreateDefaultBuilder(func(router Router.IRouterBuilder) {
router.GET("/info",func (ctx *Context.HttpContext) {
ctx.JSON(200, Context.H{"msg": "Hello World"})
})
}).Build().Run() //默认端口号 :8080
}
启动main函数,框架打印出进程ID和监听端口号,Host启动成功

我们使用PostMan访问一下我们在上面代码中创建的路由,Host返回Hello World,到这一步恭喜你完成了自己的第一个YoyoGo的Web应用的创建~( ̄▽ ̄~)(~ ̄▽ ̄)~

当然,这么简单的功能是不能满足我们的,接下里我们要完成一个单表的增删改查来更加深入的了解YoyoGo的使用:
为项目添加内容
编写配置文件
一个正常的Web框架是肯定需要一个配置文件来保存它的相关配置的,YoyoGo使用golang编写,我们基于云原生的基调采用了YAML文件格式座位我们的配置文件格式
首先我们在根目录下创建一个名为:config_dev.yml的文件,文件名可以随意编写,后缀标识当前环境是开发还是生产,我们在文件中输入以下配置,接下来文件中的各个配置我们都会在后面用到
yoyogo:
application:
name: Blogs #应用名
metadata: "develop" #当前env
server:
type: "fasthttp" #Server类型
address: ":8081" #监听端口
path: ""
max_request_size: 2096157 #最大请求体限制
mvc:
template: "v1/{controller}/{action}" #路由规则
database:
url: tcp(localhost:3306)/yoyoBlog?charset=utf8&parseTime=True #数据库连接字符串
username: root
password: 1234abcd
添加数据库支持
连接数据库首先要获取数据库驱动
go get github.com/go-sql-driver/mysql
然后我们要从上面的配置文件中读取出配置文件的数据库配置节点,进行连接,在YoyoGo中,读取配置文件配置使用的接口是:Abstractions.IConfiguration,通过使用Iconfiguration的get方法读取去配置文件的内容,语法为“xxx.xxx.xxx , 我们通过构造函数初始化一下这个接口的实例,至于是如何实现构造函数初始化的这个是YoyoGo的依赖注入实现的,到后面我们会演示讲解。
import (
"database/sql"
"fmt"
_ "github.com/go-sql-driver/mysql"
"github.com/yoyofx/yoyogo/Abstractions"
"strings"
)
type BaseRepository struct {
config Abstractions.IConfiguration
}
func NewBaseRepository(config Abstractions.IConfiguration) *BaseRepository {
return &BaseRepository{config: config}
}
//初始化一个连接对象
func (baseRepository *BaseRepository) InitDBConn() *sql.DB {
url := fmt.Sprint(baseRepository.config.Get("yoyogo.database.url")) ”
username := fmt.Sprint(baseRepository.config.Get("yoyogo.database.username"))
password := fmt.Sprint(baseRepository.config.Get("yoyogo.database.password"))
var sb = strings.Builder{}
sb.WriteString(username)
sb.WriteString(":")
sb.WriteString(password)
sb.WriteString("@")
sb.WriteString(url)
connStr := sb.String()
fmt.Println(connStr)
conn, err := sql.Open("mysql", connStr)
if err != nil {
fmt.Println(err)
}
return conn
}
数据库操作类
这部分代码比较枯燥,唯一需要注意的依然是通过构造函数来进行BaseRepository的注入
import (
"fmt"
"yoyoFxBlog/domain"
"yoyoFxBlog/repository/repository_impl"
)
type BlogService struct {
baseRepository *repository_impl.BaseRepository
}
func NewBlogService(baseRepository *repository_impl.BaseRepository) *BlogService {
return &BlogService{baseRepository: baseRepository}
}
func (service *BlogService) AddLog(blog domain.Blog) domain.Blog {
conn := service.baseRepository.InitDBConn()
defer conn.Close()
stmt, err := conn.Prepare("INSERT INTO `blog` SET title=?,introduction=?,content=?")
fmt.Println(err)
res, err := stmt.Exec(blog.Title, blog.Introduction, blog.Content)
fmt.Println(err)
id, err := res.LastInsertId()
blog.Id = int(id)
return blog
}
func (service *BlogService) QueryBlogList(pageIndex int, pageSize int) domain.Page {
conn := service.baseRepository.InitDBConn()
defer conn.Close()
res := domain.Page{}
rows, err := conn.Query("SELECT COUNT(0) as count FROM `blog` ")
if err != nil {
}
for rows.Next() {
var count int
err = rows.Scan(&count)
res.TotalCount = count
}
start := (pageIndex - 1) * pageSize
sql := fmt.Sprintf("SELECT *FROM `blog` ORDER BY creation_date LIMIT %d,%d", start, pageSize)
rows, err = conn.Query(sql)
if err != nil {
fmt.Println(err)
}
blogList := make([]domain.Blog, 0)
for rows.Next() {
element := domain.Blog{}
err := rows.Scan(&element.Id, &element.Title, &element.Introduction, &element.Content, &element.ViewCount, &element.Author, &element.CreationDate)
if err != nil {
continue
}
blogList = append(blogList, element)
}
res.Data = blogList
return res
}
MVC创建控制器
首先我们创建一个控制器和几个接口,创建控制器要注意以下几点:
所有控制器必须和 Mvc.ApiController的指针进行组合
为了从请求中抓取参数,我们使用到了go的tag特性,获取参数的格式为
param:"arg"注意参数名要用双引号包裹,切用于进行参数绑定的结构体必须和 *Mvc.Requst组合接口中用于进行自动绑定的结构体必须是指针类型
通过控制器的名称前缀来实现HTTP请求类型的限制,例如 GETXXX即为只能使用Get请求
import (
"github.com/yoyofx/yoyogo/WebFramework/ActionResult"
"github.com/yoyofx/yoyogo/WebFramework/Mvc"
"yoyoFxBlog/domain"
"yoyoFxBlog/service"
)
type BlogController struct {
*Mvc.ApiController
blogService *service.BlogService
}
func NewBlogController(blogService *service.BlogService) *BlogController {
return &BlogController{blogService: blogService}
}
//声明用于从请求中自动绑定参数的结构体
type BlogRequest struct {
*Mvc.RequestBody //必须添加标识可以自动绑定
Id int `param:"id"`
Title string `param:"title"` //标题
Introduction string `param:"introduction"` //简介
Content string `param:"content"` //内容
ViewCount int `param:"viewCount"` //浏览次数
}
type PageRequest struct {
*Mvc.RequestBody
PageIndex int `param:"pageIndex"`
PageSize int `param:"pageSize"`
}
///这里注意参数必须是指针类型
func (controller *BlogController) AddBlog(blog *BlogRequest) ActionResult.IActionResult {
data := controller.blogService.AddLog(domain.Blog{Id: blog.Id, Title: blog.Title, Introduction: blog.Introduction, Content: blog.Content, ViewCount: blog.ViewCount})
return ActionResult.Json{Data: data}
}
//使用GET开头限制这个接口只能使用GET请求方式
func (controller *BlogController) GetBlogList(PageRequest *PageRequest) ActionResult.IActionResult {
data := controller.blogService.QueryBlogList(PageRequest.PageIndex, PageRequest.PageSize)
return ActionResult.Json{Data: data}
}
func (controller *BlogController) BlogList(PageRequest *PageRequest) ActionResult.IActionResult {
data := controller.blogService.QueryBlogList(PageRequest.PageIndex, PageRequest.PageSize)
return ActionResult.Json{Data: data}
}
这里有咱们上文中讲到的,自定义Host启动依赖注入 ,我们在这一步我们初始化了配置文件,以及控制器和通过调用我们前几步定义的构造函数来实现依赖的注入
重写Main
import (
"github.com/yoyofx/yoyogo/Abstractions"
"github.com/yoyofx/yoyogo/DependencyInjection"
YoyoGo "github.com/yoyofx/yoyogo/WebFramework"
"github.com/yoyofx/yoyogo/WebFramework/Mvc"
"yoyoFxBlog/controller"
"yoyoFxBlog/repository/repository_impl"
"yoyoFxBlog/service"
)
func main() {
webHost := CreateYoyoBlogBuilder().Build()
webHost.Run()
}
func CreateYoyoBlogBuilder() *Abstractions.HostBuilder {
//读取配置文件
configuration := Abstractions.NewConfigurationBuilder().AddYamlFile("config").Build()
return YoyoGo.NewWebHostBuilder().
UseConfiguration(configuration).
Configure(func(app *YoyoGo.WebApplicationBuilder) {
//配置我们上一步写好的Controller
app.UseMvc(func(builder *Mvc.ControllerBuilder) {
builder.AddController(controller.NewBlogController)
})
}).
//配置我们之前几步中定义好的构造函数来进行注入
ConfigureServices(func(serviceCollection *DependencyInjection.ServiceCollection) {
serviceCollection.AddTransient(repository_impl.NewBaseRepository)
serviceCollection.AddTransient(service.NewBlogService)
})
}
IOC与依赖注入
关于IOC生命周期,我们暂时提供了单例和瞬时两种方式使用方法为:
func ConfigBusiness(serviceCollection *DependencyInjection.ServiceCollection) {
//瞬时
//直接注入一个容器
serviceCollection.AddTransient(repository_impl.NewBaseRepository)
//为注入的容器起一个名字,类似于Spring中为 Bean命名
serviceCollection.AddTransientByName("NewBaseRepository",repository_impl.NewBaseRepository)
//用接口的形式进行注入,用于一个接口多种实现的情况
serviceCollection.AddTransientByImplements(repository_impl.NewBaseRepository, new(repository.BaseRepository))
//单例
serviceCollection.AddSingleton(repository_impl.NewBaseRepository)
serviceCollection.AddSingletonByName("NewBaseRepository",repository_impl.NewBaseRepository)
serviceCollection.AddTransientByImplements(repository_impl.NewBaseRepository, new(repository.BaseRepository))
}
最后
启动项目,访问我们刚才定义的接口,如果你能看到下图结果,恭喜你,你已经陈工掌握了YoyoGo的基本入门使用!(o゜▽゜)o☆[BINGO!]

YoyoGo微服务框架入门系列-快速编写WEB API的更多相关文章
- YoyoGo微服务框架入门系列-基本概念
前言 Github开源:github.com/yoyofx/yoyogo 还请多多Star 之前简单介绍了YoyoGo微服务框架的基本内容,接下来了解下框架中的基本概念. 从一个简单Web服务Demo ...
- Taurus.MVC 微服务框架 入门开发教程:项目集成:3、客户端:其它编程语言项目集成:Java集成应用中心。
系列目录: 本系列分为项目集成.项目部署.架构演进三个方向,后续会根据情况调整文章目录. 开源地址:https://github.com/cyq1162/Taurus.MVC 本系列第一篇:Tauru ...
- 转载 (三)surging 微服务框架使用系列之我的第一个服务(审计日志)
(三)surging 微服务框架使用系列之我的第一个服务(审计日志) 前言:前面准备了那么久的准备工作,现在终于可以开始构建我们自己的服务了.这篇博客就让我们一起构建自己的第一个服务---审计日志 ...
- Taurus.MVC 微服务框架 入门开发教程:项目部署:1、微服务应用程序常规部署实现多开,节点扩容。
系列目录: 本系列分为项目集成.项目部署.架构演进三个方向,后续会根据情况调整文章目录. 本系列第一篇:Taurus.MVC V3.0.3 微服务开源框架发布:让.NET 架构在大并发的演进过程更简单 ...
- Taurus.MVC 微服务框架 入门开发教程:项目部署:2、让Kestrel支持绑定多个域名转发,替代Ngnix使用。
系列目录: 本系列分为项目集成.项目部署.架构演进三个方向,后续会根据情况调整文章目录. 本系列第一篇:Taurus.MVC V3.0.3 微服务开源框架发布:让.NET 架构在大并发的演进过程更简单 ...
- Taurus.MVC 微服务框架 入门开发教程:项目部署:3、微服务应用程序版本升级:全站升级和局部模块升级。
系列目录: 本系列分为项目集成.项目部署.架构演进三个方向,后续会根据情况调整文章目录. 本系列第一篇:Taurus.MVC V3.0.3 微服务开源框架发布:让.NET 架构在大并发的演进过程更简单 ...
- Taurus.MVC 微服务框架 入门开发教程:项目集成:1、服务端:注册中心、网关(提供可运行程序下载)。
系列目录: 本系列分为项目集成.项目部署.架构演进三个方向,后续会根据情况调整文章目录. 本系列第一篇:Taurus.MVC V3.0.3 微服务开源框架发布:让.NET 架构在大并发的演进过程更简单 ...
- Taurus.MVC 微服务框架 入门开发教程:项目集成:2、客户端:ASP.NET Core(C#)项目集成:应用中心。
系列目录: 本系列分为项目集成.项目部署.架构演进三个方向,后续会根据情况调整文章目录. 本系列第一篇:Taurus.MVC V3.0.3 微服务开源框架发布:让.NET 架构在大并发的演进过程更简单 ...
- Taurus.MVC 微服务框架 入门开发教程:项目集成:5、统一的日志管理。
系列目录: 本系列分为项目集成.项目部署.架构演进三个方向,后续会根据情况调整文章目录. 本系列第一篇:Taurus.MVC V3.0.3 微服务开源框架发布:让.NET 架构在大并发的演进过程更简单 ...
随机推荐
- [Luogu P2827] 蚯蚓 (巧妙的模拟)
题面: 传送门:https://www.luogu.org/problemnew/show/P2827 Solution 看到这题,我们肯定会有一个大胆想法. 那就是直接用堆模拟这个过程. 对于q,我 ...
- 2018-12-5 及 codeforces round 525v2
突然发现五天没记录了,这五天学习完全没有按着正常规划进行,先罗列一下吧. 机器学习视频第一周的全部看完了. 算法导论看了几页. 参加了一次CF.rating只加了20,看来提高实力才是最关键的. C+ ...
- C#5语法新特性
C# 5.NET Framework 4.5 Visual Studio 2012 C#5.0新引进的语法基于.Net Framework 4.5.主要引进的语法:异步与等待,调用方信息 其中最重要的 ...
- 易于理解的 python 深度学习摘要算法教程
序 "我不想要一份完整的报告,只要给我一份结果摘要就好".我经常发现自己处于这种状况 -- 无论是在大学里还是在我的职业生涯中.我们准备一份全面的报告,但老师/主管却只有时间阅读摘 ...
- explain命令---查看mysql执行计划
引言: 实际项目开发中,由于我们不知道实际查询的时候数据库里发生了什么事情,数据库软件是怎样扫描表.怎样使用索引的,因此,我们能感知到的就只有 sql语句运行的时间,在数据规模不大时,查询是瞬间的,因 ...
- Java中List,Set,Map区别
在Java开发面试中,面试官最常问到的就是Java集合,免不了要让面试者说出之间的区别,下面博主就对其做了总结. 1.集合与数组的区别 长度区别:数组是固定长度,集合长度可变: 内容区别:数组可以是基 ...
- WireShark——ARP 协议包分析
1. 什么是ARP ARP(Address Resolution Protocol)协议,即地址解析协议.该协议的功能就是将 IP 地 址解析成 MAC 地址. ARP(Address Resolu ...
- ctf-工具-binwalk
binwalk在玩杂项时是个不可缺的工具.1.最简单的,在玩隐写时,首先可以用它来找到其中的字符串例如:在铁人三项,东北赛区个人赛中,有一道题它直接给了一个文件,没有后缀,不知道是什么文件先binwa ...
- springboot使用swagger2生成开发文档
一.引入jar包 <dependency> <groupId>io.springfox</groupId> <artifactId>springfox- ...
- 新鲜出炉,这是全网讲的最详细的springboot整合消息服务了吧,建议收藏!
springboot整合activeMq ActiveMq是Apache提供的开源消息系统采用java实现, 很好地支持JMS(Java Message Service,即Java消息服务) 规范 A ...