基于Gin封装Web框架 - 7. 控制器优化 - 更好用的控制器模式

简介: 基于Gin封装Web框架 - 7. 控制器优化 - 更好用的控制器模式

基于Gin封装Web框架 - 7. 控制器优化 - 更好用的控制器模式

代码参考: https://github.com/go-jarvis/gin-rum

之前在 业务控制器模型中实现了一个简单的控制器模型, struct 对对象具有 Build() 方法, 就可以在 rum 中注册路由。

// 第一版注册起方法
type Index struct {
    Name string `query:""` 
}

func (index *Index) Build(rum *rum.RumGroup) {
    rum.Handle("GET", "/index", handlerIndex)
}

func handlerIndex(c *gin.Context) {
    name:=c.Query("name")
    c.JSON(200, map[string]string{
        "hello": "gin-rum, " + name,
    })
}

但是这样的控制器模型实现后, 在使用上还是有很多的不方便。

  1. Struct 对象 和将要绑定的 http 方法路由地址 完全割裂, 具体怎么定义需要在 Build() 方法中手工实现。
  2. 要在业务逻辑中实现 handler gin.HandleFunc 方法,逻辑臃肿。
  3. 变量绑定行为冗余, 每个 handler 都需要自己绑定变量并处理错误。

控制器优化

那要如何在 struct 定义的时候, 一站式完成所有需求约束呢? 要这么样 rum 框架帮忙处理这些冗余操作呢?

分析 rum.Handle 的参数, 分别是

  1. http 行为方法
  2. 相对路由地址
  3. 处理业务行为的 handler
rum.Handle("GET", "/index", handlerIndex)

func (group *RouterGroup) Handle(httpMethod, relativePath string, handlers ...HandlerFunc)

重新定义控制器接口

因此可以将 ClassController 结构定义成

  1. Method() string 方法: 返回 http 方法的值
  2. Path() string 方法: 返回相对路由地址
  3. Handler() (interface{}, error) 方法: 业务逻辑行为, 最终将被被 rum 封装成 handler 执行。
type ClassController interface {
    Method() string
    Path() string
    Handler() (interface{}, error)
}

重载 Handle 行为

既然控制器的接口已经变了, 那么响应的行为也需要进行变更。

// Mount 在 RumGroup 上绑定/注册 控制器
func (gg *RumGroup) Mount(group string, classes ...ClassController) *RumGroup {
    grp := newRumGroup(gg, group)

    // 老方法
    // for _, class := range claess {
    //     class.Build(grp)
    // }

    // 新方法
    for _, class := range classes {
        grp.Handle(class)
    }

    return grp
}

之前老方法是将 RumGroup 作为结构体的 Build 方法的参数传递到内部进行处理。新方法中为了能 简化请求参数的绑定和错误处理, 因此不能再将 RumGroup 传递下去了。

重载之后的的 RumGroup.Handle 方法以 结构体对象 作为参数

  1. 通过 Method()Path() 方法获取必要参数
  2. Handler() 方法封装成为 gin.HandlerFunc

    • 使用 ginbinder 库读取 request 中的所有需要参数
    • 根据 Handler() 方法的结构,封装 gin 的返回结果。
// Handle 重载 RumGroup 的 Handle 方法
func (gg *RumGroup) Handle(class ClassController) {

    m := class.Method()
    p := class.Path()
    handler := class.Handler

    // 将业务逻辑封装成为 gin.HandlerFunc
    handlerFunc := func(c *gin.Context) {
        // 绑定参数到对象中
        err := ginbinder.ShouldBindRequest(c, class)
        if err != nil {
            c.JSON(http.StatusBadRequest, err.Error())
            return
        }

        // 执行业务逻辑,获取返回值, 并封装返回结果
        v, err := handler()
        if err != nil {
            c.JSON(http.StatusInternalServerError, err.Error())
            return
        }

        // 以 JSON 格式返回信息
        c.JSON(http.StatusOK, v)
    }

    // 调用 gin RouterGroup 的 Handle 方法注册路由
    gg.RouterGroup.Handle(m, p, handlerFunc)
}

Handler 方法的传参数想法

最开的的想法, 是需要将 *gin.Context 传入到 Handler 方法中的, 这样使用者的行为能更广泛。 但后来思索再三后放弃了, Handler 方法更应该着力于 业务逻辑 而非管理或控制 gin 的行为。

type ClassController interface {
    Method() string
    Path() string
    // Handler(*gin.Context) (interface{}, error)
    Handler() (interface{}, error)
}

RumGroup.Handle 重载引起的 Fairing 控制器行为不兼容

之前在实现 Fairing 控制器的时候,为了方便 RumRumGroup 加载中间件的行为,使用了 gin.IRoutes 进行参数约束。

func attachFairings(iroute gin.IRoutes, fairs ...Fairing) {
    for _, fair := range fairs {
        fair := fair
        // 创建一个临时中间件 handler
        handler := func(c *gin.Context) {
            _ = fair.OnRequest(c)
            c.Next()
        }
        // 使用 中间件
        iroute.Use(handler)
    }
}

但是在重载 RumGroup 的 Handle 方法之后签名发生了改变, 由 Handle(string, string, ...HandlerFunc) IRoutes 变成了 Handle(class ClassController)。 因此引发了不兼容的情况。

type Rum struct {
    *gin.Engine
    rootGrp *RumGroup
}

因此最 Attach 也做了响应的改造。 将 Fairing 的接收者直接设置为了 RumGroup 。

