为你自己学Go
  • README
  • PART01.Web框架概览
    • 1.01 Web框架概览:学习路线
    • 1.02 Web框架概览-Beego框架分析
    • 1.03 Web框架概览-GIN框架分析
    • 1.04 Web框架概览-Iris框架分析
    • 1.05 Web框架概览-Echo框架分析
  • PART02.Server
    • 2.01 Server详解与面试要点
  • PART03.路由树
    • 3.01 路由树-Beego&GIN&Echo实现与设计总结
    • 3.02 路由树-全静态匹配
    • 3.03 路由树-TDD起步
    • 3.04 路由树-静态匹配测试用例
    • 3.05 路由树-静态匹配之路由查找
    • 3.06 路由树-静态匹配之集成Server
    • 3.07 路由树-通配符匹配之路由注册
    • 3.08 路由树-通配符匹配之路由查找与测试
    • 3.09 路由树-参数路径之基本注册和查找
    • 3.10 路由树-参数路径之校验
    • 3.11 路由树-参数路径之参数值
    • 3.12 路由树-总结与面试要点
  • PART04.课后复习
    • 4.01 课后复习-Server
    • 4.02 课后复习-Route
  • PART05.Context
    • 5.01 Context-简介
    • 5.02 Context-Beego Context设计分析
    • 5.03 Context-Gin Context设计分析
    • 5.04 Context-Echo和Iris的Context设计分析
    • 5.05 Context-处理输入输出总结
    • 5.06 Context-处理输入之Body输入
    • 5.07 Context-处理输入之表单输入
    • 5.08 Context-处理输入之查询参数、路径参数和StringValue
    • 5.09 Context-处理输出
    • 5.10 Context-总结与面试要点
  • PART06.AOP
    • 6.01 AOP简介与不同框架设计概览
    • 6.02 AOP设计方案-Middleware
  • PART07.Middleware
    • 7.01 Middleware-AccessLog
    • 7.02 Middleware-Trace简介和OpenTelemetry
    • 7.03 Middleware-OpenTelemetry测试
    • 7.04 Middleware-OpenTelemetry总结
    • 7.05 Prometheus详解
    • 7.06 Middleware-Prometheus
    • 7.07 Middleware-错误页面
    • 7.08 Middleware-从panic中恢复
    • 7.09 Middleware总结和面试
  • PART08.Review
    • 8.01 课后复习-AOP
    • 8.02 课后复习-Context
    • 8.03 课后复习-Middleware-AccessLog
  • PART09.Appendix
    • 附录1.责任链模式
    • 附录2.生成器模式
    • 附录3.函数选项模式
  • xiaochengxu
    • 01.原力去水印
    • 02.KeePass密码管理:安全轻松的管理您的密码
Powered by GitBook
On this page
  • PART1. 基本使用
  • PART2. 核心抽象
  • PART3. HttpServer和ControllerRegister
  • PART4. Context抽象
  • PART5. 核心抽象总结
  • 附录:1个进程监听2个端口的方法
  1. PART01.Web框架概览

1.02 Web框架概览-Beego框架分析

参考其它Web框架来设计自己的框架.

PART1. 基本使用

Beego是基于MVC(Model-View-Controller)的,所以它定义了一个核心接口ControllerInterface.ControllerInterface定义了一个控制器必须要解决什么问题.

示例:

定义Controller:

package beego

import "github.com/beego/beego/v2/server/web"

type UserController struct {
	web.Controller
}

func (c *UserController) GetUser() {
	c.Ctx.WriteString("你好,我是大明")
}

func (c *UserController) CreateUser() {
	u := &User{}
	err := c.Ctx.BindJSON(u)
	if err != nil {
		c.Ctx.WriteString(err.Error())
		return
	}

	_ = c.Ctx.JSONResp(u)
}

type User struct {
	Name string
}

可以看到,自定义的Controller是组合了Beego的web.Controller的.

使用Controller:

package beego

import (
	"github.com/beego/beego/v2/server/web"
	"testing"
)

func TestUserController(t *testing.T) {
	web.BConfig.CopyRequestBody = true
	c := &UserController{}
	web.Router("/user", c, "get:GetUser")
	// 监听 8081 端口
	web.Run(":8081")

}

