This commit is contained in:
2025-08-27 22:19:19 +08:00
parent 4031277a91
commit 5051aea55c
93 changed files with 2025 additions and 1168 deletions

View File

@@ -6,10 +6,9 @@
```
internal/shared/validator/
├── validator.go # HTTP请求验证器主逻辑
├── validator.go # 统一校验器主逻辑(包含所有功能)
├── custom_validators.go # 自定义验证器实现
├── translations.go # 中文翻译
├── business.go # 业务逻辑验证接口
└── README.md # 使用说明
```
@@ -22,9 +21,9 @@ internal/shared/validator/
- 统一的错误响应格式
### 2. 业务逻辑验证
- 独立的业务验证
- 可在任何地方调用的验证方法
- 独立的业务验证方法,可在任何地方调用
- 丰富的预定义验证规则
- 与标签验证使用相同的校验逻辑
### 3. 自定义验证规则
- 手机号验证 (`phone`)
@@ -106,35 +105,32 @@ type ProductCommand struct {
### 3. 业务逻辑验证
在Service中使用
在Service中使用统一的校验方法
```go
import "tyapi-server/internal/shared/validator"
type UserService struct {
businessValidator *validator.BusinessValidator
}
func NewUserService() *UserService {
return &UserService{
businessValidator: validator.NewBusinessValidator(),
}
// 不再需要单独的businessValidator
}
func (s *UserService) ValidateUserData(phone, password string) error {
// 验证手机号
if err := s.businessValidator.ValidatePhone(phone); err != nil {
// 直接使用包级别的校验方法
if err := validator.ValidatePhone(phone); err != nil {
return fmt.Errorf("手机号验证失败: %w", err)
}
// 验证密码强度
if err := s.businessValidator.ValidatePassword(password); err != nil {
if err := validator.ValidatePassword(password); err != nil {
return fmt.Errorf("密码验证失败: %w", err)
}
// 验证结构体
userData := UserData{Phone: phone, Password: password}
if err := s.businessValidator.ValidateStruct(userData); err != nil {
// 也可以使用结构体验证
userData := struct {
Phone string `validate:"phone"`
Password string `validate:"strong_password"`
}{Phone: phone, Password: password}
if err := validator.GetGlobalValidator().Struct(userData); err != nil {
return fmt.Errorf("用户数据验证失败: %w", err)
}
@@ -142,13 +138,12 @@ func (s *UserService) ValidateUserData(phone, password string) error {
}
func (s *UserService) ValidateEnterpriseInfo(code, idCard string) error {
// 验证统一社会信用代码
if err := s.businessValidator.ValidateSocialCreditCode(code); err != nil {
// 直接使用包级别的校验方法
if err := validator.ValidateSocialCreditCode(code); err != nil {
return err
}
// 验证身份证号
if err := s.businessValidator.ValidateIDCard(idCard); err != nil {
if err := validator.ValidateIDCard(idCard); err != nil {
return err
}
@@ -156,6 +151,27 @@ func (s *UserService) ValidateEnterpriseInfo(code, idCard string) error {
}
```
### 4. 处理器中的验证
在API处理器中可以直接使用结构体验证
```go
// 在 flxg5a3b_processor.go 中
func ProcessFLXG5A3BRequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) {
var paramsDto dto.FLXG5A3BReq
if err := json.Unmarshal(params, &paramsDto); err != nil {
return nil, errors.Join(processors.ErrSystem, err)
}
// 使用统一的校验器验证
if err := deps.Validator.ValidateStruct(paramsDto); err != nil {
return nil, errors.Join(processors.ErrInvalidParam, err)
}
// ... 继续业务逻辑
}
```
## 🔧 可用的验证规则
### 标准验证规则
@@ -208,23 +224,33 @@ fx.Provide(
),
```
业务验证器可以在需要时创建:
```go
bv := validator.NewBusinessValidator()
```
## 📝 最佳实践
1. **DTO验证**: 在DTO中使用binding标签进行声明式验证
2. **业务验证**: 在业务逻辑中使用BusinessValidator进行程序化验证
3. **错误处理**: 验证错误会自动返回统一格式的HTTP响应
4. **性能**: 验证器实例可以复用,建议在依赖注入中管理
2. **业务验证**: 在业务逻辑中直接使用 `validator.ValidateXXX()` 方法
3. **统一性**: 所有校验都使用同一个校验器实例,确保规则一致
4. **错误处理**: 验证错误会自动返回统一格式的HTTP响应
## 🧪 测试示例
参考 `examples/validator_usage.go` 文件中的完整使用示例。
```go
// 测试自定义校验规则
func TestCustomValidators(t *testing.T) {
validator.InitGlobalValidator()
// 测试手机号验证
err := validator.ValidatePhone("13800138000")
if err != nil {
t.Errorf("有效手机号验证失败: %v", err)
}
err = validator.ValidatePhone("12345")
if err == nil {
t.Error("无效手机号应该验证失败")
}
}
```
---
这个验证器包提供了完整的验证解决方案既可以用于HTTP请求的自动验证也可以在业务逻辑中进行程序化验证确保数据的完整性和正确性。
这个验证器包现在提供了完整的统一解决方案既可以用于HTTP请求的自动验证也可以在业务逻辑中进行程序化验证确保数据的完整性和正确性。