Explorar o código

完成bind simple

yjp hai 1 ano
pai
achega
0df5b7227c

+ 145 - 0
binding/bind_item.go

@@ -0,0 +1,145 @@
+package binding
+
+import (
+	"git.sxidc.com/go-framework/baize/api"
+	"git.sxidc.com/go-framework/baize/binding/request"
+	"git.sxidc.com/go-framework/baize/domain"
+	"git.sxidc.com/go-tools/utils/reflectutils"
+	"git.sxidc.com/go-tools/utils/strutils"
+	"git.sxidc.com/service-supports/fserr"
+	"net/http"
+	"reflect"
+)
+
+func Bind[O any](binder *Binder, item *BindItem[O], middlewares ...api.Handler) {
+	item.bind(binder, middlewares...)
+}
+
+// BindItem 通用BindItem
+type BindItem[O any] struct {
+	Method string
+	*SimpleBindItem[O]
+}
+
+func (item *BindItem[O]) bind(binder *Binder, middlewares ...api.Handler) {
+	if strutils.IsStringEmpty(item.Path) {
+		panic("需要指定路径")
+	}
+
+	if strutils.IsStringEmpty(item.Method) {
+		panic("需要指定方法")
+	}
+
+	if item.ResponseFunc == nil {
+		panic("需要指定响应函数")
+	}
+
+	if item.ServiceFunc == nil {
+		panic("需要指定应用服务函数")
+	}
+
+	// 给单个路由增加中间件
+	handlers := []api.Handler{
+		func(c *api.Context) {
+			itemDTO := item.DTO
+
+			// 有请求数据
+			if itemDTO != nil {
+				// 将请求数据解析到dto中
+				if item.DTOBindFunc != nil {
+					err := item.DTOBindFunc(c, itemDTO)
+					if err != nil {
+						var outputZero O
+						item.ResponseFunc(c, http.StatusBadRequest, outputZero, err)
+						return
+					}
+				} else {
+					switch item.Method {
+					case http.MethodPost:
+						fallthrough
+					case http.MethodPut:
+						err := request.JsonBody(c, itemDTO)
+						if err != nil {
+							var outputZero O
+							item.ResponseFunc(c, http.StatusBadRequest, outputZero, err)
+							return
+						}
+					case http.MethodGet:
+						err := request.QueryParams(c, itemDTO)
+						if err != nil {
+							var outputZero O
+							item.ResponseFunc(c, http.StatusBadRequest, outputZero, err)
+							return
+						}
+					case http.MethodDelete:
+						err := request.PathParams(c, itemDTO)
+						if err != nil {
+							var outputZero O
+							item.ResponseFunc(c, http.StatusBadRequest, outputZero, err)
+							return
+						}
+					}
+				}
+			}
+
+			// 进行领域对象转化
+			var domainObjects []domain.Object
+			if item.FormDomainObjectsFunc != nil {
+				innerDomainObjects, err := item.FormDomainObjectsFunc(c, itemDTO)
+				if err != nil {
+					var outputZero O
+					item.ResponseFunc(c, http.StatusOK, outputZero, err)
+					return
+				}
+
+				domainObjects = innerDomainObjects
+			} else {
+				if item.Objects != nil && len(item.Objects) != 0 {
+					for _, object := range item.Objects {
+						if object == nil {
+							continue
+						}
+
+						objectType := reflect.TypeOf(object)
+						if !reflectutils.IsTypeStructOrStructPointer(objectType) {
+							var outputZero O
+							item.ResponseFunc(c, http.StatusOK, outputZero, fserr.New("领域对象不是结构或结构指针"))
+							return
+						}
+
+						obj := reflect.New(reflectutils.PointerTypeElem(objectType)).Interface()
+						err := request.AssignDTOToDomainObject(itemDTO, obj)
+						if err != nil {
+							var outputZero O
+							item.ResponseFunc(c, http.StatusOK, outputZero, err)
+							return
+						}
+
+						domainObjects = append(domainObjects, obj)
+					}
+				}
+			}
+
+			// 执行业务函数
+			statusCode := http.StatusOK
+
+			i := binder.i
+			if item.Infrastructure != nil {
+				i = item.Infrastructure
+			}
+
+			outputModel, err := item.ServiceFunc(c, itemDTO, domainObjects, i)
+			if err != nil {
+				statusCode = fserr.ParseCode(err).HttpCode
+			}
+
+			item.ResponseFunc(c, statusCode, outputModel, err)
+			return
+		},
+	}
+
+	handlers = append(handlers, middlewares...)
+
+	// 所有的函数加入到执行链中
+	binder.router.AddRoute(item.Method, item.Path, handlers...)
+}

+ 35 - 0
binding/binder.go

@@ -0,0 +1,35 @@
+package binding
+
+import (
+	"git.sxidc.com/go-framework/baize/api"
+	"git.sxidc.com/go-framework/baize/infrastructure"
+	"git.sxidc.com/go-framework/baize/infrastructure/database"
+)
+
+type Binder struct {
+	router api.Router
+	i      *infrastructure.Infrastructure
+}
+
+func NewBinder(router api.Router, i *infrastructure.Infrastructure) *Binder {
+	return &Binder{
+		router: router,
+		i:      i,
+	}
+}
+
+const (
+	DBExecutorOperations  = "operations"
+	DBExecutorDataService = "data_service"
+)
+
+func (binder *Binder) ChooseDBExecutor(dataExecutorType string) database.Executor {
+	switch dataExecutorType {
+	case DBExecutorOperations:
+		return binder.i.DBOperations()
+	case DBExecutorDataService:
+		return binder.i.DataService()
+	default:
+		return binder.i.DBOperations()
+	}
+}

+ 0 - 262
binding/binding.go

