首页 > 其他分享 >项目总结

项目总结

时间:2024-10-04 17:25:03浏览次数:8  
标签:总结 Web http 项目 中间件 分组 Gee 路由

一. gee-web

1. 实现目标

Gee Web 是一个极简的 Go 语言 Web 框架,设计目标是为开发者提供一个简单、高效且易于扩展的 Web 框架。它通过 Go 的内置并发特性(goroutine)、接口和反射等机制,实现了基本的路由、请求处理、分组、中间件等功能,帮助开发者快速构建 Web 应用程序。

2. 总的框架结构

Gee Web 的核心包括几个重要部分:路由管理、路由分组、中间件支持、请求上下文管理、静态文件服务、HTTP 错误处理等

  • EngineGee Web 的核心结构体,负责启动 HTTP 服务器,管理路由、分组和中间件。Engine 通过嵌入 RouterGroup 实现了路由分组管理的功能,并持有 routergroups 这些核心属性。

  • Router:实现了路由注册和路由分发。将不同的 HTTP 方法和路径映射到处理函数 (HandlerFunc),并在请求到达时,查找对应的处理函数进行执行。

  • RouterGroup:用于路由的分组管理,可以通过设置不同的路径前缀或中间件,构建层次化的 API 结构。

  • Context:对每个 HTTP 请求的封装,包含请求 (http.Request) 和响应 (http.ResponseWriter) 的处理逻辑。它提供了便捷的方法来处理请求参数、响应输出、设置状态码、管理中间件控制流等。

  • 中间件Gee Web 支持在路由处理前后执行中间件逻辑。通过在 RouterGroup 级别和全局级别注册中间件,可以灵活地控制请求的处理过程。

  • 静态文件服务:通过 http.StripPrefixhttp.FileServer 实现了静态文件的便捷处理。

3. 框架的关键设计细节和精巧之处

(1)路由分组设计

Gee Web 通过 RouterGroup 实现了路由的分组管理,这种设计使得开发者可以将具有相同前缀的 API 进行分组,例如 /api/v1/api/v2。每个分组共享相同的 Engine 实例,并可以在分组中注册不同的中间件。

// Example: 创建新的路由组
group := engine.Group("/v2")
group.GET("/users", usersHandler)

这种分组机制的核心设计是通过 RouterGroup 的嵌套实现的,保证了子路由能够继承父路由的前缀和中间件。

(2)中间件机制

Gee Web 中间件的执行顺序是链式调用的,类似于责任链模式。每个中间件通过 Next() 调用下一个中间件或路由处理函数。这样可以灵活地控制中间件的执行顺序,在请求进入或离开时,添加特定逻辑(如日志记录、认证、跨域控制等)。

func (c *Context) Next() {
    c.index++
    for ; c.index < len(c.middlewares); c.index++ {
        c.middlewares[c.index](c)
    }
}
(3)Context 对象封装

Gee Web 通过 Context 将 HTTP 请求和响应封装成一个对象,简化了 http.Requesthttp.ResponseWriter 的处理。同时,Context 支持链式调用和参数解析,如 JSON 响应、设置响应头、状态码等。这样设计大大提高了代码的可读性和可维护性。

func (c *Context) JSON(code int, obj interface{}) {
    c.SetHeader("Content-Type", "application/json")
    c.Status(code)
    encoder := json.NewEncoder(c.Writer)
    encoder.Encode(obj)
}
(4)错误恢复机制

Gee Web 支持通过 deferrecover 捕获 panic,防止服务器因为请求处理中的错误而崩溃。在遇到不可恢复的错误时,能够优雅地处理并返回 500 错误,而不会让服务器宕机。

defer func() {
    if err := recover(); err != nil {
        log.Printf("Recovered from panic: %v", err)
        c.Fail(http.StatusInternalServerError, "Internal Server Error")
    }
}()
(5)静态文件处理

通过 http.StripPrefixhttp.FileServer 实现了对静态文件的便捷处理。框架中创建了一个静态文件处理器,将文件路径映射到实际的服务器文件系统中。

func (group *RouterGroup) Static(relativePath string, root string) {
    handler := group.createStaticHandler(relativePath, http.Dir(root))
    urlPattern := path.Join(relativePath, "/*filepath")
    group.GET(urlPattern, handler)
}
(6)链式路由注册

Gee Web 的路由注册通过链式调用,使得 API 注册非常简洁和流畅。比如可以通过 .GET().POST() 等方法在路由分组中添加路由规则。

group := engine.Group("/api")
group.GET("/user", userHandler)
group.POST("/login", loginHandler)

4. 使用的 Go 特性

  • goroutine 并发处理:每个请求由一个独立的 goroutine 处理,充分利用 Go 的并发特性,提升了并发处理的能力。

  • 接口与多态:大量使用接口(如 http.HandlerHandlerFunc)进行路由和中间件解耦,确保了灵活性和扩展性。

  • defer 和 recover:利用 deferrecover 机制处理异常,保证了服务器在发生 panic 时不会崩溃,提供了基本的错误恢复机制。

  • 反射机制:通过 Go 的反射机制,可以对请求参数和响应进行灵活的处理,简化了数据传输和解析。

  • 闭包与链式调用:通过闭包实现了中间件的链式处理,每个中间件的执行可以通过 Next() 来控制,保证了灵活的控制流。

