当前位置: 首页 > news >正文

AI书签管理工具开发全记录(五):后端服务搭建与API实现

文章目录

  • AI书签管理工具开发全记录(四):后端服务搭建与API实现
    • 前言 📝
    • 1. 后端框架选型 🛠️
    • 2. 项目结构优化 📁
    • 3. API路由设计 🧭
      • 分类管理
      • 书签管理
    • 4. 数据模型定义 💾
      • 分类模型(category.go)
      • 书签模型(bookmark.go)
    • 5. API服务实现 💻
      • 服务结构体定义(server.go)
      • 分类控制器实现
      • 书签控制器实现
    • 6. 服务启动集成 🚀
    • 7. Swagger文档集成 📚
    • 8. 测试运行 ✅
    • 总结 📚

AI书签管理工具开发全记录(四):后端服务搭建与API实现

前言 📝

在上一篇文章中,我们为项目添加了完善的日志系统,使用zap和lumberjack实现了高性能的日志记录、文件切割和归档功能。现在,我们将基于Gin框架搭建后端服务,实现书签和分类的增删改查(CRUD)操作,并通过Swagger生成API文档。

1. 后端框架选型 🛠️

在Go语言中,有许多优秀的Web框架可供选择,如Gin、Echo、Beego等。经过调研,本项目选择了Gin框架,因为它具有以下特点:

  • 高性能:基于HttpRouter,性能接近原生HTTP
  • 轻量级:代码简洁,易于上手
  • 丰富的中间件:支持各种中间件,如日志、恢复、认证等
  • 良好的社区支持:拥有活跃的社区和丰富的插件

此外,我们还将使用Swagger来自动生成API文档,方便前后端协作。

# 安装依赖
go get github.com/gin-gonic/gin
go get github.com/swaggo/gin-swagger
go get github.com/swaggo/files

2. 项目结构优化 📁

在开始编写API代码之前,我们先对项目结构进行优化,使其更清晰合理:

aibookmark/
├── cmd/             # 命令行入口
├── internal/        # 内部包
│   ├── api/         # API路由和控制器
│   ├── models/      # 数据模型
│   ├── server/      # 服务启动逻辑
│   ├── utils/       # 工具函数(配置、数据库等)
│   └── log/         # 日志系统
├── docs/            # Swagger文档
└── go.mod

3. API路由设计 🧭

我们设计了以下API路由,用于管理书签和分类:

分类管理

  • POST /api/categories:创建分类
  • GET /api/categories:获取分类列表(分页)
  • GET /api/categories/:id:获取单个分类
  • PUT /api/categories/:id:更新分类
  • DELETE /api/categories/:id:删除分类

书签管理

  • POST /api/bookmarks:创建书签
  • GET /api/bookmarks:获取书签列表(分页,支持按分类过滤)
  • GET /api/bookmarks/:id:获取单个书签
  • PUT /api/bookmarks/:id:更新书签
  • DELETE /api/bookmarks/:id:删除书签

4. 数据模型定义 💾

internal/models包中,我们定义了两个核心模型:分类(Category)和书签(Bookmark)。

分类模型(category.go)

package modelsimport "time"type Category struct {ID          uint   `gorm:"primaryKey"`Name        string `gorm:"unique;not null"`Description stringCreatedAt   time.Time `gorm:"default:CURRENT_TIMESTAMP"`
}

书签模型(bookmark.go)

package modelsimport "time"type Bookmark struct {ID          uint   `gorm:"primaryKey"`Title       string `gorm:"not null"`URL         string `gorm:"not null"`Description stringCategoryID  uintCategory    Category  `gorm:"foreignKey:CategoryID"`CreatedAt   time.Time `gorm:"default:CURRENT_TIMESTAMP"`UpdatedAt   time.Time `gorm:"default:CURRENT_TIMESTAMP"`
}

同时,我们定义了用于请求和响应的结构体(bookmark_request.go和category_request.go),以便于参数绑定和序列化。

5. API服务实现 💻

internal/api包中,我们实现了API的路由和控制器逻辑。

服务结构体定义(server.go)

package apiimport ("github.com/ciclebyte/aibookmark/internal/models""github.com/gin-gonic/gin"swaggerFiles "github.com/swaggo/files"ginSwagger "github.com/swaggo/gin-swagger""gorm.io/gorm"
)type Server struct {db     *gorm.DBrouter *gin.Engine
}func NewServer(db *gorm.DB) *Server {server := &Server{db: db}router := gin.Default()// 添加Swagger路由router.GET("/swagger/*any", ginSwagger.WrapHandler(swaggerFiles.Handler))// API路由分组api := router.Group("/api"){category := api.Group("/categories"){category.POST("", server.createCategory)category.GET("", server.listCategories)category.GET("/:id", server.getCategory)category.PUT("/:id", server.updateCategory)category.DELETE("/:id", server.deleteCategory)}bookmark := api.Group("/bookmarks"){bookmark.POST("", server.createBookmark)bookmark.GET("", server.listBookmarks)bookmark.GET("/:id", server.getBookmark)bookmark.PUT("/:id", server.updateBookmark)bookmark.DELETE("/:id", server.deleteBookmark)}}server.router = routerreturn server
}func (s *Server) Start(address string) error {return s.router.Run(address)
}

分类控制器实现

以创建分类为例,我们实现了以下逻辑:

// CreateCategory 创建新分类
func (s *Server) createCategory(c *gin.Context) {var req models.CreateCategoryRequestif err := c.ShouldBindJSON(&req); err != nil {c.JSON(400, gin.H{"error": "Invalid request data"})return}// 检查分类名称是否已存在var existingCategory models.Categoryif err := s.db.Where("name = ?", req.Name).First(&existingCategory).Error; err == nil {c.JSON(409, gin.H{"error": "Category with this name already exists"})return}category := models.Category{Name:        req.Name,Description: req.Description,}if err := s.db.Create(&category).Error; err != nil {c.JSON(500, gin.H{"error": "Failed to create category"})return}c.JSON(201, category)
}