@@ -1,262 +0,0 @@
-package binding
-
-import (
-	"git.sxidc.com/go-framework/baize/api"
-	"git.sxidc.com/go-framework/baize/binding/request"
-	"git.sxidc.com/go-framework/baize/domain"
-	"git.sxidc.com/go-framework/baize/infrastructure"
-	"git.sxidc.com/go-tools/utils/reflectutils"
-	"git.sxidc.com/go-tools/utils/strutils"
-	"git.sxidc.com/service-supports/fserr"
-	"net/http"
-	"reflect"
-	"strings"
-)
-
-type Binder struct {
-	router api.Router
-	i      *infrastructure.Infrastructure
-}
-
-func NewBinder(router api.Router, i *infrastructure.Infrastructure) *Binder {
-	return &Binder{
-		router: router,
-		i:      i,
-	}
-}
-
-func PostBind[O any](binder *Binder, item *SimpleBindItem[O], middlewares ...api.Handler) {
-	item.bind(binder, http.MethodPost, middlewares...)
-}
-
-func DeleteBind[O any](binder *Binder, item *SimpleBindItem[O], middlewares ...api.Handler) {
-	item.bind(binder, http.MethodDelete, middlewares...)
-}
-
-func PutBind[O any](binder *Binder, item *SimpleBindItem[O], middlewares ...api.Handler) {
-	item.bind(binder, http.MethodPut, middlewares...)
-}
-
-func GetBind[O any](binder *Binder, item *SimpleBindItem[O], middlewares ...api.Handler) {
-	item.bind(binder, http.MethodGet, middlewares...)
-}
-
-func Bind[O any](binder *Binder, item *BindItem[O], middlewares ...api.Handler) {
-	item.bind(binder, middlewares...)
-}
-
-func Static(binder *Binder, item *StaticBindItem) {
-	item.bind(binder)
-}
-
-func StaticFile(binder *Binder, item *StaticFileBindItem) {
-	item.bind(binder)
-}
-
-type DTOBindFunc func(c *api.Context, dto request.DTO) error
-type FormDomainObjectsFunc func(c *api.Context, dto request.DTO) ([]domain.Object, error)
-type ServiceFunc[O any] func(c *api.Context, dto request.DTO, objects []domain.Object, i *infrastructure.Infrastructure) (O, error)
-type ResponseFunc[O any] func(c *api.Context, statusCode int, data O, err error)
-
-// SimpleBindItem  路由条目
-type SimpleBindItem[O any] struct {
-	// URL相对路径
-	Path string
-
-	// 使用的dto,非必传,当dto为nil时,说明该接口没有参数
-	DTO request.DTO
-
-	// 可选的dto绑定函数
-	// 非必传,POST和PUT请求默认为JsonBody,DELETE默认为PathParams,GET默认为QueryParams
-	// 额外还提供了一些转化函数:
-	// MultipartForm: 绑定multipart form
-	// FormBody: 绑定form body
-	// XMLBody: 绑定XML body
-	DTOBindFunc DTOBindFunc
-
-	// 通过DTO构造使用的领域对象,之后在ServiceFunc中会按照构造实体的顺序进行回调
-	// 非必传,如果为nil,则说明没有领域对象
-	// 与Objects字段二选一使用,如果都指定,会按照该字段处理
-	FormDomainObjectsFunc FormDomainObjectsFunc
-
-	// 使用的领域对象,当使用Tag对实体进行标注后,可以直接通过该字段给定实体,之后在ServiceFunc中会按照给定实体的顺序进行回调
-	// 非必传,如果为nil或长度为0,则说明没有领域对象
-	// 与FormObjectsFunc字段二选一使用,如果都指定,会按照FormObjectsFunc字段处理
-	Objects []domain.Object
-
-	// 基础设施实例,可以通过Application取到
-	Infrastructure *infrastructure.Infrastructure
-
-	// 应用服务泛型函数
-	ServiceFunc ServiceFunc[O]
-
-	// 响应泛型函数,如果不响应,需要使用NoResponse零值占位
-	ResponseFunc ResponseFunc[O]
-}
-
-func (item *SimpleBindItem[O]) bind(binder *Binder, method string, middlewares ...api.Handler) {
-	bindingItem := &BindItem[O]{
-		Method:         method,
-		SimpleBindItem: item,
-	}
-
-	bindingItem.bind(binder, middlewares...)
-}
-
-// BindItem 路由条目结构
-type BindItem[O any] struct {
-	Method string
-	*SimpleBindItem[O]
-}
-
-func (item *BindItem[O]) bind(binder *Binder, middlewares ...api.Handler) {
-	if strutils.IsStringEmpty(item.Path) {
-		panic("需要指定路径")
-	}
-
-	if strutils.IsStringEmpty(item.Method) {
-		panic("需要指定方法")
-	}
-
-	if item.ResponseFunc == nil {
-		panic("需要指定响应函数")
-	}
-
-	if item.ServiceFunc == nil {
-		panic("需要指定应用服务函数")
-	}
-
-	// 给单个路由增加中间件
-	handlers := []api.Handler{
-		func(c *api.Context) {
-			itemDTO := item.DTO
-
-			// 有请求数据
-			if itemDTO != nil {
-				// 将请求数据解析到dto中
-				if item.DTOBindFunc != nil {
-					err := item.DTOBindFunc(c, itemDTO)
-					if err != nil {
-						var outputZero O
-						item.ResponseFunc(c, http.StatusBadRequest, outputZero, err)
-						return
-					}
-				} else {
-					switch item.Method {
-					case http.MethodPost:
-						fallthrough
-					case http.MethodPut:
-						err := request.JsonBody(c, itemDTO)
-						if err != nil {
-							var outputZero O
-							item.ResponseFunc(c, http.StatusBadRequest, outputZero, err)
-							return
-						}
-					case http.MethodGet:
-						err := request.QueryParams(c, itemDTO)
-						if err != nil {
-							var outputZero O
-							item.ResponseFunc(c, http.StatusBadRequest, outputZero, err)
-							return
-						}
-					case http.MethodDelete:
-						err := request.PathParams(c, itemDTO)
-						if err != nil {
-							var outputZero O
-							item.ResponseFunc(c, http.StatusBadRequest, outputZero, err)
-							return
-						}
-					}
-				}
-			}
-
-			// 进行领域对象转化
-			var domainObjects []domain.Object
-			if item.FormDomainObjectsFunc != nil {
-				innerDomainObjects, err := item.FormDomainObjectsFunc(c, itemDTO)
-				if err != nil {
-					var outputZero O
-					item.ResponseFunc(c, http.StatusOK, outputZero, err)
-					return
-				}
-
-				domainObjects = innerDomainObjects
-			} else {
-				if item.Objects != nil && len(item.Objects) != 0 {
-					for _, object := range item.Objects {
-						if object == nil {
-							continue
-						}
-
-						objectType := reflect.TypeOf(object)
-						if !reflectutils.IsTypeStructOrStructPointer(objectType) {
-							var outputZero O
-							item.ResponseFunc(c, http.StatusOK, outputZero, fserr.New("领域对象不是结构或结构指针"))
-							return
-						}
-
-						obj := reflect.New(reflectutils.PointerTypeElem(objectType)).Interface()
-						err := request.AssignDTOToDomainObject(itemDTO, obj)
-						if err != nil {
-							var outputZero O
-							item.ResponseFunc(c, http.StatusOK, outputZero, err)
-							return
-						}
-
-						domainObjects = append(domainObjects, obj)
-					}
-				}
-			}
-
-			// 执行业务函数
-			statusCode := http.StatusOK
-
-			i := binder.i
-			if item.Infrastructure != nil {
-				i = item.Infrastructure
-			}
-
-			outputModel, err := item.ServiceFunc(c, itemDTO, domainObjects, i)
-			if err != nil {
-				statusCode = fserr.ParseCode(err).HttpCode
-			}
-
-			item.ResponseFunc(c, statusCode, outputModel, err)
-			return
-		},
-	}
-
-	handlers = append(handlers, middlewares...)
-
-	// 所有的函数加入到执行链中
-	binder.router.AddRoute(item.Method, item.Path, handlers...)
-}
-
-// StaticBindItem 静态路由item
-type StaticBindItem struct {
-	RelativePath string
-	Root         string
-	WithBasePath bool
-}
-
-func (item *StaticBindItem) bind(binder *Binder) {
-	if item.WithBasePath {
-		binder.router.Static(strings.TrimPrefix(item.RelativePath, binder.router.BasePath()), item.Root)
-	} else {
-		binder.router.Static(item.RelativePath, item.Root)
-	}
-}
-
-type StaticFileBindItem struct {
-	RelativePath string
-	FilePath     string
-	WithBasePath bool
-}
-
-func (item *StaticFileBindItem) bind(binder *Binder) {
-	if item.WithBasePath {
-		binder.router.StaticFile(strings.TrimPrefix(item.RelativePath, binder.router.BasePath()), item.FilePath)
-	} else {
-		binder.router.StaticFile(item.RelativePath, item.FilePath)
-	}
-}

