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

article/2025/7/26 21:31:21

文章目录

  • 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文档的自动化生成,便于前后端协作。在下一篇文章中,我们将为搭建前端基础框架。



http://www.hkcw.cn/article/siLUsdMDEt.shtml

相关文章

CentOS-stream-9 Zabbix的安装与配置

一、Web环境搭建部署Zabbix时&#xff0c;选择合适的MariaDB、PHP和Nginx版本非常重要&#xff0c;以确保兼容性和最佳性能。以下是建议版本&#xff1a;Zabbix 6.4 MariaDB&#xff1a;官方文档推荐使用MariaDB 10.3或更高版本。对于CentOS Stream 9&#xff0c;建议使用Maria…

Scratch节日 | 龙舟比赛 | 端午节

端午节快乐&#xff01; 这款专为孩子们打造的Scratch游戏——《龙舟比赛》&#xff0c;让你在掌控龙舟的竞速中&#xff0c;沉浸式体验中华传统节日的魅力&#xff01; &#x1f3ae; 游戏亮点 节日氛围浓厚&#xff1a;化身龙舟选手&#xff0c;在波涛汹涌的河流中展开刺激竞…

抢占先机!品牌如何利用软文营销领跑内容营销赛道?

在当今这个信息爆炸的时代&#xff0c;内容营销已成为品牌与消费者沟通的重要桥梁。而软文营销&#xff0c;作为内容营销的一种重要形式&#xff0c;更是以其独特的魅力和高效的传播力&#xff0c;成为众多品牌抢占市场先机的利器。本文将深入探讨品牌如何利用软文营销领跑内容…

用谷歌云服务器可以做些什么?

解锁云端无限可能 在当今数字化飞速发展的时代&#xff0c;云计算技术犹如一股强大的动力&#xff0c;推动着各行各业的变革与创新。而谷歌云服务器&#xff0c;作为云计算领域的佼佼者&#xff0c;正以其卓越的性能和丰富的功能&#xff0c;为全球用户开启一扇通往全新数字世界…

Jetson Orin Nano - SONY imx415 camera驱动开发

目录 前言: 调试准备工作: 修改内核默认打印等级 一、imx415驱动开发 1、硬件接线 2、设备树修改 2.1 创建 tegra234-p3767-camera-p3768-imx415-C-4lane.dtsi 文件 2.2 tegra234-p3767-camera-p3768-imx415-C-4lane.dtsi 添加到设备树 2.3 编译设备树 3、imx415驱动…

Linux ClearOS yum无法使用解决备忘

前述 一个长期未使用的系统ClearOS Linux系统&#xff0c;属于CentOS家族&#xff0c;该系统用于网络设备。现在继续使用时&#xff0c;发现通过yum命令无法更新或下载软件。在这里记录一下解决该问题的过程。 问题 SSL证书问题 问题描述 问题现象如下所示&#xff0c;执行…

Bonjour

Bonjour 是苹果的一套零配置网络协议&#xff0c;用于发现局域网内的其他设备并进行通信&#xff0c;比如发现打印机、手机、电视等。 一句话&#xff1a;发现局域网其他设备和让其他设备发现。 Bonjour 可以完成的工作 IP 获取名称解析搜索服务 实际应用场景示例&#xff0…

day16 数组的常见操作和形状

目录 Numpy数组基础知识 数组的维度 数组的秩 数组的简单创建 zeros创建数组 ones创建数组 arange创建数组 数组的随机化创建 数组的遍历 数组的运算 数组的索引 一维数组索引 二维数组索引 三维数组索引 SHAP值的深入理解 知识点&#xff1a; numpy数组的创建&#xff1a;简单…

利用 Synonyms 中文近义词库调优 RAG 服务,基于 Ollama, DeepSeek R1, Langchain

目录 比对代码对比结果Synonyms 中文近义词 EmbeddingsHuggingFaceEmbeddings GitHub https://github.com/hailiang-wang/llm-get-started/tree/master/003_rag_langchain 本文介绍&#xff0c;在基于 RAG 服务实现问答的过程中&#xff0c;使用两种 Embeddings 模式下&#…

HTML 文件反编译指南:优化与学习网页代码

原文&#xff1a;HTML 文件反编译指南&#xff1a;优化与学习网页代码 | w3cschool笔记 (请勿将文章标记为付费&#xff01;&#xff01;&#xff01;&#xff09; 一、何为 HTML 文件反编译&#xff1f; 反编译 HTML 文件即将其从可读代码转换为更精简的形式。实际上&#…

