Go Web项目 接口开发全流程

news2024/11/18 5:47:12

风离不摆烂学习日志 Day5 — Go Web项目 接口开发全流程

接上篇地址 Web项目学习之项目结构

routes包分析

InitRoutes

package routes

import (
	"fmt"
	"github.com/gin-gonic/gin"
	"go-web-mini/common"
	"go-web-mini/config"
	"go-web-mini/middleware"
	"time"
)

// 初始化
func InitRoutes() *gin.Engine {
	//设置模式
	gin.SetMode(config.Conf.System.Mode)

	// 创建带有默认中间件的路由:
	// 日志与恢复中间件
	r := gin.Default()
	// 创建不带中间件的路由:
	// r := gin.New()
	// r.Use(gin.Recovery())

	// 启用限流中间件
	// 默认每50毫秒填充一个令牌,最多填充200个
	fillInterval := time.Duration(config.Conf.RateLimit.FillInterval)
	capacity := config.Conf.RateLimit.Capacity
	r.Use(middleware.RateLimitMiddleware(time.Millisecond*fillInterval, capacity))

	// 启用全局跨域中间件
	r.Use(middleware.CORSMiddleware())

	// 启用操作日志中间件
	r.Use(middleware.OperationLogMiddleware())

	// 初始化JWT认证中间件
	authMiddleware, err := middleware.InitAuth()
	if err != nil {
		common.Log.Panicf("初始化JWT中间件失败:%v", err)
		panic(fmt.Sprintf("初始化JWT中间件失败:%v", err))
	}

	// 路由分组
	apiGroup := r.Group("/" + config.Conf.System.UrlPathPrefix)

	// 注册路由
	InitBaseRoutes(apiGroup, authMiddleware)         // 注册基础路由, 不需要jwt认证中间件,不需要casbin中间件
	InitUserRoutes(apiGroup, authMiddleware)         // 注册用户路由, jwt认证中间件,casbin鉴权中间件
	InitRoleRoutes(apiGroup, authMiddleware)         // 注册角色路由, jwt认证中间件,casbin鉴权中间件
	InitMenuRoutes(apiGroup, authMiddleware)         // 注册菜单路由, jwt认证中间件,casbin鉴权中间件
	InitApiRoutes(apiGroup, authMiddleware)          // 注册接口路由, jwt认证中间件,casbin鉴权中间件
	InitOperationLogRoutes(apiGroup, authMiddleware) // 注册操作日志路由, jwt认证中间件,casbin鉴权中间件

	common.Log.Info("初始化路由完成!")
	return r
}

设置开发模式(debug/release/test,正式版改为release) => 加载中间件 => 注册路由

base_routes.go

package routes

import (
	jwt "github.com/appleboy/gin-jwt/v2"
	"github.com/gin-gonic/gin"
)

// 注册基础路由
func InitBaseRoutes(r *gin.RouterGroup, authMiddleware *jwt.GinJWTMiddleware) gin.IRoutes {
	router := r.Group("/base")
	{
		// 登录登出刷新token无需鉴权
		router.POST("/login", authMiddleware.LoginHandler)
		router.POST("/logout", authMiddleware.LogoutHandler)
		router.POST("/refreshToken", authMiddleware.RefreshHandler)
	}
	return r
}

menu_routes.go

package routes

import (
	jwt "github.com/appleboy/gin-jwt/v2"
	"github.com/gin-gonic/gin"
	"go-web-mini/controller"
	"go-web-mini/middleware"
)

func InitMenuRoutes(r *gin.RouterGroup, authMiddleware *jwt.GinJWTMiddleware) gin.IRoutes {
	menuController := controller.NewMenuController()
	router := r.Group("/menu")
	// 开启jwt认证中间件
	router.Use(authMiddleware.MiddlewareFunc())
	// 开启casbin鉴权中间件
	router.Use(middleware.CasbinMiddleware())
	{
		router.GET("/tree", menuController.GetMenuTree)
		router.GET("/list", menuController.GetMenus)
		router.POST("/create", menuController.CreateMenu)
		router.PATCH("/update/:menuId", menuController.UpdateMenuById)
		router.DELETE("/delete/batch", menuController.BatchDeleteMenuByIds)
		router.GET("/access/list/:userId", menuController.GetUserMenusByUserId)
		router.GET("/access/tree/:userId", menuController.GetUserMenuTreeByUserId)
	}

	return r
}

函数格式:

1. func 函数名(入参1 参数类型,入参2 参数类型) 返回类型

2. func 函数名(入参1 参数类型,入参2 参数类型)(返回值1 返回类型)

controller包分析

user_controller.go