+ 0 - 0
binding/service/entity_crud/callbacks.go → binding/entity_crud/callbacks.go


+ 93 - 0
binding/entity_crud/entity_crud.go

@@ -0,0 +1,93 @@
+package entity_crud
+
+import (
+	"git.sxidc.com/go-framework/baize/binding"
+	"git.sxidc.com/go-framework/baize/binding/request"
+	"git.sxidc.com/go-framework/baize/binding/response"
+	"git.sxidc.com/go-framework/baize/domain"
+)
+
+func BindSimple[O any](binder *binding.Binder, crud *Simple[O]) {
+	crud.bind(binder)
+}
+
+// Simple 实体CRUD的Bind参数
+type Simple[O any] struct {
+	// 使用的领域实体,注意是Entity类型
+	Entity domain.Entity
+
+	// 表名
+	TableName string
+
+	// 选择要使用的数据库Executor
+	// DBExecutorOperations operations 数据库操作
+	// DBExecutorDataService data_service 数据服务
+	DBExecutorType string
+
+	// URL领域相对路径,如/class,后面会自动补充
+	DomainPath string
+
+	// 创建使用的DTO
+	CreateDTO request.DTO
+
+	// 删除使用的DTO,注意是WithID类型
+	DeleteDTO request.WithID
+
+	// 更新使用的DTO,注意是WithID类型
+	UpdateDTO request.WithID
+
+	// 查询使用的DTO,注意是Query类型
+	QueryDTO request.Query
+
+	// 根据ID查询使用的DTO,注意是WithID类型
+	QueryByIDDTO request.WithID
+}
+
+func (crud *Simple[O]) bind(binder *binding.Binder) {
+	dbExecutor := binder.ChooseDBExecutor(crud.DBExecutorType)
+
+	// 创建班级
+	binding.PostBind(binder, &binding.SimpleBindItem[string]{
+		Path:         crud.DomainPath + "/create",
+		ResponseFunc: response.SendIDResponse[string],
+		DTO:          crud.CreateDTO,
+		Objects:      []domain.Object{crud.Entity},
+		ServiceFunc:  CommonEntityCreate(crud.TableName, dbExecutor, nil),
+	})
+
+	// 删除班级
+	binding.DeleteBind(binder, &binding.SimpleBindItem[any]{
+		Path:         crud.DomainPath + "/:id/delete",
+		ResponseFunc: response.SendMsgResponse,
+		DTO:          crud.DeleteDTO,
+		Objects:      []domain.Object{crud.Entity},
+		ServiceFunc:  CommonEntityDelete(crud.TableName, dbExecutor, nil),
+	})
+
+	// 修改班级
+	binding.PutBind(binder, &binding.SimpleBindItem[any]{
+		Path:         crud.DomainPath + "/update",
+		ResponseFunc: response.SendMsgResponse,
+		DTO:          crud.UpdateDTO,
+		Objects:      []domain.Object{crud.Entity},
+		ServiceFunc:  CommonEntityUpdate(crud.TableName, dbExecutor, nil),
+	})
+
+	// 查询班级
+	binding.GetBind(binder, &binding.SimpleBindItem[response.InfosData[O]]{
+		Path:         crud.DomainPath + "/query",
+		ResponseFunc: response.SendInfosResponse[O],
+		DTO:          crud.QueryDTO,
+		Objects:      []domain.Object{crud.Entity},
+		ServiceFunc:  CommonEntityQuery[O](crud.TableName, dbExecutor, nil, nil),
+	})
+
+	// 通过ID获取班级
+	binding.GetBind(binder, &binding.SimpleBindItem[O]{
+		Path:         crud.DomainPath + "/get",
+		ResponseFunc: response.SendInfoResponse[O],
+		DTO:          crud.QueryByIDDTO,
+		Objects:      []domain.Object{crud.Entity},
+		ServiceFunc:  CommonEntityQueryByID[O](crud.TableName, dbExecutor, nil),
+	})
+}

