zoukankan      html  css  js  c++  java
  • 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创建控制器

    首先我们创建一个控制器和几个接口,创建控制器要注意以下几点:

    1. 所有控制器必须和 Mvc.ApiController的指针进行组合

    2. 为了从请求中抓取参数,我们使用到了go的tag特性,获取参数的格式为 param:"arg" 注意参数名要用双引号包裹,切用于进行参数绑定的结构体必须和 *Mvc.Requst组合

    3. 接口中用于进行自动绑定的结构体必须是指针类型

    4. 通过控制器的名称前缀来实现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!]

  • 相关阅读:
    Android自动化测试框架UIAutomator原理浅析
    UiAutomator和Appium之间的区别2
    UiAutomator、UiAutomator2、Bootstrap的关系
    好的博客和网站
    appium介绍和工作原理
    UiAutomator1.0 与 UiAutomator2.0
    Jenkins之配置GitHub-Webhook2
    jenkins部署github项目持续集成
    Windows下安装的Jenkins修改默认端口号8080(修改配置文件的方式)
    Git使用教程
  • 原文地址:https://www.cnblogs.com/maxzhang1985/p/14081932.html
Copyright © 2011-2022 走看看