服务的UBD架构示例
1 简介
三层架构(UBD)就是为了符合"高内聚,低耦合“思想、把各个功能模块划分为表示层(UI)、业务逻辑层(BLL)和数据访问层(DAL)三层架构。
在使用 Gin 实现三层架构的 Web 服务时,可以通过分层设计的方式,将功能模块划分为 表示层 (UI)、业务逻辑层 (BLL) 和 数据访问层 (DAL),从而实现高内聚、低耦合的架构。
这种设计不仅便于代码维护,还能提升可扩展性和可测试性。
2 三层架构设计
- 表示层 (UI)
负责处理 HTTP 请求和响应。
与客户端交互,通过调用业务逻辑层完成具体功能。
例如:路由控制器。
- 业务逻辑层 (BLL)
负责业务逻辑处理。
接收表示层的请求,完成业务校验和处理逻辑。
调用数据访问层进行数据存取。
- 数据访问层 (DAL)
与数据库直接交互。
负责执行 SQL 查询或通过 ORM 操作数据库。
3 go 的三层架构实现
目录结构.以下是一个示例的目录结构:
project/
├── controllers/ // 表示层
│ ├── user_controller.go
├── services/ // 业务逻辑层
│ ├── user_service.go
├── models/ // 数据访问层
│ ├── user_model.go
├── routes/ // 路由管理
│ ├── routes.go
├── main.go // 程序入口
-
- 数据访问层 (DAL)
负责定义数据模型和数据库操作逻辑,使用 GORM 操作数据库。
文件:models/user_model.go
package models
import (
"errors"
"gorm.io/gorm"
)
var db *gorm.DB // 假设已在 main.go 中初始化数据库连接
// User 模型
type User struct {
ID uint `gorm:"primaryKey"`
Name string `gorm:"type:varchar(100)"`
Email string `gorm:"type:varchar(100);unique"`
Age int `gorm:"type:int"`
}
// 查询用户
func GetUserByID(id uint) (*User, error) {
var user User
if err := db.First(&user, id).Error; err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return nil, nil // 用户不存在
}
return nil, err
}
return &user, nil
}
// 创建用户
func CreateUser(user *User) error {
return db.Create(user).Error
}
-
- 业务逻辑层 (BLL)
负责处理业务逻辑,如数据校验、业务规则等。
文件:services/user_service.go
package services
import (
"errors"
"myapp/models"
)
// 创建用户业务逻辑
func CreateUser(name, email string, age int) error {
// 检查邮箱是否已经存在
existingUser, _ := models.GetUserByID(1) // 示例:通过 Email 查询是否存在(未实现)
if existingUser != nil {
return errors.New("email already exists")
}
// 创建用户
user := &models.User{Name: name, Email: email, Age: age}
return models.CreateUser(user)
}
// 获取用户业务逻辑
func GetUser(id uint) (*models.User, error) {
user, err := models.GetUserByID(id)
if err != nil {
return nil, err
}
if user == nil {
return nil, errors.New("user not found")
}
return user, nil
}
-
- 表示层 (UI)
负责处理 HTTP 请求,调用业务逻辑层,并返回结果。
文件:controllers/user_controller.go
package controllers
import (
"net/http"
"strconv"
"github.com/gin-gonic/gin"
"myapp/services"
)
// 获取用户
func GetUser(c *gin.Context) {
idParam := c.Param("id")
id, err := strconv.Atoi(idParam)
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid user ID"})
return
}
user, err := services.GetUser(uint(id))
if err != nil {
c.JSON(http.StatusNotFound, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusOK, user)
}
// 创建用户
func CreateUser(c *gin.Context) {
var input struct {
Name string `json:"name" binding:"required"`
Email string `json:"email" binding:"required,email"`
Age int `json:"age" binding:"required"`
}
if err := c.ShouldBindJSON(&input); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
err := services.CreateUser(input.Name, input.Email, input.Age)
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusOK, gin.H{"message": "User created successfully"})
}
-
- 路由管理
将路由注册与处理逻辑分离,便于维护。
文件:routes/routes.go
package routes
import (
"github.com/gin-gonic/gin"
"myapp/controllers"
)
func RegisterRoutes(r *gin.Engine) {
userRoutes := r.Group("/users")
{
userRoutes.GET("/:id", controllers.GetUser) // 获取用户
userRoutes.POST("/", controllers.CreateUser) // 创建用户
}
}
-
- 主入口文件
启动 Gin 服务并注册路由。
文件:main.go
import (
"github.com/gin-gonic/gin"
"gorm.io/driver/mysql"
"gorm.io/gorm"
"myapp/routes"
)
func main() {
// 初始化数据库连接
dsn := "user:password@tcp(127.0.0.1:3306)/dbname?charset=utf8mb4&parseTime=True&loc=Local"
db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
if err != nil {
panic("failed to connect to database")
}
models.db = db // 给模型层赋值数据库连接
// 初始化 Gin 路由
r := gin.Default()
// 注册路由
routes.RegisterRoutes(r)
// 启动服务
r.Run(":8080")
}
4 架构特点分析
三层架构的优点,高内聚,低耦合
各层职责明确,业务逻辑与数据操作分离,方便扩展和维护。
- 易于测试
每层都可以独立进行单元测试(例如测试服务层的业务逻辑)。
- 可扩展性
方便添加新功能,如更换数据库或新增业务逻辑。
- 清晰的代码结构
逻辑清晰,便于团队协作。通过三层架构设计,可以构建一个安全、高效且易维护的 Web 服务。
- 点赞
- 收藏
- 关注作者
评论(0)