+ 36 - 46
binding/service/entity_crud/service.go → binding/entity_crud/service.go

@@ -15,10 +15,8 @@ import (
 	"reflect"
 )
 
-func CommonEntityCreate(tableName string, dbExecutorType string, callbacks *Callbacks[string]) binding.ServiceFunc[string] {
+func CommonEntityCreate(tableName string, dbExecutor database.Executor, callbacks *Callbacks[string]) binding.ServiceFunc[string] {
 	return func(c *api.Context, dto request.DTO, objects []domain.Object, i *infrastructure.Infrastructure) (string, error) {
-		dbExecutor := i.ChooseDBExecutor(dbExecutorType)
-
 		e, ok := objects[0].(domain.Entity)
 		if !ok {
 			return "", fserr.New("需要传递领域对象应该为实体")
@@ -47,10 +45,8 @@ func CommonEntityCreate(tableName string, dbExecutorType string, callbacks *Call
 	}
 }
 
-func CommonEntityDelete(tableName string, databaseExecutorType string, callbacks *Callbacks[any]) binding.ServiceFunc[any] {
+func CommonEntityDelete(tableName string, dbExecutor database.Executor, callbacks *Callbacks[any]) binding.ServiceFunc[any] {
 	return func(c *api.Context, dto request.DTO, objects []domain.Object, i *infrastructure.Infrastructure) (any, error) {
-		dbExecute := i.ChooseDBExecutor(databaseExecutorType)
-
 		e, ok := objects[0].(domain.Entity)
 		if !ok {
 			return nil, fserr.New("需要传递领域对象应该为实体")
@@ -58,40 +54,38 @@ func CommonEntityDelete(tableName string, databaseExecutorType string, callbacks
 
 		if strutils.IsStringEmpty(e.GetID()) {
 			err := fserr.New("领域实体ID为空")
-			return callbackOnError(callbacks, e, err, dbExecute, nil)
+			return callbackOnError(callbacks, e, err, dbExecutor, nil)
 		}
 
-		exist, err := database.CheckExist(dbExecute, &sql.CheckExistExecuteParams{
+		exist, err := database.CheckExist(dbExecutor, &sql.CheckExistExecuteParams{
 			TableName:  tableName,
 			Conditions: sql.NewConditions().Equal(e.IDColumnName(), e.GetID()),
 		})
 		if err != nil {
-			return callbackOnError(callbacks, e, err, dbExecute, nil)
+			return callbackOnError(callbacks, e, err, dbExecutor, nil)
 		}
 
 		if !exist {
 			err := fserr.New(e.DomainCNName() + "不存在")
-			return callbackOnError(callbacks, e, err, dbExecute, nil)
+			return callbackOnError(callbacks, e, err, dbExecutor, nil)
 		}
 
-		err = callbackBeforeDBOperate(callbacks, e, dbExecute)
+		err = callbackBeforeDBOperate(callbacks, e, dbExecutor)
 		if err != nil {
-			return callbackOnError(callbacks, e, err, dbExecute, nil)
+			return callbackOnError(callbacks, e, err, dbExecutor, nil)
 		}
 
-		err = database.DeleteEntity(dbExecute, tableName, e)
+		err = database.DeleteEntity(dbExecutor, tableName, e)
 		if err != nil {
-			return callbackOnError(callbacks, e, err, dbExecute, nil)
+			return callbackOnError(callbacks, e, err, dbExecutor, nil)
 		}
 
-		return callbackOnReturn(callbacks, e, dbExecute, nil)
+		return callbackOnReturn(callbacks, e, dbExecutor, nil)
 	}
 }
 
-func CommonEntityUpdate(tableName string, databaseExecutorType string, callbacks *Callbacks[any]) binding.ServiceFunc[any] {
+func CommonEntityUpdate(tableName string, dbExecutor database.Executor, callbacks *Callbacks[any]) binding.ServiceFunc[any] {
 	return func(c *api.Context, dto request.DTO, objects []domain.Object, i *infrastructure.Infrastructure) (any, error) {
-		dbExecute := i.ChooseDBExecutor(databaseExecutorType)
-
 		e, ok := objects[0].(domain.Entity)
 		if !ok {
 			return nil, fserr.New("需要传递领域对象应该为实体")
@@ -99,40 +93,38 @@ func CommonEntityUpdate(tableName string, databaseExecutorType string, callbacks
 
 		if strutils.IsStringEmpty(e.GetID()) {
 			err := fserr.New("领域实体ID为空")
-			return callbackOnError(callbacks, e, err, dbExecute, nil)
+			return callbackOnError(callbacks, e, err, dbExecutor, nil)
 		}
 
-		exist, err := database.CheckExist(dbExecute, &sql.CheckExistExecuteParams{
+		exist, err := database.CheckExist(dbExecutor, &sql.CheckExistExecuteParams{
 			TableName:  tableName,
 			Conditions: sql.NewConditions().Equal(e.IDColumnName(), e.GetID()),
 		})
 		if err != nil {
-			return callbackOnError(callbacks, e, err, dbExecute, nil)
+			return callbackOnError(callbacks, e, err, dbExecutor, nil)
 		}
 
 		if !exist {
 			err := fserr.New(e.DomainCNName() + "不存在")
-			return callbackOnError(callbacks, e, err, dbExecute, nil)
+			return callbackOnError(callbacks, e, err, dbExecutor, nil)
 		}
 
-		err = callbackBeforeDBOperate(callbacks, e, dbExecute)
+		err = callbackBeforeDBOperate(callbacks, e, dbExecutor)
 		if err != nil {
-			return callbackOnError(callbacks, e, err, dbExecute, nil)
+			return callbackOnError(callbacks, e, err, dbExecutor, nil)
 		}
 
-		err = database.UpdateEntity(dbExecute, tableName, e)
+		err = database.UpdateEntity(dbExecutor, tableName, e)
 		if err != nil {
-			return callbackOnError(callbacks, e, err, dbExecute, nil)
+			return callbackOnError(callbacks, e, err, dbExecutor, nil)
 		}
 
-		return callbackOnReturn(callbacks, e, dbExecute, nil)
+		return callbackOnReturn(callbacks, e, dbExecutor, nil)
 	}
 }
 
-func CommonEntityQuery[O any](tableName string, databaseExecutorType string, callbacks *Callbacks[response.InfosData[O]], conditionFieldCallback domain.ConditionFieldCallback) binding.ServiceFunc[response.InfosData[O]] {
+func CommonEntityQuery[O any](tableName string, dbExecutor database.Executor, callbacks *Callbacks[response.InfosData[O]], conditionFieldCallback domain.ConditionFieldCallback) binding.ServiceFunc[response.InfosData[O]] {
 	return func(c *api.Context, dto request.DTO, objects []domain.Object, i *infrastructure.Infrastructure) (response.InfosData[O], error) {
-		dbExecute := i.ChooseDBExecutor(databaseExecutorType)
-
 		queryDTO, ok := dto.(request.Query)
 		if !ok {
 			return response.InfosData[O]{}, fserr.New("DTO不是Query")
@@ -164,25 +156,25 @@ func CommonEntityQuery[O any](tableName string, databaseExecutorType string, cal
 			}
 		}
 
-		err = callbackBeforeDBOperate(callbacks, e, dbExecute)
+		err = callbackBeforeDBOperate(callbacks, e, dbExecutor)
 		if err != nil {
-			return callbackOnError(callbacks, e, err, dbExecute, response.InfosData[O]{})
+			return callbackOnError(callbacks, e, err, dbExecutor, response.InfosData[O]{})
 		}
 
-		results, totalCount, err := database.Query(dbExecute, &sql.QueryExecuteParams{
+		results, totalCount, err := database.Query(dbExecutor, &sql.QueryExecuteParams{
 			TableName:  tableName,
 			Conditions: conditions,
 			PageNo:     queryDTO.GetPageNo(),
 			PageSize:   queryDTO.GetPageSize(),
 		})
 		if err != nil {
-			return callbackOnError(callbacks, e, err, dbExecute, response.InfosData[O]{})
+			return callbackOnError(callbacks, e, err, dbExecutor, response.InfosData[O]{})
 		}
 
 		infos := make([]O, 0)
 		err = sql.ParseSqlResult(results, &infos)
 		if err != nil {
-			return callbackOnError(callbacks, e, err, dbExecute, response.InfosData[O]{})
+			return callbackOnError(callbacks, e, err, dbExecutor, response.InfosData[O]{})
 		}
 
 		output := response.InfosData[O]{
@@ -191,11 +183,11 @@ func CommonEntityQuery[O any](tableName string, databaseExecutorType string, cal
 			PageNo:     queryDTO.GetPageNo(),
 		}
 
-		return callbackOnReturn(callbacks, e, dbExecute, output)
+		return callbackOnReturn(callbacks, e, dbExecutor, output)
 	}
 }
 
-func CommonEntityQueryByID[O any](tableName string, databaseExecutorType string, callbacks *Callbacks[O]) binding.ServiceFunc[O] {
+func CommonEntityQueryByID[O any](tableName string, dbExecutor database.Executor, callbacks *Callbacks[O]) binding.ServiceFunc[O] {
 	return func(c *api.Context, dto request.DTO, objects []domain.Object, i *infrastructure.Infrastructure) (O, error) {
 		var outputZero O
 		outputZeroValue := reflect.Zero(reflect.TypeOf(outputZero))
@@ -203,8 +195,6 @@ func CommonEntityQueryByID[O any](tableName string, databaseExecutorType string,
 			outputZeroValue.Set(reflect.New(outputZeroValue.Type().Elem()))
 		}
 
-		dbExecute := i.ChooseDBExecutor(databaseExecutorType)
-
 		e, ok := objects[0].(domain.Entity)
 		if !ok {
 			return outputZero, fserr.New("需要传递领域对象应该为实体")
@@ -212,20 +202,20 @@ func CommonEntityQueryByID[O any](tableName string, databaseExecutorType string,
 
 		if strutils.IsStringEmpty(e.GetID()) {
 			err := fserr.New("领域实体ID为空")
-			return callbackOnError(callbacks, e, err, dbExecute, outputZero)
+			return callbackOnError(callbacks, e, err, dbExecutor, outputZero)
 		}
 
-		err := callbackBeforeDBOperate(callbacks, e, dbExecute)
+		err := callbackBeforeDBOperate(callbacks, e, dbExecutor)
 		if err != nil {
-			return callbackOnError(callbacks, e, err, dbExecute, outputZero)
+			return callbackOnError(callbacks, e, err, dbExecutor, outputZero)
 		}
 
-		result, err := database.QueryOne(dbExecute, &sql.QueryOneExecuteParams{
+		result, err := database.QueryOne(dbExecutor, &sql.QueryOneExecuteParams{
 			TableName:  tableName,
 			Conditions: sql.NewConditions().Equal(e.IDColumnName(), e.GetID()),
 		})
 		if err != nil {
-			return callbackOnError(callbacks, e, err, dbExecute, outputZero)
+			return callbackOnError(callbacks, e, err, dbExecutor, outputZero)
 		}
 
 		var info O
@@ -238,9 +228,9 @@ func CommonEntityQueryByID[O any](tableName string, databaseExecutorType string,
 
 		err = sql.ParseSqlResult(result, infoPointer)
 		if err != nil {
-			return callbackOnError(callbacks, e, err, dbExecute, outputZero)
+			return callbackOnError(callbacks, e, err, dbExecutor, outputZero)
 		}
 
-		return callbackOnReturn(callbacks, e, dbExecute, info)
+		return callbackOnReturn(callbacks, e, dbExecutor, info)
 	}
 }

+ 1 - 1
binding/request/common.go

@@ -1,6 +1,6 @@
 package request
 
-type ID interface {
+type WithID interface {
 	GetID() string
 }
 

+ 75 - 0
binding/simple_bind_item.go

@@ -0,0 +1,75 @@
+package binding
+
+import (
+	"git.sxidc.com/go-framework/baize/api"
+	"git.sxidc.com/go-framework/baize/binding/request"
+	"git.sxidc.com/go-framework/baize/domain"
+	"git.sxidc.com/go-framework/baize/infrastructure"
+	"net/http"
+)
+
+func PostBind[O any](binder *Binder, item *SimpleBindItem[O], middlewares ...api.Handler) {
+	item.bind(binder, http.MethodPost, middlewares...)
+}
+
+func DeleteBind[O any](binder *Binder, item *SimpleBindItem[O], middlewares ...api.Handler) {
+	item.bind(binder, http.MethodDelete, middlewares...)
+}
+
+func PutBind[O any](binder *Binder, item *SimpleBindItem[O], middlewares ...api.Handler) {
+	item.bind(binder, http.MethodPut, middlewares...)
+}
+
+func GetBind[O any](binder *Binder, item *SimpleBindItem[O], middlewares ...api.Handler) {
+	item.bind(binder, http.MethodGet, middlewares...)
+}
+
+type DTOBindFunc func(c *api.Context, dto request.DTO) error
+type FormDomainObjectsFunc func(c *api.Context, dto request.DTO) ([]domain.Object, error)
+type ServiceFunc[O any] func(c *api.Context, dto request.DTO, objects []domain.Object, i *infrastructure.Infrastructure) (O, error)
+type ResponseFunc[O any] func(c *api.Context, statusCode int, data O, err error)
+
+// SimpleBindItem 简化的BindItem
+type SimpleBindItem[O any] struct {
+	// URL相对路径
+	Path string
+
+	// 使用的dto,非必传,当dto为nil时,说明该接口没有参数
+	DTO request.DTO
+
+	// 可选的dto绑定函数
+	// 非必传,POST和PUT请求默认为JsonBody,DELETE默认为PathParams,GET默认为QueryParams
+	// 额外还提供了一些转化函数:
+	// MultipartForm: 绑定multipart form
+	// FormBody: 绑定form body
+	// XMLBody: 绑定XML body
+	DTOBindFunc DTOBindFunc
+
+	// 通过DTO构造使用的领域对象,之后在ServiceFunc中会按照构造实体的顺序进行回调
+	// 非必传,如果为nil,则说明没有领域对象
+	// 与Objects字段二选一使用,如果都指定,会按照该字段处理
+	FormDomainObjectsFunc FormDomainObjectsFunc
+
+	// 使用的领域对象,当使用Tag对实体进行标注后,可以直接通过该字段给定实体,之后在ServiceFunc中会按照给定实体的顺序进行回调
+	// 非必传,如果为nil或长度为0,则说明没有领域对象
+	// 与FormObjectsFunc字段二选一使用,如果都指定,会按照FormObjectsFunc字段处理
+	Objects []domain.Object
+
+	// 基础设施实例,可以通过Application取到
+	Infrastructure *infrastructure.Infrastructure
+
+	// 应用服务泛型函数
+	ServiceFunc ServiceFunc[O]
+
+	// 响应泛型函数,如果不响应,需要使用NoResponse零值占位
+	ResponseFunc ResponseFunc[O]
+}
+
+func (item *SimpleBindItem[O]) bind(binder *Binder, method string, middlewares ...api.Handler) {
+	bindingItem := &BindItem[O]{
+		Method:         method,
+		SimpleBindItem: item,
+	}
+
+	bindingItem.bind(binder, middlewares...)
+}

+ 40 - 0
binding/static.go

@@ -0,0 +1,40 @@
+package binding
+
+import "strings"
+
+func Static(binder *Binder, item *StaticBindItem) {
+	item.bind(binder)
+}
+
+func StaticFile(binder *Binder, item *StaticFileBindItem) {
+	item.bind(binder)
+}
+
+// StaticBindItem 静态路由item
+type StaticBindItem struct {
+	RelativePath string
+	Root         string
+	WithBasePath bool
+}
+
+func (item *StaticBindItem) bind(binder *Binder) {
+	if item.WithBasePath {
+		binder.router.Static(strings.TrimPrefix(item.RelativePath, binder.router.BasePath()), item.Root)
+	} else {
+		binder.router.Static(item.RelativePath, item.Root)
+	}
+}
+
+type StaticFileBindItem struct {
+	RelativePath string
+	FilePath     string
+	WithBasePath bool
+}
+
+func (item *StaticFileBindItem) bind(binder *Binder) {
+	if item.WithBasePath {
+		binder.router.StaticFile(strings.TrimPrefix(item.RelativePath, binder.router.BasePath()), item.FilePath)
+	} else {
+		binder.router.StaticFile(item.RelativePath, item.FilePath)
+	}
+}

+ 17 - 53
examples/binding/main.go

@@ -4,9 +4,8 @@ import (
 	"git.sxidc.com/go-framework/baize"
 	"git.sxidc.com/go-framework/baize/application"
 	"git.sxidc.com/go-framework/baize/binding"
+	"git.sxidc.com/go-framework/baize/binding/entity_crud"
 	"git.sxidc.com/go-framework/baize/binding/request"
-	"git.sxidc.com/go-framework/baize/binding/response"
-	"git.sxidc.com/go-framework/baize/binding/service/entity_crud"
 	"git.sxidc.com/go-framework/baize/domain"
 	"git.sxidc.com/go-framework/baize/infrastructure"
 	"git.sxidc.com/go-framework/baize/infrastructure/database/operations"
@@ -16,10 +15,10 @@ import (
 )
 
 // curl -X POST -H "Content-Type: application/json" -d '{"name":"test", "studentNum": 10}' "http://localhost:10100/test/v1/class/create"
-// curl -X PUT -H "Content-Type: application/json" -d '{"id":"10ec51a6485b4fadb9fc1b4f1360b8d0", "name":"test-new"}' "http://localhost:10100/test/v1/class/update"
+// curl -X PUT -H "Content-Type: application/json" -d '{"id":"6e3a9ec340124af6abe12fdbfd342580", "name":"test-new"}' "http://localhost:10100/test/v1/class/update"
 // curl -X GET "http://localhost:10100/test/v1/class/query?name=test-new&pageNo=1&pageSize=1"
-// curl -X GET "http://localhost:10100/test/v1/class/get?id=10ec51a6485b4fadb9fc1b4f1360b8d0"
-// curl -X DELETE "http://localhost:10100/test/v1/class/10ec51a6485b4fadb9fc1b4f1360b8d0/delete"
+// curl -X GET "http://localhost:10100/test/v1/class/get?id=6e3a9ec340124af6abe12fdbfd342580"
+// curl -X DELETE "http://localhost:10100/test/v1/class/6e3a9ec340124af6abe12fdbfd342580/delete"
 
 type CreateClassJsonBody struct {
 	Name       string `json:"name" binding:"required" assign:"toField:Name"`
@@ -27,11 +26,11 @@ type CreateClassJsonBody struct {
 }
 
 type DeleteClassPathParams struct {
-	ID string `uri:"id" binding:"required" assign:"toField:ID"`
+	request.IDPath
 }
 
 type UpdateClassJsonBody struct {
-	ID         string `json:"id" binding:"required" assign:"toField:ID"`
+	request.IDJsonBody
 	Name       string `json:"name" assign:"toField:Name"`
 	StudentNum int    `json:"studentNum" assign:"toField:StudentNum"`
 }
@@ -43,7 +42,7 @@ type QueryClassesQueryParams struct {
 }
 
 type GetClassQueryParams struct {
-	ID string `form:"id" binding:"required" assign:"toField:ID"`
+	request.IDQuery
 }
 
 type Class struct {
@@ -147,51 +146,16 @@ func main() {
 		PrefixRouter().
 		RegisterVersionedRouter("v1")
 
-	binder := app.Binder("v1")
-
-	// 创建班级
-	binding.PostBind(binder, &binding.SimpleBindItem[string]{
-		Path:         "/class/create",
-		ResponseFunc: response.SendIDResponse[string],
-		DTO:          &CreateClassJsonBody{},
-		Objects:      []domain.Object{&Class{}},
-		ServiceFunc:  entity_crud.CommonEntityCreate(tableName, infrastructure.DBExecutorOperations, nil),
-	})
-
-	// 删除班级
-	binding.DeleteBind(binder, &binding.SimpleBindItem[any]{
-		Path:         "/class/:id/delete",
-		ResponseFunc: response.SendMsgResponse,
-		DTO:          &DeleteClassPathParams{},
-		Objects:      []domain.Object{&Class{}},
-		ServiceFunc:  entity_crud.CommonEntityDelete(tableName, infrastructure.DBExecutorOperations, nil),
-	})
-
-	// 修改班级
-	binding.PutBind(binder, &binding.SimpleBindItem[any]{
-		Path:         "/class/update",
-		ResponseFunc: response.SendMsgResponse,
-		DTO:          &UpdateClassJsonBody{},
-		Objects:      []domain.Object{&Class{}},
-		ServiceFunc:  entity_crud.CommonEntityUpdate(tableName, infrastructure.DBExecutorOperations, nil),
-	})
-
-	// 查询班级
-	binding.GetBind(binder, &binding.SimpleBindItem[response.InfosData[ClassInfo]]{
-		Path:         "/class/query",
-		ResponseFunc: response.SendInfosResponse[ClassInfo],
-		DTO:          &QueryClassesQueryParams{},
-		Objects:      []domain.Object{&Class{}},
-		ServiceFunc:  entity_crud.CommonEntityQuery[ClassInfo](tableName, infrastructure.DBExecutorOperations, nil, nil),
-	})
-
-	// 通过ID获取班级
-	binding.GetBind(binder, &binding.SimpleBindItem[ClassInfo]{
-		Path:         "/class/get",
-		ResponseFunc: response.SendInfoResponse[ClassInfo],
-		DTO:          &GetClassQueryParams{},
-		Objects:      []domain.Object{&Class{}},
-		ServiceFunc:  entity_crud.CommonEntityQueryByID[ClassInfo](tableName, infrastructure.DBExecutorOperations, nil),
+	entity_crud.BindSimple[ClassInfo](app.Binder("v1"), &entity_crud.Simple[ClassInfo]{
+		Entity:         &Class{},
+		TableName:      tableName,
+		DBExecutorType: binding.DBExecutorOperations,
+		DomainPath:     "/class",
+		CreateDTO:      &CreateClassJsonBody{},
+		DeleteDTO:      &DeleteClassPathParams{},
+		UpdateDTO:      &UpdateClassJsonBody{},
+		QueryDTO:       &QueryClassesQueryParams{},
+		QueryByIDDTO:   &GetClassQueryParams{},
 	})
 
 	go func() {

+ 14 - 50
examples/binding_ds/main.go

@@ -4,9 +4,8 @@ import (
 	"git.sxidc.com/go-framework/baize"
 	"git.sxidc.com/go-framework/baize/application"
 	"git.sxidc.com/go-framework/baize/binding"
+	"git.sxidc.com/go-framework/baize/binding/entity_crud"
 	"git.sxidc.com/go-framework/baize/binding/request"
-	"git.sxidc.com/go-framework/baize/binding/response"
-	"git.sxidc.com/go-framework/baize/binding/service/entity_crud"
 	"git.sxidc.com/go-framework/baize/domain"
 	"git.sxidc.com/go-framework/baize/infrastructure"
 	"git.sxidc.com/go-framework/baize/infrastructure/database/data_service"
@@ -27,11 +26,11 @@ type CreateClassJsonBody struct {
 }
 
 type DeleteClassPathParams struct {
-	ID string `uri:"id" binding:"required" assign:"toField:ID"`
+	request.IDPath
 }
 
 type UpdateClassJsonBody struct {
-	ID         string `json:"id" binding:"required" assign:"toField:ID"`
+	request.IDJsonBody
 	Name       string `json:"name" assign:"toField:Name"`
 	StudentNum int    `json:"studentNum" assign:"toField:StudentNum"`
 }
@@ -43,7 +42,7 @@ type QueryClassesQueryParams struct {
 }
 
 type GetClassQueryParams struct {
-	ID string `form:"id" binding:"required" assign:"toField:ID"`
+	request.IDQuery
 }
 
 type Class struct {
@@ -102,51 +101,16 @@ func main() {
 		PrefixRouter().
 		RegisterVersionedRouter("v1")
 
-	binder := app.Binder("v1")
-
-	// 创建班级
-	binding.PostBind(binder, &binding.SimpleBindItem[string]{
-		Path:         "/class/create",
-		ResponseFunc: response.SendIDResponse[string],
-		DTO:          &CreateClassJsonBody{},
-		Objects:      []domain.Object{&Class{}},
-		ServiceFunc:  entity_crud.CommonEntityCreate(tableName, infrastructure.DBExecutorDataService, nil),
-	})
-
-	// 删除班级
-	binding.DeleteBind(binder, &binding.SimpleBindItem[any]{
-		Path:         "/class/:id/delete",
-		ResponseFunc: response.SendMsgResponse,
-		DTO:          &DeleteClassPathParams{},
-		Objects:      []domain.Object{&Class{}},
-		ServiceFunc:  entity_crud.CommonEntityDelete(tableName, infrastructure.DBExecutorDataService, nil),
-	})
-
-	// 修改班级
-	binding.PutBind(binder, &binding.SimpleBindItem[any]{
-		Path:         "/class/update",
-		ResponseFunc: response.SendMsgResponse,
-		DTO:          &UpdateClassJsonBody{},
-		Objects:      []domain.Object{&Class{}},
-		ServiceFunc:  entity_crud.CommonEntityUpdate(tableName, infrastructure.DBExecutorDataService, nil),
-	})
-
-	// 查询班级
-	binding.GetBind(binder, &binding.SimpleBindItem[response.InfosData[ClassInfo]]{
-		Path:         "/class/query",
-		ResponseFunc: response.SendInfosResponse[ClassInfo],
-		DTO:          &QueryClassesQueryParams{},
-		Objects:      []domain.Object{&Class{}},
-		ServiceFunc:  entity_crud.CommonEntityQuery[ClassInfo](tableName, infrastructure.DBExecutorDataService, nil, nil),
-	})
-
-	// 通过ID获取班级
-	binding.GetBind(binder, &binding.SimpleBindItem[ClassInfo]{
-		Path:         "/class/get",
-		ResponseFunc: response.SendInfoResponse[ClassInfo],
-		DTO:          &GetClassQueryParams{},
-		Objects:      []domain.Object{&Class{}},
-		ServiceFunc:  entity_crud.CommonEntityQueryByID[ClassInfo](tableName, infrastructure.DBExecutorDataService, nil),
+	entity_crud.BindSimple[ClassInfo](app.Binder("v1"), &entity_crud.Simple[ClassInfo]{
+		Entity:         &Class{},
+		TableName:      tableName,
+		DBExecutorType: binding.DBExecutorDataService,
+		DomainPath:     "/class",
+		CreateDTO:      &CreateClassJsonBody{},
+		DeleteDTO:      &DeleteClassPathParams{},
+		UpdateDTO:      &UpdateClassJsonBody{},
+		QueryDTO:       &QueryClassesQueryParams{},
+		QueryByIDDTO:   &GetClassQueryParams{},
 	})
 
 	go func() {

+ 0 - 17
infrastructure/infrastructure.go

@@ -1,7 +1,6 @@
 package infrastructure
 
 import (
-	"git.sxidc.com/go-framework/baize/infrastructure/database"
 	"git.sxidc.com/go-framework/baize/infrastructure/database/data_service"
 	"git.sxidc.com/go-framework/baize/infrastructure/database/operations"
 )
@@ -66,22 +65,6 @@ func DestroyInfrastructure(i *Infrastructure) {
 	return
 }
 
-const (
-	DBExecutorOperations  = "operations"
-	DBExecutorDataService = "data_service"
-)
-
-func (i Infrastructure) ChooseDBExecutor(dataExecutorType string) database.Executor {
-	switch dataExecutorType {
-	case DBExecutorOperations:
-		return i.DBOperations()
-	case DBExecutorDataService:
-		return i.DataService()
-	default:
-		return i.DBOperations()
-	}
-}
-
 func (i Infrastructure) DBOperations() *operations.Operations {
 	return i.dbOperations
 }