注意web.Router("/user", c, "get:GetUser"),将uri/user映射到了ControllerUserController的GetUser()方法上."get:GetUser"中的get要求HTTP动词为GET.

PART2. 核心抽象

那么问题来了,Beego的核心抽象是什么?

// ControllerInterface is an interface to uniform all controller handler.
type ControllerInterface interface {
	Init(ct *context.Context, controllerName, actionName string, app interface{})
	Prepare()
	Get()
	Post()
	Delete()
	Put()
	Head()
	Patch()
	Options()
	Trace()
	Finish()
	Render() error
	XSRFToken() string
	CheckXSRFCookie() bool
	HandlerFunc(fn string) bool
	URLMapping()
}
  • Get()、Post()、Delete()、Put()、Head()、Patch()、Options()定义了如何处理HTTP动词

  • Init()、Prepare()、Finish()定义了一个Controller的生命周期.Prepare()类似于一个BeforeRequest的过程,Finish()类似于一个AfterRequest的过程,本质上二者都是回调

  • 实际上刚刚示例中的web.Contrller就是接口ControllerInterface的默认实现.自定义的Controller只需组合web.Contrller即可

注意示例中的如下2行代码:

web.Router("/user", c, "get:GetUser")
web.Run(":8081")

这说明用户虽然被要求组合web.Contrller,但路由注册和服务器启动是通过另一套机制来完成的.换言之,Beego框架中的路由注册与Controller的组合是无关的.Controller仅仅用于帮助组织业务代码.

PART3. HttpServer和ControllerRegister

ControllerInterface可以看做核心接口,因为它直接体现了Beego的设计初衷:MVC模式.同时它也是用户核心接入点.

  • HttpServer:代表一个"服务器",大多数时候它就是一个进程.

    • 当然你也可以做成1个进程监听多个端口的形式,但是端口与端口之间是资源隔离的

  • ControllerRegister:注册路由、路由匹配、执行业务代码都是通过它来完成的

PART4. Context抽象

// Context Http request context struct including BeegoInput, BeegoOutput, http.Request and http.ResponseWriter.
// BeegoInput and BeegoOutput provides an api to operate request and response more easily.
type Context struct {
	Input          *BeegoInput
	Output         *BeegoOutput
	Request        *http.Request
	ResponseWriter *Response
	_xsrfToken     string
}

Beego对Context进行了一个细分,分为Input和Output.Request字段是请求的副本,而ResponseWriter字段则是对响应的一个封装.

也有人认为Input应该包含Request,Output应该包含ResponseWriter,这样的设计会更清晰.

PART5. 核心抽象总结

  • ControllerRegister:最为基础,它解决了路由注册和路由匹配这个基础问题

  • Context和Controller:为用户提供了丰富API,用于辅助构建系统

    • 当然,硬要说的话,没有这二者也不是不行.只是用户需要手动和http.Request和http.ResponseWriter交互,这二者也只是对http.Request和http.ResponseWriter的封装

  • HttpServer:作为服务器抽象,用于管理应用生命周期和资源隔离单位

附录:1个进程监听2个端口的方法

package beego

import (
	"github.com/beego/beego/v2/server/web"
	"testing"
)

func TestUserController(t *testing.T) {
	go func() {
		s := web.NewHttpSever()
		s.Run(":8082")
	}()
	web.BConfig.CopyRequestBody = true
	c := &UserController{}
	web.Router("/user", c, "get:GetUser")
	// 监听 8081 端口
	web.Run(":8081")
}

此时访问localhost:8082/user是无法得到响应的.只有访问localhost:8081/user能够得到响应.

1个进程监听2个端口的使用场景:实时更新配置.例如同一个进程内,端口8081可以修改8082的内存

Last updated 9 months ago

但是如果从功能特性上来说,和才是核心

和之前的内容相比,其他抽象更侧重于用户友好性.抽象代表的是整个请求执行过程的上下文,用户操作请求和响应是通过Ctx来达成的.

实际上在Beego默认实现的Controller中也有这个.一般情况下这个Ctx代表了整个请求过程的上下文.

ControllerInterface
HttpServer
ControllerRegister
Context
Ctx
Beego核心抽象