备份代码
This commit is contained in:
parent
e097eae2f4
commit
bf525906e4
|
@ -1,6 +1,7 @@
|
||||||
package http
|
package http
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"github.com/Superdanda/hade/app/infrastructure"
|
||||||
"github.com/Superdanda/hade/app/provider/database_connect"
|
"github.com/Superdanda/hade/app/provider/database_connect"
|
||||||
"github.com/Superdanda/hade/framework"
|
"github.com/Superdanda/hade/framework"
|
||||||
"github.com/Superdanda/hade/framework/gin"
|
"github.com/Superdanda/hade/framework/gin"
|
||||||
|
@ -13,8 +14,7 @@ func NewHttpEngine(container *framework.HadeContainer) (*gin.Engine, error) {
|
||||||
// 默认启动一个Web引擎
|
// 默认启动一个Web引擎
|
||||||
r := gin.Default()
|
r := gin.Default()
|
||||||
r.SetContainer(container)
|
r.SetContainer(container)
|
||||||
// 业务绑定路由操作
|
|
||||||
Routes(r)
|
|
||||||
// 返回绑定路由后的Web引擎
|
// 返回绑定路由后的Web引擎
|
||||||
|
|
||||||
// 对业务模型进行注册,通过注册名获取业务模型类型信息
|
// 对业务模型进行注册,通过注册名获取业务模型类型信息
|
||||||
|
@ -23,5 +23,10 @@ func NewHttpEngine(container *framework.HadeContainer) (*gin.Engine, error) {
|
||||||
//绑定服务
|
//绑定服务
|
||||||
container.Bind(&database_connect.DatabaseConnectProvider{})
|
container.Bind(&database_connect.DatabaseConnectProvider{})
|
||||||
|
|
||||||
|
//注册 infrastructure 包的实例
|
||||||
|
infrastructure.NewOrmRepositoryAndRegister(container)
|
||||||
|
|
||||||
|
// 业务绑定路由操作
|
||||||
|
Routes(r)
|
||||||
return r, nil
|
return r, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,7 +23,8 @@ func RegisterRoutes(r *gin.Engine) error {
|
||||||
{
|
{
|
||||||
|
|
||||||
userGroup.POST("/login", api.UserLogin)
|
userGroup.POST("/login", api.UserLogin)
|
||||||
|
userGroup.POST("/get", api.UserGet)
|
||||||
|
userGroup.POST("/save", api.UserSave)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,30 @@
|
||||||
|
package user
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/Superdanda/hade/app/http/result"
|
||||||
|
"github.com/Superdanda/hade/app/provider/user"
|
||||||
|
"github.com/Superdanda/hade/framework/gin"
|
||||||
|
"github.com/spf13/cast"
|
||||||
|
"net/http"
|
||||||
|
)
|
||||||
|
|
||||||
|
type UserGetParam struct {
|
||||||
|
ID string `json:"id"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (api *UserApi) UserGet(c *gin.Context) {
|
||||||
|
userService := c.MustMake(user.UserKey).(user.Service)
|
||||||
|
param := &UserGetParam{}
|
||||||
|
err := c.ShouldBindJSON(param)
|
||||||
|
if err != nil {
|
||||||
|
c.ISetStatus(http.StatusBadRequest).IJson(result.Fail("参数错误"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
userQuery, err := userService.GetUser(c, cast.ToInt64(param.ID))
|
||||||
|
if err != nil {
|
||||||
|
c.ISetStatus(http.StatusInternalServerError).IJson(result.Fail("网络开小差"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
c.ISetOkStatus().IJson(result.Success(userQuery))
|
||||||
|
}
|
|
@ -0,0 +1,44 @@
|
||||||
|
package user
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/Superdanda/hade/app/http/result"
|
||||||
|
"github.com/Superdanda/hade/app/provider/database_connect"
|
||||||
|
"github.com/Superdanda/hade/app/provider/user"
|
||||||
|
"github.com/Superdanda/hade/framework/gin"
|
||||||
|
"net/http"
|
||||||
|
)
|
||||||
|
|
||||||
|
type UserSaveParam struct {
|
||||||
|
ID int64 `gorm:"column:id;primary_key;auto_increment" json:"id"` // 代表用户id, 只有注册成功之后才有这个id,唯一表示一个用户
|
||||||
|
UserName string `gorm:"column:username;type:varchar(255);comment:用户名;not null" json:"username"`
|
||||||
|
NickName string `gorm:"column:username;type:varchar(255);comment:昵称;not null" json:"nickname"`
|
||||||
|
Email string `gorm:"column:email;type:varchar(255);comment:邮箱;not null" json:"email"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (u *UserSaveParam) conventUser() *user.User {
|
||||||
|
return &user.User{
|
||||||
|
ID: u.ID,
|
||||||
|
UserName: u.UserName,
|
||||||
|
NickName: u.NickName,
|
||||||
|
Email: u.Email,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (api *UserApi) UserSave(c *gin.Context) {
|
||||||
|
|
||||||
|
service := c.MustMake(database_connect.DatabaseConnectKey).(database_connect.Service)
|
||||||
|
service.DefaultDatabaseConnect().AutoMigrate(&user.User{})
|
||||||
|
|
||||||
|
userService := c.MustMake(user.UserKey).(user.Service)
|
||||||
|
param := &UserSaveParam{}
|
||||||
|
err := c.ShouldBindJSON(param)
|
||||||
|
if err != nil {
|
||||||
|
c.ISetStatus(http.StatusBadRequest).IJson(result.Fail("参数错误"))
|
||||||
|
}
|
||||||
|
conventUser := param.conventUser()
|
||||||
|
err = userService.SaveUser(c, conventUser)
|
||||||
|
if err != nil {
|
||||||
|
c.ISetStatus(http.StatusInternalServerError).IJson(result.Fail("网络开小差"))
|
||||||
|
}
|
||||||
|
c.ISetOkStatus().IJson(result.SuccessWithOKMessage())
|
||||||
|
}
|
|
@ -0,0 +1,18 @@
|
||||||
|
### GET request to example server
|
||||||
|
POST http://127.0.0.1:8888/user/get
|
||||||
|
Content-Type: application/json
|
||||||
|
|
||||||
|
{
|
||||||
|
"id": "1"
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
### POST request to example server
|
||||||
|
POST http://127.0.0.1:8888/user/save
|
||||||
|
Content-Type: application/json
|
||||||
|
|
||||||
|
{
|
||||||
|
"username": "testuser",
|
||||||
|
"nickname": "Test",
|
||||||
|
"email": "test@example.com"
|
||||||
|
}
|
|
@ -0,0 +1,46 @@
|
||||||
|
package result
|
||||||
|
|
||||||
|
type Result struct {
|
||||||
|
Code int `json:"code"`
|
||||||
|
Success bool `json:"success"`
|
||||||
|
Message string `json:"message"`
|
||||||
|
Data interface{} `json:"data,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Success 方法,封装成功响应的结构体
|
||||||
|
func Success(data interface{}) Result {
|
||||||
|
return Result{
|
||||||
|
Code: 1,
|
||||||
|
Success: true,
|
||||||
|
Message: "Success",
|
||||||
|
Data: data,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// SuccessWithMessage 方法,封装成功响应的结构体
|
||||||
|
func SuccessWithMessage(message string) Result {
|
||||||
|
return Result{
|
||||||
|
Code: 1,
|
||||||
|
Success: true,
|
||||||
|
Message: message,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// SuccessWithOKMessage 方法,封装成功响应的结构体, message 操作成功
|
||||||
|
func SuccessWithOKMessage() Result {
|
||||||
|
return Result{
|
||||||
|
Code: 1,
|
||||||
|
Success: true,
|
||||||
|
Message: "操作成功",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fail 方法,封装失败响应的结构体
|
||||||
|
func Fail(message string) Result {
|
||||||
|
return Result{
|
||||||
|
Code: 0,
|
||||||
|
Success: false,
|
||||||
|
Message: message,
|
||||||
|
Data: nil,
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
package infrastructure
|
||||||
|
|
||||||
|
import "github.com/Superdanda/hade/framework"
|
||||||
|
|
||||||
|
func NewOrmRepositoryAndRegister(container framework.Container) {
|
||||||
|
NewOrmUserRepositoryAndRegister(container) // 用户仓储实例
|
||||||
|
}
|
|
@ -6,6 +6,7 @@ import (
|
||||||
userModule "github.com/Superdanda/hade/app/provider/user"
|
userModule "github.com/Superdanda/hade/app/provider/user"
|
||||||
"github.com/Superdanda/hade/framework"
|
"github.com/Superdanda/hade/framework"
|
||||||
"github.com/Superdanda/hade/framework/contract"
|
"github.com/Superdanda/hade/framework/contract"
|
||||||
|
"github.com/Superdanda/hade/framework/provider/repository"
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -16,15 +17,18 @@ type UserRepository struct {
|
||||||
userModule.Repository
|
userModule.Repository
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewUserRepository(container framework.Container) contract.OrmRepository[userModule.User, int64] {
|
func NewOrmUserRepositoryAndRegister(container framework.Container) {
|
||||||
|
//获取必要服务对象
|
||||||
connectService := container.MustMake(database_connect.DatabaseConnectKey).(database_connect.Service)
|
connectService := container.MustMake(database_connect.DatabaseConnectKey).(database_connect.Service)
|
||||||
|
infrastructureService := container.MustMake(contract.InfrastructureKey).(contract.InfrastructureService)
|
||||||
|
repositoryService := container.MustMake(contract.RepositoryKey).(contract.RepositoryService)
|
||||||
|
|
||||||
connect := connectService.DefaultDatabaseConnect()
|
connect := connectService.DefaultDatabaseConnect()
|
||||||
userOrmService := &UserRepository{container: container, db: connect}
|
userOrmService := &UserRepository{container: container, db: connect}
|
||||||
infrastructureService := container.MustMake(contract.InfrastructureKey).(contract.InfrastructureService)
|
|
||||||
infrastructureService.RegisterOrmRepository(userModule.UserKey, userOrmService)
|
infrastructureService.RegisterOrmRepository(userModule.UserKey, userOrmService)
|
||||||
|
|
||||||
//repository.RegisterRepository[userModule.User, int64](userModule.UserKey,)
|
//注册通用仓储对象
|
||||||
return userOrmService
|
repository.RegisterRepository[userModule.User, int64](repositoryService, userModule.UserKey, userOrmService)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (u *UserRepository) SaveToDB(entity *userModule.User) error {
|
func (u *UserRepository) SaveToDB(entity *userModule.User) error {
|
||||||
|
@ -38,7 +42,7 @@ func (u *UserRepository) FindByIDFromDB(id int64) (*userModule.User, error) {
|
||||||
return user, nil
|
return user, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (u *UserRepository) FindByID64sFromDB(ids []int64) ([]*userModule.User, error) {
|
func (u *UserRepository) FindByIDsFromDB(ids []int64) ([]*userModule.User, error) {
|
||||||
var users []*userModule.User
|
var users []*userModule.User
|
||||||
// 使用 GORM 的 Where 方法查询用户 ID 在给定 ID 列表中的记录
|
// 使用 GORM 的 Where 方法查询用户 ID 在给定 ID 列表中的记录
|
||||||
if err := u.db.Where("id IN ?", ids).Find(&users).Error; err != nil {
|
if err := u.db.Where("id IN ?", ids).Find(&users).Error; err != nil {
|
||||||
|
@ -126,16 +130,18 @@ func (u *UserRepository) GetFieldValueFunc(fieldName string) (func(entity *userM
|
||||||
}
|
}
|
||||||
|
|
||||||
func (u *UserRepository) Save(ctx context.Context, user *userModule.User) error {
|
func (u *UserRepository) Save(ctx context.Context, user *userModule.User) error {
|
||||||
repository := u.container.MustMake(contract.RepositoryKey).(contract.Repository[userModule.User, int64])
|
repositoryService := u.container.MustMake(contract.RepositoryKey).(contract.RepositoryService)
|
||||||
if err := repository.Save(ctx, userModule.UserKey, user); err != nil {
|
genericRepository := repositoryService.GetGenericRepositoryByKey(userModule.UserKey).(contract.GenericRepository[userModule.User, int64])
|
||||||
|
if err := genericRepository.Save(ctx, user); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (u *UserRepository) FindById(ctx context.Context, id int64) (*userModule.User, error) {
|
func (u *UserRepository) FindById(ctx context.Context, id int64) (*userModule.User, error) {
|
||||||
repository := u.container.MustMake(contract.RepositoryKey).(contract.Repository[userModule.User, int64])
|
repositoryService := u.container.MustMake(contract.RepositoryKey).(contract.RepositoryService)
|
||||||
byID, err := repository.FindByID(ctx, userModule.UserKey, id)
|
genericRepository := repositoryService.GetGenericRepositoryByKey(userModule.UserKey).(contract.GenericRepository[userModule.User, int64])
|
||||||
|
byID, err := genericRepository.FindByID(ctx, id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@ package user
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"encoding/json"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -24,3 +25,11 @@ type User struct {
|
||||||
Email string `gorm:"column:email;type:varchar(255);comment:邮箱;not null" json:"email"`
|
Email string `gorm:"column:email;type:varchar(255);comment:邮箱;not null" json:"email"`
|
||||||
CreatedAt time.Time `gorm:"column:created_at;type:datetime;comment:创建时间;not null;<-:create" json:"createdAt"`
|
CreatedAt time.Time `gorm:"column:created_at;type:datetime;comment:创建时间;not null;<-:create" json:"createdAt"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (u *User) MarshalBinary() ([]byte, error) {
|
||||||
|
return json.Marshal(u)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (u *User) UnmarshalBinary(data []byte) error {
|
||||||
|
return json.Unmarshal(data, u)
|
||||||
|
}
|
||||||
|
|
|
@ -4,7 +4,6 @@ import (
|
||||||
"context"
|
"context"
|
||||||
"github.com/Superdanda/hade/framework"
|
"github.com/Superdanda/hade/framework"
|
||||||
"github.com/Superdanda/hade/framework/contract"
|
"github.com/Superdanda/hade/framework/contract"
|
||||||
"github.com/Superdanda/hade/framework/provider/infrastructure"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type UserService struct {
|
type UserService struct {
|
||||||
|
@ -30,7 +29,7 @@ func (s *UserService) SaveUser(ctx context.Context, user *User) error {
|
||||||
|
|
||||||
func NewUserService(params ...interface{}) (interface{}, error) {
|
func NewUserService(params ...interface{}) (interface{}, error) {
|
||||||
container := params[0].(framework.Container)
|
container := params[0].(framework.Container)
|
||||||
infrastructureService := container.MustMake(contract.InfrastructureKey).(infrastructure.Service)
|
infrastructureService := container.MustMake(contract.InfrastructureKey).(contract.InfrastructureService)
|
||||||
ormRepository := infrastructureService.GetModuleOrmRepository(UserKey).(Repository)
|
ormRepository := infrastructureService.GetModuleOrmRepository(UserKey).(Repository)
|
||||||
return &UserService{container: container, repository: ormRepository}, nil
|
return &UserService{container: container, repository: ormRepository}, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
driver: memory
|
driver: redis
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
repository:
|
repository:
|
||||||
expire: 6h
|
expire: 6h
|
|
@ -4,4 +4,4 @@ write_timeout: 2s # 写超时
|
||||||
host: 10.10.103.131 # ip地址
|
host: 10.10.103.131 # ip地址
|
||||||
port: 6379 # 端口
|
port: 6379 # 端口
|
||||||
password: Worktask@Redis2023
|
password: Worktask@Redis2023
|
||||||
db: 0 #db
|
db: 6 #db
|
|
@ -2,11 +2,9 @@ timeout: 10s # 连接超时
|
||||||
read_timeout: 2s # 读超时
|
read_timeout: 2s # 读超时
|
||||||
write_timeout: 2s # 写超时
|
write_timeout: 2s # 写超时
|
||||||
|
|
||||||
write:
|
|
||||||
host: 10.10.103.131 # ip地址
|
host: 10.10.103.131 # ip地址
|
||||||
port: 6379 # 端口
|
port: 6379 # 端口
|
||||||
password: Worktask@Redis2023
|
password: Worktask@Redis2023
|
||||||
db: 0 #db
|
db: 6 #db
|
||||||
timeout: 10s # 连接超时
|
|
||||||
read_timeout: 2s # 读超时
|
|
||||||
write_timeout: 2s # 写超时
|
|
||||||
|
|
|
@ -30,7 +30,7 @@ func NewRedisCache(params ...interface{}) (interface{}, error) {
|
||||||
|
|
||||||
// 获取redis服务配置,并且实例化redis.Client
|
// 获取redis服务配置,并且实例化redis.Client
|
||||||
redisService := container.MustMake(contract.RedisKey).(contract.RedisService)
|
redisService := container.MustMake(contract.RedisKey).(contract.RedisService)
|
||||||
client, err := redisService.GetClient(redis.WithConfigPath("cache"))
|
client, err := redisService.GetClient(redis.WithConfigPath("redis"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -111,7 +111,8 @@ func (r *RedisCache) Set(ctx context.Context, key string, val string, timeout ti
|
||||||
|
|
||||||
// SetObj 设置某个key和对象到缓存, 对象必须实现 https://pkg.go.dev/encoding#BinaryMarshaler
|
// SetObj 设置某个key和对象到缓存, 对象必须实现 https://pkg.go.dev/encoding#BinaryMarshaler
|
||||||
func (r *RedisCache) SetObj(ctx context.Context, key string, val interface{}, timeout time.Duration) error {
|
func (r *RedisCache) SetObj(ctx context.Context, key string, val interface{}, timeout time.Duration) error {
|
||||||
return r.client.Set(ctx, key, val, timeout).Err()
|
set := r.client.Set(ctx, key, val, timeout)
|
||||||
|
return set.Err()
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetMany 设置多个key和值到缓存
|
// SetMany 设置多个key和值到缓存
|
||||||
|
|
|
@ -2,18 +2,18 @@ package infrastructure
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/Superdanda/hade/framework"
|
"github.com/Superdanda/hade/framework"
|
||||||
"github.com/Superdanda/hade/framework/contract"
|
|
||||||
_ "github.com/Superdanda/hade/framework/provider/repository"
|
_ "github.com/Superdanda/hade/framework/provider/repository"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Service struct {
|
type Service struct {
|
||||||
container framework.Container
|
container framework.Container
|
||||||
contract.InfrastructureService
|
|
||||||
ormRepositoryMap map[string]interface{}
|
ormRepositoryMap map[string]interface{}
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewInfrastructureService(params ...interface{}) (interface{}, error) {
|
func NewInfrastructureService(params ...interface{}) (interface{}, error) {
|
||||||
return &Service{container: params[0].(framework.Container)}, nil
|
infrastructureService := &Service{container: params[0].(framework.Container),
|
||||||
|
ormRepositoryMap: make(map[string]interface{})}
|
||||||
|
return infrastructureService, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (i *Service) GetModuleOrmRepository(moduleName string) interface{} {
|
func (i *Service) GetModuleOrmRepository(moduleName string) interface{} {
|
||||||
|
|
|
@ -16,7 +16,7 @@ func (r RepositoryProvider) Boot(container framework.Container) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r RepositoryProvider) IsDefer() bool {
|
func (r RepositoryProvider) IsDefer() bool {
|
||||||
return true
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r RepositoryProvider) Params(container framework.Container) []interface{} {
|
func (r RepositoryProvider) Params(container framework.Container) []interface{} {
|
||||||
|
|
|
@ -10,7 +10,7 @@ import (
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
func RegisterRepository[T any, ID comparable](service contract.RepositoryService, key string, ormRepository interface{}) {
|
func RegisterRepository[T any, ID comparable](service contract.RepositoryService, key string, ormRepository interface{}) *HadeGenericRepository[T, ID] {
|
||||||
container := service.GetContainer()
|
container := service.GetContainer()
|
||||||
cacheService := container.MustMake(contract.CacheKey).(contract.CacheService)
|
cacheService := container.MustMake(contract.CacheKey).(contract.CacheService)
|
||||||
configService := container.MustMake(contract.ConfigKey).(contract.Config)
|
configService := container.MustMake(contract.ConfigKey).(contract.Config)
|
||||||
|
@ -32,6 +32,7 @@ func RegisterRepository[T any, ID comparable](service contract.RepositoryService
|
||||||
ormRepository.(contract.OrmRepository[T, ID]),
|
ormRepository.(contract.OrmRepository[T, ID]),
|
||||||
)
|
)
|
||||||
service.GetGenericRepositoryMap()[key] = genericRepository
|
service.GetGenericRepositoryMap()[key] = genericRepository
|
||||||
|
return genericRepository
|
||||||
}
|
}
|
||||||
|
|
||||||
type HadeRepositoryService struct {
|
type HadeRepositoryService struct {
|
||||||
|
@ -41,9 +42,6 @@ type HadeRepositoryService struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewHadeRepositoryService(params ...interface{}) (interface{}, error) {
|
func NewHadeRepositoryService(params ...interface{}) (interface{}, error) {
|
||||||
if len(params) < 2 {
|
|
||||||
return nil, errors.New("insufficient parameters")
|
|
||||||
}
|
|
||||||
container, ok := params[0].(framework.Container)
|
container, ok := params[0].(framework.Container)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, errors.New("invalid container parameter")
|
return nil, errors.New("invalid container parameter")
|
||||||
|
|
|
@ -0,0 +1,197 @@
|
||||||
|
package request
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/json"
|
||||||
|
"io"
|
||||||
|
"net/http"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
// DefaultClient 默认定义一个60秒超时的请求
|
||||||
|
var DefaultClient = NewClient(60 * time.Second)
|
||||||
|
|
||||||
|
// Client 定义了一个包含 http.Client 的结构体,可以设置超时时间等参数
|
||||||
|
type Client struct {
|
||||||
|
httpClient *http.Client
|
||||||
|
}
|
||||||
|
|
||||||
|
type Headers = map[string]string
|
||||||
|
|
||||||
|
// NewClient 返回一个新的 Client 实例,可以设置请求超时时间
|
||||||
|
func NewClient(timeout time.Duration) *Client {
|
||||||
|
return &Client{
|
||||||
|
httpClient: &http.Client{
|
||||||
|
Timeout: timeout,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Request 封装了 HTTP 请求,返回响应的字节数组
|
||||||
|
func (c *Client) Request(method, url string, headers map[string]string, body io.Reader) ([]byte, error) {
|
||||||
|
req, err := http.NewRequest(method, url, body)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// 设置请求头
|
||||||
|
if headers != nil && len(headers) > 0 {
|
||||||
|
for key, value := range headers {
|
||||||
|
req.Header.Set(key, value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 发起请求
|
||||||
|
resp, err := DefaultClient.httpClient.Do(req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer func(Body io.ReadCloser) {
|
||||||
|
err := Body.Close()
|
||||||
|
if err != nil {
|
||||||
|
|
||||||
|
}
|
||||||
|
}(resp.Body)
|
||||||
|
|
||||||
|
// 读取响应体
|
||||||
|
return io.ReadAll(resp.Body)
|
||||||
|
}
|
||||||
|
|
||||||
|
// requestJSON 使用泛型,将响应解析为指定的类型 T
|
||||||
|
func requestJSON[T any](method, url string, headers map[string]string, body io.Reader) (T, error) {
|
||||||
|
var result T
|
||||||
|
// 发起请求,获取字节数组
|
||||||
|
data, err := DefaultClient.Request(method, url, headers, body)
|
||||||
|
if err != nil {
|
||||||
|
return result, err
|
||||||
|
}
|
||||||
|
// 解析 JSON 到指定类型
|
||||||
|
err = json.Unmarshal(data, &result)
|
||||||
|
return result, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get 快捷 GET 请求,返回字节数组
|
||||||
|
func Get(url string, headers Headers) ([]byte, error) {
|
||||||
|
return DefaultClient.Request(http.MethodGet, url, headers, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetJSON 快捷 GET 请求,使用泛型返回指定类型
|
||||||
|
func GetJSON[T any](url string, headers Headers) (T, error) {
|
||||||
|
return requestJSON[T](http.MethodGet, url, headers, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Post 快捷 POST 请求,返回字节数组
|
||||||
|
func Post(url string, headers Headers, body interface{}) ([]byte, error) {
|
||||||
|
jsonBody, err := JSONBody(body)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return DefaultClient.Request(http.MethodPost, url, headers, jsonBody)
|
||||||
|
}
|
||||||
|
|
||||||
|
// PostJSON 快捷 POST 请求,使用泛型返回指定类型
|
||||||
|
func PostJSON[T any](url string, headers Headers, body interface{}) (T, error) {
|
||||||
|
var result T
|
||||||
|
jsonBody, err := JSONBody(body)
|
||||||
|
if err != nil {
|
||||||
|
return result, err
|
||||||
|
}
|
||||||
|
return requestJSON[T](http.MethodPost, url, headers, jsonBody)
|
||||||
|
}
|
||||||
|
|
||||||
|
// JSONBody 接受任意结构体数据,将其序列化为 JSON 格式并作为请求体
|
||||||
|
func JSONBody(data interface{}) (*bytes.Buffer, error) {
|
||||||
|
jsonBytes, err := json.Marshal(data)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return bytes.NewBuffer(jsonBytes), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// RequestBuilder 定义了一个请求构建器,支持链式调用
|
||||||
|
type RequestBuilder struct {
|
||||||
|
client *Client
|
||||||
|
method string
|
||||||
|
url string
|
||||||
|
headers Headers
|
||||||
|
body io.Reader
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewRequest 创建一个新的 RequestBuilder 实例
|
||||||
|
func NewRequest() *RequestBuilder {
|
||||||
|
return &RequestBuilder{
|
||||||
|
client: DefaultClient,
|
||||||
|
headers: make(map[string]string),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithClient 设置自定义的 Client
|
||||||
|
func (rb *RequestBuilder) WithClient(client *Client) *RequestBuilder {
|
||||||
|
rb.client = client
|
||||||
|
return rb
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get 设置请求方法为 GET,并指定 URL
|
||||||
|
func (rb *RequestBuilder) Get(url string) *RequestBuilder {
|
||||||
|
rb.method = http.MethodGet
|
||||||
|
rb.url = url
|
||||||
|
return rb
|
||||||
|
}
|
||||||
|
|
||||||
|
// Post 设置请求方法为 POST,并指定 URL
|
||||||
|
func (rb *RequestBuilder) Post(url string) *RequestBuilder {
|
||||||
|
rb.method = http.MethodPost
|
||||||
|
rb.url = url
|
||||||
|
return rb
|
||||||
|
}
|
||||||
|
|
||||||
|
// Header 添加一个请求头
|
||||||
|
func (rb *RequestBuilder) Header(key, value string) *RequestBuilder {
|
||||||
|
rb.headers[key] = value
|
||||||
|
return rb
|
||||||
|
}
|
||||||
|
|
||||||
|
// Headers 批量添加请求头,接受任意数量的键值对
|
||||||
|
func (rb *RequestBuilder) Headers(headers map[string]string) *RequestBuilder {
|
||||||
|
for k, v := range headers {
|
||||||
|
rb.headers[k] = v
|
||||||
|
}
|
||||||
|
return rb
|
||||||
|
}
|
||||||
|
|
||||||
|
// JSONBody 设置请求体为 JSON 格式,接受任意可被 json.Marshal 的类型
|
||||||
|
func (rb *RequestBuilder) JSONBody(body interface{}) *RequestBuilder {
|
||||||
|
data, _ := json.Marshal(body)
|
||||||
|
rb.body = bytes.NewBuffer(data)
|
||||||
|
rb.Header("Content-Type", "application/json")
|
||||||
|
return rb
|
||||||
|
}
|
||||||
|
|
||||||
|
// Body 设置请求体,接受一个 io.Reader
|
||||||
|
func (rb *RequestBuilder) Body(body io.Reader) *RequestBuilder {
|
||||||
|
rb.body = body
|
||||||
|
return rb
|
||||||
|
}
|
||||||
|
|
||||||
|
// Do 发送请求,返回响应的字节数组
|
||||||
|
func (rb *RequestBuilder) Do() ([]byte, error) {
|
||||||
|
req, err := http.NewRequest(rb.method, rb.url, rb.body)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// 设置请求头
|
||||||
|
for key, value := range rb.headers {
|
||||||
|
req.Header.Set(key, value)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 发起请求
|
||||||
|
resp, err := rb.client.httpClient.Do(req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
|
||||||
|
// 读取响应体
|
||||||
|
return io.ReadAll(resp.Body)
|
||||||
|
}
|
Loading…
Reference in New Issue