在 ODROID-H3+ 上安装 Win11 系统

在 ODROID-H3 上安装 Windows 11 系统。 以下是完整的步骤&#xff0c;包括 BIOS 设置、U 盘制作、安装和驱动处理&#xff0c;全程不保留之前的系统数据。 ✅ 准备工作 1. 准备一个 ≥8GB 的 USB 启动盘 用另一台电脑制作 Windows 11 安装盘。 &#x1f449; 推荐工具&…

大话软工笔记—分离之业务与管理

1. 业务与管理的定义 业务&#xff0c;指企业为达成某个目标而进行的一系列活动&#xff08;业务指的是“做事”&#xff09;。 管理&#xff0c;为实现业务目标而进行的决策、计划、组织、指导、实施、控制的过程&#xff08;管理是“管事”&#xff0c;“事”指的是业务&am…

DeepSeek R1 模型小版本升级,DeepSeek-R1-0528都更新了哪些新特性?

DeepSeek-R1‑0528 技术剖析&#xff1a;思维链再进化&#xff0c;推理性能飙升 目录 版本概览深度思考能力再升级基准测试成绩功能与体验更新API 变动与示例模型开源与下载结语 版本概览 DeepSeek 团队今日发布 DeepSeek‑R1‑0528 —— 基于 DeepSeek V3 Base&#xff08;2…

请求分页中的内存分配

最小物理块数的确定 最小物理块数是确保进程能够正常运行所需的最少物理块数量。它是一个基础保障值&#xff0c;若分配的物理块数少于这个值&#xff0c;进程可能因无法完整加载必要页面而无法正常执行。例如&#xff0c;一个简单程序可能至少需要 3 个物理块来存放关键代码和…

痉挛性斜颈相关内容说明

一、颈部姿态的异常偏移​ 痉挛性斜颈会打破颈部原本自然笔直的状态&#xff0c;让颈部像被无形的力量牵引&#xff0c;出现不自主的歪斜、扭转。它就像打乱了颈部原本和谐的 “平衡游戏”&#xff0c;使得颈部姿态偏离正常&#xff0c;影响日常的体态与活动。​ 二、容易察觉…

【C++】位图

位图&#xff08;Bitmap&#xff09;是一种用于高效表示集合的数据结构&#xff0c;其核心思想是使用二进制位来指示某个元素是否存在。在位图中&#xff0c;每个元素对应一个二进制位&#xff0c;若该元素存在&#xff0c;则对应的位为1&#xff1b;若不存在&#xff0c;则为0…

初学c语言21(文件操作)

一.为什么使用文件 之前我们写的程序的数据都是存储到内存里面的&#xff0c;当程序结束时&#xff0c;内存回收&#xff0c;数据丢失&#xff0c; 再次运行程序时&#xff0c;就看不到上次程序的数据&#xff0c;如果要程序的数据一直保存得使用文件 二.文件 文件一般可以…

回车键为什么叫做“回车键”?

Enter键&#xff0c;也就是 “回车键”&#xff0c; 大家应该都不陌生。 可你知道它为什么叫“回车键”&#xff0c; 而不叫“输入键”、“登记键”嘛&#xff1f; 这要从机械英文打字机说起 因为电脑的普及&#xff0c;打字机几乎消失匿迹。 有的小伙伴们也许在小时候用过…

以太联Intellinet 分享:PoE 技术在医疗保健行业的创新应用

在当今科技飞速发展的时代&#xff0c;物联网(IoT)在医疗领域的应用正呈现出蓬勃兴起的态势。全球各地的医院以及老年生活中心纷纷引入物联网智能医疗解决方案&#xff0c;以实现设施运营的高效化与智能化。而在这背后&#xff0c;以太网供电(PoE)技术发挥着关键作用&#xff0…

大语言模型的技术原理与应用前景:从Transformer到ChatGPT

目录 摘要 1. 引言 2. Transformer架构核心原理 2.1 自注意力机制 2.2 位置编码 2.3 前馈神经网络 3. 从GPT到ChatGPT的演进 3.1 GPT系列模型架构 3.2 训练流程优化 4. 应用场景与案例分析 4.1 代码生成 4.2 文本摘要 4.3 问答系统 5. 挑战与未来方向 5.1 当前技…