6. 总结

  • 从主函数流程来看,首先是通过engine实现处理上下文的ServeHTTP接口,方便传入http.ListenAndServe进行触发和并发运行业务处理逻辑,
  • 触发响应时新建一个上下文,该上下文记录地址,方法、状态码、匹配地址、所属engine、微服务、当前微服务下标,该上下文会根据请求报文地址,
  • 首先扫描所有分组,根据前缀获取微服务,然后engine处理该上下文,实际上就是根据前缀路由树,找到匹配的节点,获取对应哈希映射的函数,接着就是采用链式执行。
  • engine是一个特殊的分组,通过匿名嵌套实现,建立分组实例其实就是分组存储对应前缀,来区分分组权限,每个分组可以存储注册的微服务,
  • 然后路由前缀树叶子节点存储映射方法,每个engine只有一个路由树,也就是分组的方法注册和匹配也是在该路由树上进行的划分,所有分组共享一个engine,默认对所有方法注册日志微服务和错误恢复追溯微服务
  • 访问静态资源通过注册http提供的静态文件服务器映射处理函数,通过返回函数闭包该映射服务器

二. gee-cache

标签:总结,Web,http,项目,中间件,分组,Gee,路由
From: https://www.cnblogs.com/929code/p/18446901

相关文章

  • PbootCMS网站常见错误提示总结
    在安装和使用PbootCMS的过程中,新手朋友们经常会遇到一些常见的错误。下面列出了几个典型的错误及其解决方法,帮助大家顺利安装和使用PbootCMS。错误及解决方法Parseerror:syntaxerror,unexpected':',expecting'{'inwww\core\function\handle.phponline130问题描......
  • 从零开始创建一个空白的Vue项目(自用)
    目录一、配置node环境1.安装nvm2.安装node二、创建Vue项目1.创建Vue项目2.空白页面三、安装Vue3UI框架(ElementPlus)一、配置node环境1.安装nvm    可以在github下载nvm安装包,安装路径不要有中文。     在vscode里面按ctrl+shift+~打开命......
  • Vue3的项目搭建
    有两种方式可以搭建:一:使用vue-cli中的webpack创建 第二:推荐使用vite来创建项目vite是新一代前端构建工具,新的前端构建工具,比webpack要快一些。npmcreatevue@latest创建完项目后,我们可以看到项目最外层有index.htmlVite项目中,index.html是项目的入口文件,在项目最外层。......
  • CSP-J/S2024总结
    CSP-J/S2024游记初赛前记今年最后一年J了...希望圆我个2年都没有实现的J一等梦还有希望S考好点期待1=day-1考完不放假,然后月考,高兴坏了day1没什么好说的,行就行,不行就AFO(假CSP-J本来就打算摆烂,所以不慌因为是最后一个考场,只有26人,赢!嗯?开局放int?完辣!组合题放那......
  • 10.3 - AM - 模拟赛 总结
    复盘T1很水,一道异或求和,但是某两位仁兄因没打括号而死。T2很水,一道字符串处理,但是我和某位仁兄因没特判而死(虽然没有hack掉我,所以我理论上还是满分)。T3不水,看了很久,没想出来,自闭了就去看了T4。发现也做不出来。此时我出去晃了一圈,大概是不知道从哪里看到了一个“二”字......
  • 从 JavaScript 到 OCaml:浅浅浅总结一下函数式编程
    背景这几天突击了一下Cornell的cs3110;抽了两个下午刷完了Chapter3,4,5的课后习题,很有感触。结合自己浅薄的函数式编程理解和贫瘠的JavaScript/TypeScript开发经历,总结一下自己第一阶段的函数式编程学习经历。......
  • java日总结24-10-3:mysql的基础知识
    今日学习javaweb1、了解了javaweb的概况与数据库的相关概念2、安装了mysqlMySQL的学习:1、SQL的简介:是一门操作关系型数据库的编程语言2、SQL的通用语法:单行注释:--注释内容或#注释内容;多行注释:/注释内容/3、SQL的分类:一、DDL操作数据库:创建数据库:判断是否存在创建:c......
  • [Electron] 搭建 Vite+Electron 项目
    安装搭建Vite项目(根据官方文档搭建),安装electron、nodemon。pnpminstallelectronnodemon-D配置electron/main.jsfile:[electron/main.js]import{app,BrowserWindow}from"electron";constcreateWindow=()=>{constwin=newBrowserWindow({wid......
  • 10.2与10.3日noip多校联考总结
    10.2与10.3noip多校联考总结10.2T1考场上推了比较久,想到了对于每个二进制位进行贪心,但是往上面套了二分和判定,导致时间复杂度到了\(O(T\log^3n)\),时间过劣。在考后知道了二分和判定都可以省去。因为要求最小次数,所以不免想到了二分和贪心,用学长讲的“调整法”就可以很好......
  • 2024-1-16 三年总结 192623
    三年总结因果有关于感情,似乎不知从何说起,但是可以肯定的是有因果安排。这份因果一则还债,二则让我领悟一些道理。其中除了需要学会判断之外,还需要明白色即是空,也即放下执着,但并不仅限于爱情。对于一般人而言,必须要找一个活下去的意义,在世界上如果没有自己存在的价值,或者说优越感......