大致流程:

定义接口

定义结构体 结构体里包含持久层的CRUD

然后实现这些接口 返回出去

对比Java 的 SpringBoot框架 Gin 没有自动注入 我们需要自己写构造函数 来初始化持久层 Controller层

type UserController struct {
	UserRepository repository.IUserRepository
}

// 构造函数
func NewUserController() IUserController {
	userRepository := repository.NewUserRepository()
	userController := UserController{UserRepository: userRepository}
	return userController
}

然后上层调用这个构造函数来完成初始化

image-20221123111701951

repository包分析

大体流程与controller层逻辑一致

type UserRepository struct { //结构体为空
}

内存缓存go-cache

用户信息缓存 避免频繁读取数据库

地址: https://github.com/patrickmn/go-cache
一个基于内存的key-value存储/缓存项目,类似于Memcached,并且可选择定期的垃圾回收,适合单机程序。代码量不多,也不难懂。

"github.com/patrickmn/go-cache"

// 当前用户信息缓存,避免频繁获取数据库  这里逻辑跟Redis差不多 增 删 改 时更新缓存 查优先走缓存 
var userInfoCache = cache.New(24*time.Hour, 48*time.Hour)

model包分析

package model

import "gorm.io/gorm"

type User struct {
	gorm.Model
	Username     string  `gorm:"type:varchar(20);not null;unique" json:"username"`
	Password     string  `gorm:"size:255;not null" json:"password"`
	Mobile       string  `gorm:"type:varchar(11);not null;unique" json:"mobile"`
	Avatar       string  `gorm:"type:varchar(255)" json:"avatar"`
	Nickname     string  `gorm:"type:varchar(20)" json:"nickname"`
	Introduction *string `gorm:"type:varchar(255)" json:"introduction"`
	Status       uint    `gorm:"type:tinyint(1);default:1;comment:'1正常, 2禁用'" json:"status"`
	Creator      string  `gorm:"type:varchar(20);" json:"creator"`
	Roles        []*Role `gorm:"many2many:user_roles" json:"roles"`
}

这里结构体 类似于Java中对象

需要首字母大写 指定 转 json 后的类型 对应长字段 类型存储为 指针 即取地址

dto包分析

user_dto.go

package dto

import "go-web-mini/model"

// 返回给前端的当前用户信息
type UserInfoDto struct {
	ID           uint          `json:"id"`
	Username     string        `json:"username"`
	Mobile       string        `json:"mobile"`
	Avatar       string        `json:"avatar"`
	Nickname     string        `json:"nickname"`
	Introduction string        `json:"introduction"`
	Roles        []*model.Role `json:"roles"`
}

func ToUserInfoDto(user model.User) UserInfoDto {
	return UserInfoDto{
		ID:           user.ID,
		Username:     user.Username,
		Mobile:       user.Mobile,
		Avatar:       user.Avatar,
		Nickname:     user.Nickname,
		Introduction: *user.Introduction,
		Roles:        user.Roles,
	}
}

// 返回给前端的用户列表
type UsersDto struct {
	ID           uint   `json:"ID"`
	Username     string `json:"username"`
	Mobile       string `json:"mobile"`
	Avatar       string `json:"avatar"`
	Nickname     string `json:"nickname"`
	Introduction string `json:"introduction"`
	Status       uint   `json:"status"`
	Creator      string `json:"creator"`
	RoleIds      []uint `json:"roleIds"`
}

func ToUsersDto(userList []*model.User) []UsersDto {
	var users []UsersDto
	for _, user := range userList {
		userDto := UsersDto{
			ID:           user.ID,
			Username:     user.Username,
			Mobile:       user.Mobile,
			Avatar:       user.Avatar,
			Nickname:     user.Nickname,
			Introduction: *user.Introduction,
			Status:       user.Status,
			Creator:      user.Creator,
		}
		roleIds := make([]uint, 0)
		for _, role := range user.Roles {
			roleIds = append(roleIds, role.ID)
		}
		userDto.RoleIds = roleIds
		users = append(users, userDto)
	}

	return users
}

当我们不需要将数据库的数据全部返回出去的时候 或者需要做字段转换 拼接 等操作 皆可在dto层完成


response包分析

封装统一返回格式

package response

import (
	"github.com/gin-gonic/gin"
	"net/http"
)

// 返回前端
func Response(c *gin.Context, httpStatus int, code int, data gin.H, message string) {
	c.JSON(httpStatus, gin.H{"code": code, "data": data, "message": message})
}

// 返回前端-成功
func Success(c *gin.Context, data gin.H, message string) {
	Response(c, http.StatusOK, 200, data, message)
}

