Go-Spring 学习笔记三【v1.1.0版本】

记录版本

  • Go-Spring v1.1.0-rc2

安装

# 安装spring核心包
go get -u github.com/go-spring/[email protected]
# 安装web starter
# gin
go get -u github.com/go-spring/[email protected]
# echo
go get -u github.com/go-spring/[email protected]

1.过滤器

1.1 创建Web过滤器

main.go

package main

import (
	"errors"
	"github.com/go-spring/spring-core/gs"
	"github.com/go-spring/spring-core/web"
	// 引入spring web引擎
	// gin
	SpringGin "github.com/go-spring/spring-gin"
	// echo
	//SpringEcho "github.com/go-spring/spring-echo"
	// 这里使用SpringGin方式创建一个web容器, 因此引入web starter而不是具体某个web引擎的starter
	_ "github.com/go-spring/starter-web"
	"log"
)

// 定义token过滤器
type TokenFilter struct {
    
    
}

/**
	设置过滤器指定的path pattern范围, 这里设置为 /test2/* 即拦截 /test2/*类型的端点
	若不定义该方法则默认为全局拦截器
 */
func (f *TokenFilter) URLPatterns() []string {
    
    
	return []string{
    
    "/test2/*"}
}

// 实现 web.Filter 接口
func (t *TokenFilter) Invoke(ctx web.Context, chain web.FilterChain) {
    
    
	token :=  ctx.QueryParam("token")
	if token != "abcde" {
    
    
		ctx.JSON(web.ERROR.Error(errors.New("invalid token")))
	} else {
    
    
		chain.Next(ctx)
	}
}

func init() {
    
    
	// 使用SpringGin创建web容器, 使用该方式可创建多http server
	webContainer := SpringGin.NewContainer(web.ContainerConfig{
    
    
		Port:     8080,
		BasePath: "/",
	})
	// 为web容器添加token过滤器
	webContainer.AddFilter(&TokenFilter{
    
    })
	// 若直接使用默认容器则使用如下方法添加过滤器
	// gs.Object(&TokenFilter{}).Export((*web.Filter)(nil))

	// 注入容器并设置导出接口
	gs.Object(webContainer).Export((*web.Container)(nil))

	/*
		访问 http://127.0.0.1:8080/test/t1 将不会经过token拦截器, 返回:
			{
				"code": 200,
				"msg": "SUCCESS"
			}
		访问 http://127.0.0.1:8080/test2/t1 将被token过滤器拦截, 返回:
			{
				"code": -1,
				"msg": "ERROR",
				"err": "/path/main.go:32: invalid userId"
			}
		访问 http://127.0.0.1:8080/test2/t1?token=abcde 将被token过滤器放行, 返回:
			{
				"code": 200,
				"msg": "SUCCESS"
			}
	*/
	gs.Object(new(testController)).Init(func(c *testController) {
    
    
		gs.GetMapping("/test/t1", c.echo)
		gs.GetMapping("/test2/t1", c.echo)
	})
}

// 定义测试控制器
type testController struct {
    
    
}

func (c *testController) echo(ctx web.Context) {
    
    
	ctx.JSON(web.SUCCESS)
}

func main() {
    
    
	log.Fatal(gs.Run())
}

在spring-gin v1.1.0-rc2版本中, 中间件不会直接拦截并返回结果, 而是将拦截器的结果与端点方法返回的结果组合返回, 这里修改源码文件github.com/go-spring/spring-gin/container.go的168行与174行即可解决(问题已反馈, 等到正式版应该不会有这种问题了)

// ...省略
func HandlerWrapper(fn web.Handler, wildCardName string, filters []web.Filter) []gin.HandlerFunc {
    
    
	var handlers []gin.HandlerFunc

	handlers = append(handlers, func(ginCtx *gin.Context) {
    
    
		if WebContext(ginCtx) == nil {
    
    
			NewContext(fn, wildCardName, ginCtx)
		}
	})

	for _, filter := range filters {
    
    
		f := filter
		handlers = append(handlers, func(ginCtx *gin.Context) {
    
    
			f.Invoke(WebContext(ginCtx), &ginFilterChain{
    
    ginCtx})
			ginCtx.Abort() // 168行之后添加该代码
		})
	}

	handlers = append(handlers, func(ginCtx *gin.Context) {
    
    
		fn.Invoke(WebContext(ginCtx))
		ginCtx.Abort() // 174行之后添加该代码
	})

	return handlers
}
// ...省略

1.2 替换默认Web日志过滤器

Go-Spring启动的Web容器会带有默认的日志过滤器,当我们不需要使用默认日志而自定义日志时,可以在创建容器时重新设置日志过滤器, 如下所示:

main.go

package main

import (
	"github.com/go-spring/spring-core/gs"
	"github.com/go-spring/spring-core/web"
	SpringGin "github.com/go-spring/spring-gin"
    // 仅使用starter web
	_ "github.com/go-spring/starter-web"
	"log"
	"time"
)

func init() {
    
    
    // 方式一
	// 创建gin容器, 并设置初始化方法
	gs.Object(SpringGin.NewContainer(web.ContainerConfig{
    
    
		Port: 8080,
		BasePath: "/",
	})).Init(func(container *SpringGin.Container) {
    
    
        // 直接使用内置的web.FuncFilter方法构建过滤器
		container.SetLoggerFilter(web.FuncFilter(func(ctx web.Context, chain web.FilterChain) {
    
    
            // 自定义日志信息
			startTime := time.Now()
			chain.Next(ctx)
			log.Printf("接口耗时:%v", time.Since(startTime))
		}))
        // 导出为web.Container类型(若不指定将无法检测到web容器)
	}).Export((*web.Container)(nil))
    
    // 方式二
    // 使用gs.Provide + 函数方式创建 web 容器, 创建容器过程中配置容器日志过滤器及其他信息
    //gs.Provide(func() web.Container {
    
    
	//	webContainer := SpringGin.NewContainer(web.ContainerConfig{
    
    
	//		Port:     8080,
	//		BasePath: "/",
	//	})
	//	webContainer.SetLoggerFilter(web.FuncFilter(func(ctx web.Context, chain web.FilterChain) {
    
    
	//		startTime := time.Now()
	//		chain.Next(ctx)
	//		log.Printf("接口耗时:%v", time.Since(startTime))
	//	}))
	//	return webContainer
	//})

    
	// 定义GET方法端点
	gs.GetMapping("/", func(ctx web.Context) {
    
    
		ctx.JSON(web.SUCCESS.Data("Hello Go-Spring!"))
	})
}

func main() {
    
    
	log.Fatal(gs.Run())
}

猜你喜欢

转载自blog.csdn.net/qq_33129963/article/details/121402740