looklapi是一个为业务构建的基于kataras/iris的微服务开发脚手架项目。
项目地址https://github.com/DOLLook/looklapi
项目不限制web框架,开发者也可以方便地接入gin等web框架处理请求。
1. controller 1.1 api路由绑定controller api接口
paramValidator 参数校验器(可选)
beforeHandlers 接口请求前拦截器(可选)
afterHandlers 接口请求后拦截器(可选)
func RegisterController(irisApp *iris.Application, apiParty string, routePath string, httpMethod string, controller interface{}, paramValidator interface{}, beforeHandlers []iris.Handler, afterHandlers []iris.Handler)
注册接口
irisserver_middleware.RegisterController(
ctr.app,
ctr.apiParty(),
"/testLog",
http.MethodGet,
ctr.testLog,
ctr.testLogParamValidator,
nil,
nil)
1.2 api参数自动映射
无需解析请求参数,自动映射到接口
package irisserver_controller
import "fmt"
import "errors"
type testController struct {
}
func (ctr *testController) testLog(log string) error {
fmt.Println(log)
return nil
}
type LogBody struct{
id int
content string
}
// 结构化参数
func (ctr *testController) testLog(log *LogBody) error {
fmt.Println(log)
return nil
}
// 可选的参数校验器
// testLog参数校验
func (ctr *testController) testLogParamValidator(log string) error {
if len(log)==0{
return errors.New("invalid param")
}
return nil
}
2. 依赖注入
采用内置ioc容器实现(无第三方依赖)
容器实现了类型与实例绑定,使用tag注解注入,自动代理注入(暂未支持多层代理)itype 待绑定的类型target 绑定的实例proxy 指定是否为代理priority 指定注入优先级, 在自动注入时按优先级注入func Bind(itype reflect.Type, target interface{}, proxy bool, priority int)
3. service层注入
定义接口
package srv_isrv
type TestSrvInterface interface {
TestLog(log string) error
}
定义实现
package srv_impl
// 定义实现
type testSrvImpl struct {
}
func init() {
testSrv := &testSrvImpl{}
// 绑定接口映射
wireutils.Bind(reflect.TypeOf((*srv_isrv.TestSrvInterface)(nil)).Elem(), testSrv, false, 1)
}
// 实现接口
func (srv *testSrvImpl) TestLog(log string) error {
fmt.Println(log)
return nil
}
注入controller。使用Tag wired:"Autowired"
自动注入,使用springboot的同学应该很熟悉。
package irisserver_controller
import (
"srv-isrv"
"reflect"
)
type testController struct {
testSrv srv_isrv.TestSrvInterface `wired:"Autowired"`
}
var testApi *testController
func init() {
testApi = &testController{}
wireutils.Bind(reflect.TypeOf((*testController)(nil)).Elem(), testApi, false, 1)
}
func (ctr *testController) testLog(log string) error {
// 使用注入的testSrv
return ctr.testSrv.TestLog(log)
}
service层aop
在需要时,可通过可选的代理注入实现aop
定义代理并实现与业务层相同接口,代理层在容器中具有最高优先级,在注入时会优先注入(注:代理层是可选的)
package srv_proxy
// testsrv 代理
type testSrvProxy struct {
srv srv_isrv.TestSrvInterface `wired:"Autowired"`
}
func init() {
proxyIns := &testSrvProxy{}
// 绑定接口映射
wireutils.Bind(reflect.TypeOf((*srv_isrv.TestSrvInterface)(nil)).Elem(), proxyIns, true, 1)
}
// 代理实现
func (proxy *testSrvProxy) TestLog(log string) error {
fmt.Println("before log")
if err := proxy.srv.TestLog(log); err != nil {
return err
}
fmt.Println("after log")
return nil
}
4. 声明式http调用
声明调用接口
type RpcService interface {
SrvName() string
}
// TestService为远程测试服务,暴露接口TestApi
type TestService struct {
// 测试接口
// header 请求头,可选
// body 自定义参数, 可选
// temp1, temp2 自定义url参数, 可选
// resultPtr 自定义的请求结果接收指针,必传
// tag route: 指定请求路由, method: 指定求请方式, alias: 指定url参数别名
TestApi func(header http.Header, body []int, temp1 string, temp2 int, resultPtr *modelbase.ResponseResult) error `route:"/api/testapi" method:"POST" alias:"[temp1,temp2]"`
}
// 固定实现
func (srv *TestService) SrvName() string {
return "YOUR_SERVICE_NAME"
}
// 初始化注册接口
func init() {
register(&TestService{})
}
调用接口
// api错误响应
type errResponse struct {
// 是否成功
IsSuccess bool
// 错误码
ErrorCode int
// 错误信息
ErrorMsg string
}
// api请求响应值
type ResponseResult struct {
errResponse
// 结果
Result interface{}
}
// 请求结果
func NewResponse(data interface{}) (result *ResponseResult) {
result = &ResponseResult{
Result: data,
}
result.IsSuccess = true
return
}
// 调用
func testRequest(){
resp := NewResponse(make(map[int]int))
testClient := rpc.GetHttpRpcClient("YOUR_SERVICE_NAME").(*TestService)
if err := testClient.TestApi(nil,[]int{1,2,3},"temp1",0, resp); err != nil {
}
}
5. MQ
基于rabbitmq实现了两类消费者,worker模式和broadcast模式
worker模式maxRetry 消息最大重试次数, 重试过程中须自行保证消息幂等性
func NewWorkQueueConsumer(routeKey string, concurrency uint32, prefetchCount uint32, parallel bool, maxRetry uint32, messageType reflect.Type, consume func(msg interface{}) bool)
broadcast模式maxRetry 消息最大重试次数, 重试过程中须自行保证消息幂等性
func NewBroadcastConsumer(exchange string, maxRetry uint32, messageType reflect.Type, consume func(msg interface{}) bool)
示例
// 定义消费者
type testConsumer struct {
messageType reflect.Type // 接收的消息类型
testSrv srv_isrv.TestSrvInterface `wired:"Autowired"`
}
// 定义消息体
type myMsgBody struct{
}
func init() {
consumer := &testConsumer{} // 创建消费者
consumer.messageType = reflect.TypeOf((*myMsgBody)(nil)) // 指定接收的消息类型
mqutils.NewBroadcastConsumer(”your_exchange“, 5, consumer.messageType, consumer.consume)
wireutils.Bind(reflect.TypeOf((*testConsumer)(nil)).Elem(), consumer, false, 1)
}
// 消费消息
func (consumer *testConsumer) consume(msg interface{}) bool {
msgbody := msg.(*myMsgBody)
// your code...
// consumer.testSrv.TestLog("hello")
return true
}
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)