书签控制器实现

以获取书签列表为例,我们实现了分页和按分类过滤的功能:

// ListBookmarks 获取书签列表
func (s *Server) listBookmarks(c *gin.Context) {var bookmarks []models.BookmarkpageStr := c.DefaultQuery("page", "1")sizeStr := c.DefaultQuery("size", "10")categoryID := c.Query("category_id")page, err := strconv.Atoi(pageStr)if err != nil || page < 1 {page = 1}size, err := strconv.Atoi(sizeStr)if err != nil || size < 1 {size = 10}query := s.db.Model(&models.Bookmark{})if categoryID != "" {query = query.Where("category_id = ?", categoryID)}offset := (page - 1) * sizeif err := query.Offset(offset).Limit(size).Preload("Category").Find(&bookmarks).Error; err != nil {c.JSON(500, gin.H{"error": "Failed to fetch bookmarks"})return}c.JSON(200, gin.H{"data":  bookmarks,"page":  page,"size":  size,"total": len(bookmarks),})
}

6. 服务启动集成 🚀

internal/server/server.go中,我们集成了数据库初始化和服务启动逻辑:

package serverimport ("github.com/ciclebyte/aibookmark/internal/api""github.com/ciclebyte/aibookmark/internal/models""github.com/ciclebyte/aibookmark/internal/utils"
)func StartServer(port string) error {db, err := utils.GetGormDB()if err != nil {return err}// 自动迁移数据库err = db.AutoMigrate(&models.Category{}, &models.Bookmark{})if err != nil {return err}server := api.NewServer(db)return server.Start(":" + port)
}

cmd/root.go中,我们添加了serve命令来启动服务:

// serveCmd 代表 serve 命令
var serveCmd = &cobra.Command{Use:   "serve",Short: "启动API服务",Run: func(cmd *cobra.Command, args []string) {port, _ := cmd.Flags().GetString("port")startGinServer(port)},
}func startGinServer(port string) {if err := server.StartServer(port); err != nil {log.Error("Failed to start server",zap.String("operation", "server start"),zap.Error(err))os.Exit(1)}
}

7. Swagger文档集成 📚

我们使用Swagger注解来生成API文档。在每个API方法上方,我们添加了相应的Swagger注释,例如:

// CreateCategory godoc
// @Summary 创建分类
// @Description 创建新的书签分类
// @Tags categories
// @Accept json
// @Produce json
// @Param category body models.CreateCategoryRequest true "分类信息"
// @Success 201 {object} models.Category
// @Failure 400 {object} map[string]string
// @Failure 500 {object} map[string]string
// @Router /api/categories [post]
func (s *Server) createCategory(c *gin.Context) {// ...
}

然后,在项目根目录下运行以下命令生成Swagger文档:

swag init -g internal/api/api.go

生成的文档位于docs目录,我们可以通过/swagger/index.html访问API文档。

8. 测试运行 ✅

启动服务:

go run main.go serve -p 8080

访问Swagger文档:

http://localhost:8080/swagger/index.html

通过Swagger UI,我们可以方便地测试各个API接口。
image.png

也可以访问doc.json
image.png

可以在apifox中导入doc.json,方便的对api服务进行测试
image.png

image.png

总结 📚

本文详细介绍了如何基于Gin框架搭建后端API服务,并实现书签和分类的CRUD功能。通过Swagger集成,我们实现了API文档的自动化生成,便于前后端协作。在下一篇文章中,我们将为搭建前端基础框架。


相关文章:

  • (18)混合云架构部署
  • SpringBoot整合Flowable【08】- 前后端如何交互
  • 数据分类分级的实践与反思:源自数据分析、治理与安全交叉视角的洞察
  • AWS WebRTC:获取ICE服务地址(part 3):STUN服务和TURN服务的作用
  • 深入剖析HBase架构
  • 若依项目AI 助手代码解析
  • ImBatch 7.6.3 中文版 - 高效图片批量处理工具
  • [Javascript进阶]JSON.stringify与JSON.parse详解
  • 超级对话3:大跨界且大综合的学问融智学应用场景述评(不同第三方的回应)之三
  • 酒店管理系统设计与实现
  • 数据交易场景的数据质量评估
  • muduo库的初步认识和基本使用,创建一个简单查询单词服务系统
  • 【C++】STL详解(四)---Stack和Queue
  • ansible自动化playbook简单实践
  • MSTNet:用于糖尿病视网膜病变分类的多尺度空间感知 Transformer 与多实例学习方法|文献速递-深度学习医疗AI最新文献
  • C++高级编程深度指南:内存管理、安全函数、递归、错误处理、命令行参数解析、可变参数应用与未定义行为规避
  • 面试题 08.08. 有重复字符串的排列组合【 力扣(LeetCode) 】
  • 低功耗架构突破:STM32H750 与 SD NAND (存储芯片)如何延长手环续航至 14 天
  • OCC笔记:BRepMesh_IncrementalMesh的使用
  • 用Git管理你的服务器配置文件与自动化脚本:版本控制、变更追溯、团队协作与安全回滚的运维之道
  • 在那些网站可以接兼职做/怎么提高百度搜索排名
  • 网页设计有限公司/百度seo不正当竞争秒收
  • 杭州定制网站公司/哪家公司网站做得好
  • 男男做暧暧视频网站/seo短视频发布页
  • 邯郸网站建设包括哪些/直销的八大课程
  • 做网站什么什么/十大收益最好的自媒体平台