// 返回前端-失败
func Fail(c *gin.Context, data gin.H, message string) {
	Response(c, http.StatusBadRequest, 400, data, message)
}

config 包分析

这里结构体对应 config.yml 配置文件中对应的配置

type MysqlConfig struct { //mysql配置
	Username    string `mapstructure:"username" json:"username"`
	Password    string `mapstructure:"password" json:"password"`
	Database    string `mapstructure:"database" json:"database"`
	Host        string `mapstructure:"host" json:"host"`
	Port        int    `mapstructure:"port" json:"port"`
	Query       string `mapstructure:"query" json:"query"`
	LogMode     bool   `mapstructure:"log-mode" json:"logMode"`
	TablePrefix string `mapstructure:"table-prefix" json:"tablePrefix"`
	Charset     string `mapstructure:"charset" json:"charset"`
	Collation   string `mapstructure:"collation" json:"collation"`
}

在一个结构体里包含 各个配置的集合 mysql jwt...

type config struct {
	System    *SystemConfig    `mapstructure:"system" json:"system"`
	Logs      *LogsConfig      `mapstructure:"logs" json:"logs"`
	Mysql     *MysqlConfig     `mapstructure:"mysql" json:"mysql"`
	Casbin    *CasbinConfig    `mapstructure:"casbin" json:"casbin"`
	Jwt       *JwtConfig       `mapstructure:"jwt" json:"jwt"`
	RateLimit *RateLimitConfig `mapstructure:"rate-limit" json:"rateLimit"`
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/29952.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Charles断点

1、断点测试的含义 1.1、断点(英语:Breakpoint)是程序中为了调试而故意停止或者暂停的地方。 调试设置断点:可以让程序运行到该行程序时停住,借此观察程序到断点位置时,其变量、寄存器、I/O等相关的变量内…

mysql InnoDB 索引结构

目录 前言 1. InnoDB常见的索引 2. B树索引 2.1 二分查找法 2.2 二叉查找树 2.3 平衡二叉树 2.4 B树索引 2.5 B树索引 2.5.1 聚集索引 2.5.2 非聚集索引 2.5.3 聚集索引与非聚集索引区别 前言 索引的本质是让mysql以最高效、扫描行数最少的方式找到需要的数据。索引…

Paper写作怎么了解题目方面的重要性?

我们常听到:Paper的好坏,从选择题目开始!可见选择Paper题目的重要性。这正是我们今天要探讨的内容。 We often hear that the quality of paper starts from choosing the topic!This shows the importance of selecting paper topics.This i…

数字信号处理-9-离散余弦变换

1 波形合成 假定给一系列振幅和一系列频率,要求构建一个信号,此信号是这些频率元素的和。这样的操作就是合成 def synthesize(amps, fs, ts):"""amps 振幅数组fs 频率数组ts 采样时间点"""# ts 和 fs 的外积&#xff0c…

Spring Cloud(十三):Spring 扩展

Spring扩展点 Bean的生命周期中的BeanPostProcessor扩展点Spring扩展点梳理 Spring扩展点应用场景 整合Nacos 服务注册 ApplicationListener扩展场景——监听容器中发布的事件Lifecycle Nacos 发布订阅 & Eureka 服务启动、同步、剔除Lifecycle扩展场景——管理具有启动、停…

JSP快速入门

目录 1、jsp简述 2、JSP快速入门 2.1、搭建环境 2.2、导入JSP页面 2.3、编写代码 2.4、启动测试 3、JSP原理 4、JSP脚本 4.1、JSP脚本的分类 4.2、案例 4.2.1、需求 4.2.2、实现 ​编辑 4.2.3、测试 ​编辑4.3、JSP缺点 5、JSP语法 5.1、JSP页面的基本结构…

【每日一题Day36】LC1742盒子中小球的最大数量 | 哈希表 找规律

盒子中小球的最大数量【LC1742】 You are working in a ball factory where you have n balls numbered from lowLimit up to highLimit inclusive (i.e., n highLimit - lowLimit 1), and an infinite number of boxes numbered from 1 to infinity. Your job at this facto…

[附源码]java毕业设计养老院管理系统

项目运行 环境配置: Jdk1.8 Tomcat7.0 Mysql HBuilderX(Webstorm也行) Eclispe(IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持)。 项目技术: SSM mybatis Maven Vue 等等组成,B/S模式 M…

C++ 语言学习 day10 复习(2)

1.友元 的三种形式 /*********** 友元 ************ * ①全局函数做友元 * ②类做友元 * ③类成员函数做友元 * **************************/ 代码&#xff1a; #include <iostream> #include <string> using namespace std;/* ③类函数友元 : 程序规则{ 自上…

Charles下载抓包基本流程

一、Charles官网下载链接&#xff1a; https://www.charlesproxy.com/download/ 二、抓包步骤&#xff1a; 1、安装Charles&#xff0c;并打开 2、电脑设置代理端口&#xff1a; 打开charles->Proxy->Proxy Settings,设置代理端口&#xff0c;如图所示 3、手机设置代…

Day10--配置uni-app的开发环境

1.啥子是ui-app呢&#xff1f; 1》官方介绍&#xff1a; 2》博主介绍 ************************************************************************************************************** 2.开发工具建议使用HBuilder X *************************************************…

BSA/HSA表面修饰二甘醇酐,人血清白蛋白HSA、牛血清白蛋白BSA偶联二甘醇酐

BSA作用&#xff1a; BSA一般做为稳定剂被用于限制酶或者修饰酶的保存溶液和反应液中&#xff0c;因为有些酶在低浓度下不稳定或活性低。加入BSA后&#xff0c;它可能起到“保护”或“载体”作用&#xff0c;不少酶类添加 BSA后能使其活性大幅度提高。不需要加BSA的酶加入BSA一…

【时序预测-SVM】基于鲸鱼算法优化支持向量机SVM实现时序数据预测附matlab代码

✅作者简介&#xff1a;热爱科研的Matlab仿真开发者&#xff0c;修心和技术同步精进&#xff0c;matlab项目合作可私信。 &#x1f34e;个人主页&#xff1a;Matlab科研工作室 &#x1f34a;个人信条&#xff1a;格物致知。 更多Matlab仿真内容点击&#x1f447; 智能优化算法 …

【数据结构】二叉树详解(上篇)

&#x1f9d1;‍&#x1f4bb;作者&#xff1a; 情话0.0 &#x1f4dd;专栏&#xff1a;《数据结构》 &#x1f466;个人简介&#xff1a;一名双非编程菜鸟&#xff0c;在这里分享自己的编程学习笔记&#xff0c;欢迎大家的指正与点赞&#xff0c;谢谢&#xff01; 二叉树&…

18 【Redux Toolkit】

18 【Redux Toolkit】 上边的案例我们一直在使用Redux核心库来使用Redux&#xff0c;除了Redux核心库外Redux还为我们提供了一种使用Redux的方式——Redux Toolkit。它的名字起的非常直白&#xff0c;Redux工具包&#xff0c;简称RTK。RTK可以帮助我们处理使用Redux过程中的重…

ABTest样本量计算

A/B 测试一般是比较实验组和对照组在某些指标上是否存在差异&#xff0c;当然更多时候是看实验组相比对照组某个指标表现是否更好。 这样的对比在统计学上叫做两样本假设检验&#xff0c;即实验组和对照组为两样本&#xff0c;假设检验的原假设Ho&#xff1a;实验组和对照组无…

Springboot 整合 JWT + Redis 实现双Token 校验Demo(简单实现)

一、新建一个SpringBoot 项目&#xff0c;springboot项目创建过程详见 mac idea 创建 springboot 项目_JAVA&#xff24;WangJing的博客-CSDN博客_mac idea创建springboot项目 二、SpringBoot 整合使用 Rdis SpringBoot 项目 添加 redis配置_JAVA&#xff24;WangJing的博客…

Linux内存映射函数mmap与匿名内存块

学习系列&#xff1a;《APUE14.8》《CSAPP9.8.4》 1 总结 memory-mapped io可以将文件映射到内存中的buffer&#xff0c;当我们从buffer读写数据时&#xff0c;其实操作的是对应文件中的数据。这样可以达到不使用READ/WRITE的IO操作。mmap也可以直接映射匿名内存块&#xff0c…

零信任对企业安全防护能起到什么作用?

随着网络攻击的不断演变&#xff0c;变得更加普遍和复杂&#xff0c;企业正在寻找一种基于身份的网络安全新方法。这些策略和解决方案旨在保护企业内的所有人和机器&#xff0c;并用于检测和防止身份驱动的违规行为。 企业很容易被感染&#xff0c;但问题在于如何找到解决方案。…

基于花朵授粉算法的无线传感器网络部署优化附Matlab代码

✅作者简介&#xff1a;热爱科研的Matlab仿真开发者&#xff0c;修心和技术同步精进&#xff0c;matlab项目合作可私信。 &#x1f34e;个人主页&#xff1a;Matlab科研工作室 &#x1f34a;个人信条&#xff1a;格物致知。 更多Matlab仿真内容点击&#x1f447; 智能优化算法 …