func (gg *RumGroup) attach(fairs ...Fairing) {
    for _, fair := range fairs {
        fair := fair

        // 创建一个临时中间件 handler
        handler := func(c *gin.Context) {
            _ = fair.OnRequest(c)
            c.Next()
        }

        // 使用 中间件
        gg.Use(handler)
    }
}
相关文章
|
3月前
|
Java 应用服务中间件 Docker
java-web部署模式概述
本文总结了现代 Web 开发中 Spring Boot HTTP 接口服务的常见部署模式,包括 Servlet 与 Reactive 模型、内置与外置容器、物理机 / 容器 / 云环境部署及单体与微服务架构,帮助开发者根据实际场景选择合适的方案。
122 25
|
4月前
|
开发框架 JSON 中间件
Go语言Web开发框架实践:路由、中间件、参数校验
Gin框架以其极简风格、强大路由管理、灵活中间件机制及参数绑定校验系统著称。本文详解其核心功能:1) 路由管理,支持分组与路径参数;2) 中间件机制,实现全局与局部控制;3) 参数绑定,涵盖多种来源;4) 结构体绑定与字段校验,确保数据合法性;5) 自定义校验器扩展功能;6) 统一错误处理提升用户体验。Gin以清晰模块化、流程可控及自动化校验等优势,成为开发者的优选工具。
|
4月前
|
开发框架 JSON 中间件
Go语言Web开发框架实践:使用 Gin 快速构建 Web 服务
Gin 是一个高效、轻量级的 Go 语言 Web 框架,支持中间件机制,非常适合开发 RESTful API。本文从安装到进阶技巧全面解析 Gin 的使用:快速入门示例(Hello Gin)、定义 RESTful 用户服务(增删改查接口实现),以及推荐实践如参数校验、中间件和路由分组等。通过对比标准库 `net/http`,Gin 提供更简洁灵活的开发体验。此外,还推荐了 GORM、Viper、Zap 等配合使用的工具库,助力高效开发。
|
6月前
|
中间件 Go
Golang | Gin:net/http与Gin启动web服务的简单比较
总的来说,`net/http`和 `Gin`都是优秀的库,它们各有优缺点。你应该根据你的需求和经验来选择最适合你的工具。希望这个比较可以帮助你做出决策。
219 35
|
6月前
|
人工智能 自然语言处理 JavaScript
测试工程师要失业?Magnitude:开源AI Agent驱动的端到端测试框架,让Web测试更智能,自动完善测试用例!
Magnitude是一个基于视觉AI代理的开源端到端测试框架,通过自然语言构建测试用例,结合推理代理和视觉代理实现智能化的Web应用测试,支持本地运行和CI/CD集成。
751 15
测试工程师要失业?Magnitude:开源AI Agent驱动的端到端测试框架,让Web测试更智能,自动完善测试用例!
|
7月前
|
关系型数据库 MySQL 数据库
基于Flink CDC 开发,支持Web-UI的实时KingBase 连接器,三大模式无缝切换,效率翻倍!
TIS 是一款基于Web-UI的开源大数据集成工具,通过与人大金仓Kingbase的深度整合,提供高效、灵活的实时数据集成方案。它支持增量数据监听和实时写入,兼容MySQL、PostgreSQL和Oracle模式,无需编写复杂脚本,操作简单直观,特别适合非专业开发人员使用。TIS率先实现了Kingbase CDC连接器的整合,成为业界首个开箱即用的Kingbase CDC数据同步解决方案,助力企业数字化转型。
1219 5
基于Flink CDC 开发,支持Web-UI的实时KingBase 连接器,三大模式无缝切换,效率翻倍!
|
11月前
|
开发框架 搜索推荐 数据可视化
Django框架适合开发哪种类型的Web应用程序?
Django 框架凭借其强大的功能、稳定性和可扩展性,几乎可以适应各种类型的 Web 应用程序开发需求。无论是简单的网站还是复杂的企业级系统,Django 都能提供可靠的支持,帮助开发者快速构建高质量的应用。同时,其活跃的社区和丰富的资源也为开发者在项目实施过程中提供了有力的保障。
432 67
|
11月前
|
设计模式 前端开发 数据库
Python Web开发:Django框架下的全栈开发实战
【10月更文挑战第27天】本文介绍了Django框架在Python Web开发中的应用,涵盖了Django与Flask等框架的比较、项目结构、模型、视图、模板和URL配置等内容,并展示了实际代码示例,帮助读者快速掌握Django全栈开发的核心技术。
612 45
|
11月前
|
开发框架 JavaScript 前端开发
TypeScript 是一种静态类型的编程语言,它扩展了 JavaScript,为 Web 开发带来了强大的类型系统、组件化开发支持、与主流框架的无缝集成、大型项目管理能力和提升开发体验等多方面优势
TypeScript 是一种静态类型的编程语言,它扩展了 JavaScript,为 Web 开发带来了强大的类型系统、组件化开发支持、与主流框架的无缝集成、大型项目管理能力和提升开发体验等多方面优势。通过明确的类型定义,TypeScript 能够在编码阶段发现潜在错误,提高代码质量;支持组件的清晰定义与复用,增强代码的可维护性;与 React、Vue 等框架结合,提供更佳的开发体验;适用于大型项目,优化代码结构和性能。随着 Web 技术的发展,TypeScript 的应用前景广阔,将继续引领 Web 开发的新趋势。
221 2
|
11月前
|
中间件 Go API
Go语言中几种流行的Web框架,如Beego、Gin和Echo,分析了它们的特点、性能及适用场景,并讨论了如何根据项目需求、性能要求、团队经验和社区支持等因素选择最合适的框架
本文概述了Go语言中几种流行的Web框架,如Beego、Gin和Echo,分析了它们的特点、性能及适用场景,并讨论了如何根据项目需求、性能要求、团队经验和社区支持等因素选择最合适的框架。
1044 1