性能优化

This commit is contained in:
xiangheng
2024-07-10 15:36:00 +08:00
parent 69fe1613fa
commit 8f42f5d33b
13 changed files with 139 additions and 75 deletions

View File

@@ -1,6 +1,7 @@
{ {
"cSpell.words": [ "cSpell.words": [
"dcloudio", "dcloudio",
"endregion",
"excelize", "excelize",
"fontsize", "fontsize",
"freetype", "freetype",
@@ -9,10 +10,13 @@
"gorm", "gorm",
"Infof", "Infof",
"Inno", "Inno",
"Itoa",
"jinzhu", "jinzhu",
"mapstructure", "mapstructure",
"oneof", "oneof",
"rmvb", "rmvb",
"strconv",
"struct",
"uniapp", "uniapp",
"Warnf", "Warnf",
"webp", "webp",

View File

@@ -2,16 +2,20 @@ package {{{ .ModuleName }}}
import ( import (
"net/http" "net/http"
"strconv"
"time" "time"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"x_admin/core/request" "x_admin/core/request"
"x_admin/core/response" "x_admin/core/response"
"x_admin/util" "x_admin/util"
"x_admin/util/excel" "x_admin/util/excel"
"golang.org/x/sync/singleflight"
) )
type {{{ title (toCamelCase .ModuleName) }}}Handler struct {} type {{{ title (toCamelCase .ModuleName) }}}Handler struct {
requestGroup singleflight.Group
}
// @Summary {{{ .FunctionName }}}列表 // @Summary {{{ .FunctionName }}}列表
// @Tags {{{ .ModuleName }}}-{{{ .FunctionName }}} // @Tags {{{ .ModuleName }}}-{{{ .FunctionName }}}
@@ -31,7 +35,7 @@ type {{{ title (toCamelCase .ModuleName) }}}Handler struct {}
{{{- end }}} {{{- end }}}
//@Success 200 {object} {{{getPageResp (title (toCamelCase .EntityName)) }}} "成功" //@Success 200 {object} {{{getPageResp (title (toCamelCase .EntityName)) }}} "成功"
//@Router /api/admin/{{{ .ModuleName }}}/list [get] //@Router /api/admin/{{{ .ModuleName }}}/list [get]
func (hd {{{ title (toCamelCase .ModuleName) }}}Handler) List(c *gin.Context) { func (hd *{{{ title (toCamelCase .ModuleName) }}}Handler) List(c *gin.Context) {
var page request.PageReq var page request.PageReq
var listReq {{{ title (toCamelCase .EntityName) }}}ListReq var listReq {{{ title (toCamelCase .EntityName) }}}ListReq
if response.IsFailWithResp(c, util.VerifyUtil.VerifyQuery(c, &page)) { if response.IsFailWithResp(c, util.VerifyUtil.VerifyQuery(c, &page)) {
@@ -59,7 +63,7 @@ func (hd {{{ title (toCamelCase .ModuleName) }}}Handler) List(c *gin.Context) {
{{{- end }}} {{{- end }}}
// @Success 200 {object} response.Response{ data=[]{{{ title (toCamelCase .EntityName) }}}Resp} "成功" // @Success 200 {object} response.Response{ data=[]{{{ title (toCamelCase .EntityName) }}}Resp} "成功"
// @Router /api/admin/{{{ .ModuleName }}}/listAll [get] // @Router /api/admin/{{{ .ModuleName }}}/listAll [get]
func (hd {{{ title (toCamelCase .ModuleName) }}}Handler) ListAll(c *gin.Context) { func (hd *{{{ title (toCamelCase .ModuleName) }}}Handler) ListAll(c *gin.Context) {
var listReq {{{ title (toCamelCase .EntityName) }}}ListReq var listReq {{{ title (toCamelCase .EntityName) }}}ListReq
if response.IsFailWithResp(c, util.VerifyUtil.VerifyQuery(c, &listReq)) { if response.IsFailWithResp(c, util.VerifyUtil.VerifyQuery(c, &listReq)) {
return return
@@ -79,12 +83,16 @@ func (hd {{{ title (toCamelCase .ModuleName) }}}Handler) ListAll(c *gin.Context
{{{- end }}} {{{- end }}}
// @Success 200 {object} response.Response{ data={{{ title (toCamelCase .EntityName) }}}Resp} "成功" // @Success 200 {object} response.Response{ data={{{ title (toCamelCase .EntityName) }}}Resp} "成功"
// @Router /api/admin/{{{ .ModuleName }}}/detail [get] // @Router /api/admin/{{{ .ModuleName }}}/detail [get]
func (hd {{{ title (toCamelCase .ModuleName) }}}Handler) Detail(c *gin.Context) { func (hd *{{{ title (toCamelCase .ModuleName) }}}Handler) Detail(c *gin.Context) {
var detailReq {{{ title (toCamelCase .EntityName) }}}DetailReq var detailReq {{{ title (toCamelCase .EntityName) }}}DetailReq
if response.IsFailWithResp(c, util.VerifyUtil.VerifyQuery(c, &detailReq)) { if response.IsFailWithResp(c, util.VerifyUtil.VerifyQuery(c, &detailReq)) {
return return
} }
res, err := {{{ title (toCamelCase .EntityName) }}}Service.Detail(detailReq.{{{ title (toCamelCase .PrimaryKey) }}}) res, err, _ := hd.requestGroup.Do("{{{ title (toCamelCase .EntityName) }}}:Detail:"+strconv.Itoa(detailReq.{{{ title (toCamelCase .PrimaryKey) }}}), func() (any, error) {
v, err := {{{ title (toCamelCase .EntityName) }}}Service.Detail(detailReq.{{{ title (toCamelCase .PrimaryKey) }}})
return v, err
})
response.CheckAndRespWithData(c, res, err) response.CheckAndRespWithData(c, res, err)
} }
@@ -100,12 +108,13 @@ func (hd {{{ title (toCamelCase .ModuleName) }}}Handler) Detail(c *gin.Context)
{{{- end }}} {{{- end }}}
// @Success 200 {object} response.Response "成功" // @Success 200 {object} response.Response "成功"
// @Router /api/admin/{{{ .ModuleName }}}/add [post] // @Router /api/admin/{{{ .ModuleName }}}/add [post]
func (hd {{{ title (toCamelCase .ModuleName) }}}Handler) Add(c *gin.Context) { func (hd *{{{ title (toCamelCase .ModuleName) }}}Handler) Add(c *gin.Context) {
var addReq {{{ title (toCamelCase .EntityName) }}}AddReq var addReq {{{ title (toCamelCase .EntityName) }}}AddReq
if response.IsFailWithResp(c, util.VerifyUtil.VerifyJSON(c, &addReq)) { if response.IsFailWithResp(c, util.VerifyUtil.VerifyJSON(c, &addReq)) {
return return
} }
response.CheckAndResp(c, {{{ title (toCamelCase .EntityName) }}}Service.Add(addReq)) createId, e := {{{ title (toCamelCase .EntityName) }}}Service.Add(addReq)
response.CheckAndRespWithData(c,createId, e)
} }
// @Summary {{{ .FunctionName }}}编辑 // @Summary {{{ .FunctionName }}}编辑
// @Tags {{{ .ModuleName }}}-{{{ .FunctionName }}} // @Tags {{{ .ModuleName }}}-{{{ .FunctionName }}}
@@ -118,12 +127,12 @@ func (hd {{{ title (toCamelCase .ModuleName) }}}Handler) Add(c *gin.Context) {
{{{- end }}} {{{- end }}}
// @Success 200 {object} response.Response "成功" // @Success 200 {object} response.Response "成功"
// @Router /api/admin/{{{ .ModuleName }}}/edit [post] // @Router /api/admin/{{{ .ModuleName }}}/edit [post]
func (hd {{{ title (toCamelCase .ModuleName) }}}Handler) Edit(c *gin.Context) { func (hd *{{{ title (toCamelCase .ModuleName) }}}Handler) Edit(c *gin.Context) {
var editReq {{{ title (toCamelCase .EntityName) }}}EditReq var editReq {{{ title (toCamelCase .EntityName) }}}EditReq
if response.IsFailWithResp(c, util.VerifyUtil.VerifyJSON(c, &editReq)) { if response.IsFailWithResp(c, util.VerifyUtil.VerifyJSON(c, &editReq)) {
return return
} }
response.CheckAndResp(c, {{{ title (toCamelCase .EntityName) }}}Service.Edit(editReq)) response.CheckAndRespWithData(c,editReq.{{{ title (toCamelCase .PrimaryKey) }}}, {{{ title (toCamelCase .EntityName) }}}Service.Edit(editReq))
} }
// @Summary {{{ .FunctionName }}}删除 // @Summary {{{ .FunctionName }}}删除
// @Tags {{{ .ModuleName }}}-{{{ .FunctionName }}} // @Tags {{{ .ModuleName }}}-{{{ .FunctionName }}}
@@ -136,7 +145,7 @@ func (hd {{{ title (toCamelCase .ModuleName) }}}Handler) Edit(c *gin.Context) {
{{{- end }}} {{{- end }}}
// @Success 200 {object} response.Response "成功" // @Success 200 {object} response.Response "成功"
// @Router /api/admin/{{{ .ModuleName }}}/del [post] // @Router /api/admin/{{{ .ModuleName }}}/del [post]
func (hd {{{ title (toCamelCase .ModuleName) }}}Handler) Del(c *gin.Context) { func (hd *{{{ title (toCamelCase .ModuleName) }}}Handler) Del(c *gin.Context) {
var delReq {{{ title (toCamelCase .EntityName) }}}DelReq var delReq {{{ title (toCamelCase .EntityName) }}}DelReq
if response.IsFailWithResp(c, util.VerifyUtil.VerifyJSON(c, &delReq)) { if response.IsFailWithResp(c, util.VerifyUtil.VerifyJSON(c, &delReq)) {
return return
@@ -161,7 +170,7 @@ func (hd {{{ title (toCamelCase .ModuleName) }}}Handler) Del(c *gin.Context) {
{{{- end }}} {{{- end }}}
{{{- end }}} {{{- end }}}
// @Router /api/admin/{{{ .ModuleName }}}/ExportFile [get] // @Router /api/admin/{{{ .ModuleName }}}/ExportFile [get]
func (hd {{{ title (toCamelCase .ModuleName) }}}Handler) ExportFile(c *gin.Context) { func (hd *{{{ title (toCamelCase .ModuleName) }}}Handler) ExportFile(c *gin.Context) {
var listReq {{{ title (toCamelCase .EntityName) }}}ListReq var listReq {{{ title (toCamelCase .EntityName) }}}ListReq
if response.IsFailWithResp(c, util.VerifyUtil.VerifyQuery(c, &listReq)) { if response.IsFailWithResp(c, util.VerifyUtil.VerifyQuery(c, &listReq)) {
return return
@@ -183,7 +192,7 @@ func (hd {{{ title (toCamelCase .ModuleName) }}}Handler) ExportFile(c *gin.Cont
// @Tags {{{ .ModuleName }}}-{{{ .FunctionName }}} // @Tags {{{ .ModuleName }}}-{{{ .FunctionName }}}
// @Produce json // @Produce json
// @Router /api/admin/{{{ .ModuleName }}}/ImportFile [post] // @Router /api/admin/{{{ .ModuleName }}}/ImportFile [post]
func (hd {{{ title (toCamelCase .ModuleName) }}}Handler) ImportFile(c *gin.Context) { func (hd *{{{ title (toCamelCase .ModuleName) }}}Handler) ImportFile(c *gin.Context) {
file, _, err := c.Request.FormFile("file") file, _, err := c.Request.FormFile("file")
if err != nil { if err != nil {
c.String(http.StatusInternalServerError, "文件不存在") c.String(http.StatusInternalServerError, "文件不存在")

View File

@@ -51,5 +51,5 @@ func {{{ title (toCamelCase .ModuleName) }}}Route(rg *gin.RouterGroup) {
r.POST("/{{{ .ModuleName }}}/edit",middleware.RecordLog("{{{ .FunctionName }}}编辑"), handle.Edit) r.POST("/{{{ .ModuleName }}}/edit",middleware.RecordLog("{{{ .FunctionName }}}编辑"), handle.Edit)
r.POST("/{{{ .ModuleName }}}/del", middleware.RecordLog("{{{ .FunctionName }}}删除"), handle.Del) r.POST("/{{{ .ModuleName }}}/del", middleware.RecordLog("{{{ .FunctionName }}}删除"), handle.Del)
r.GET("/{{{ .ModuleName }}}/ExportFile", middleware.RecordLog("{{{ .FunctionName }}}导出"), handle.ExportFile) r.GET("/{{{ .ModuleName }}}/ExportFile", middleware.RecordLog("{{{ .FunctionName }}}导出"), handle.ExportFile)
r.POST("/{{{ .ModuleName }}}/ImportFile", handle.ImportFile) r.POST("/{{{ .ModuleName }}}/ImportFile",middleware.RecordLog("{{{ .FunctionName }}}导入"), handle.ImportFile)
} }

View File

@@ -27,13 +27,13 @@ func (service {{{ toCamelCase .EntityName }}}Service) SetCache(obj model.{{{ tit
if e != nil { if e != nil {
return false return false
} }
return util.RedisUtil.Set("{{{ toCamelCase .EntityName }}}:id:"+strconv.Itoa(obj.Id), str, 3600) return util.RedisUtil.HSet("{{{ toCamelCase .EntityName }}}",strconv.Itoa(obj.{{{ title (toCamelCase .PrimaryKey) }}}), str, 3600)
} }
// 获取缓存 // 获取缓存
func (service {{{ toCamelCase .EntityName }}}Service) GetCache(id int) (model.{{{ title (toCamelCase .EntityName) }}}, error) { func (service {{{ toCamelCase .EntityName }}}Service) GetCache(key int) (model.{{{ title (toCamelCase .EntityName) }}}, error) {
var obj model.{{{ title (toCamelCase .EntityName) }}} var obj model.{{{ title (toCamelCase .EntityName) }}}
str := util.RedisUtil.Get("{{{ toCamelCase .EntityName }}}:id:" + strconv.Itoa(id)) str := util.RedisUtil.HGet("{{{ toCamelCase .EntityName }}}", strconv.Itoa(key))
if str == "" { if str == "" {
return obj, errors.New("获取缓存失败") return obj, errors.New("获取缓存失败")
} }
@@ -46,7 +46,7 @@ func (service {{{ toCamelCase .EntityName }}}Service) GetCache(id int) (model.{{
} }
// 删除缓存 // 删除缓存
func (service {{{ toCamelCase .EntityName }}}Service) RemoveCache(obj model.{{{ title (toCamelCase .EntityName) }}}) bool { func (service {{{ toCamelCase .EntityName }}}Service) RemoveCache(obj model.{{{ title (toCamelCase .EntityName) }}}) bool {
return util.RedisUtil.Del("{{{ toCamelCase .EntityName }}}:id:" + strconv.Itoa(obj.Id)) return util.RedisUtil.HDel("{{{ toCamelCase .EntityName }}}", strconv.Itoa(obj.{{{ title (toCamelCase .PrimaryKey) }}}))
} }
@@ -124,11 +124,11 @@ func (service {{{ toCamelCase .EntityName }}}Service) ListAll(listReq {{{ title
} }
// Detail {{{ .FunctionName }}}详情 // Detail {{{ .FunctionName }}}详情
func (service {{{ toCamelCase .EntityName }}}Service) Detail(id int) (res {{{ title (toCamelCase .EntityName) }}}Resp, e error) { func (service {{{ toCamelCase .EntityName }}}Service) Detail({{{ title (toCamelCase .PrimaryKey) }}} int) (res {{{ title (toCamelCase .EntityName) }}}Resp, e error) {
var obj, err = service.GetCache(id) var obj, err = service.GetCache({{{ title (toCamelCase .PrimaryKey) }}})
// var obj model.{{{ title (toCamelCase .EntityName) }}} // var obj model.{{{ title (toCamelCase .EntityName) }}}
if err != nil { if err != nil {
err := service.db.Where("{{{ $.PrimaryKey }}} = ?{{{ if contains .AllFields "is_delete" }}} AND is_delete = ?{{{ end }}}", id{{{ if contains .AllFields "is_delete" }}}, 0{{{ end }}}).Limit(1).First(&obj).Error err := service.db.Where("{{{ $.PrimaryKey }}} = ?{{{ if contains .AllFields "is_delete" }}} AND is_delete = ?{{{ end }}}", {{{ title (toCamelCase .PrimaryKey) }}}{{{ if contains .AllFields "is_delete" }}}, 0{{{ end }}}).Limit(1).First(&obj).Error
if e = response.CheckErrDBNotRecord(err, "数据不存在!"); e != nil { if e = response.CheckErrDBNotRecord(err, "数据不存在!"); e != nil {
return return
} }
@@ -149,15 +149,16 @@ func (service {{{ toCamelCase .EntityName }}}Service) Detail(id int) (res {{{ ti
} }
// Add {{{ .FunctionName }}}新增 // Add {{{ .FunctionName }}}新增
func (service {{{ toCamelCase .EntityName }}}Service) Add(addReq {{{ title (toCamelCase .EntityName) }}}AddReq) (e error) { func (service {{{ toCamelCase .EntityName }}}Service) Add(addReq {{{ title (toCamelCase .EntityName) }}}AddReq) (createId int,e error) {
var obj model.{{{ title (toCamelCase .EntityName) }}} var obj model.{{{ title (toCamelCase .EntityName) }}}
response.Copy(&obj, addReq) response.Copy(&obj, addReq)
err := service.db.Create(&obj).Error err := service.db.Create(&obj).Error
e = response.CheckMysqlErr(err) e = response.CheckMysqlErr(err)
if e != nil { if e != nil {
return e return 0,e
} }
service.SetCache(obj) service.SetCache(obj)
createId = obj.{{{ title (toCamelCase .PrimaryKey) }}}
e = response.CheckErr(err, "添加失败") e = response.CheckErr(err, "添加失败")
return return
} }
@@ -165,7 +166,7 @@ func (service {{{ toCamelCase .EntityName }}}Service) Add(addReq {{{ title (toCa
// Edit {{{ .FunctionName }}}编辑 // Edit {{{ .FunctionName }}}编辑
func (service {{{ toCamelCase .EntityName }}}Service) Edit(editReq {{{ title (toCamelCase .EntityName) }}}EditReq) (e error) { func (service {{{ toCamelCase .EntityName }}}Service) Edit(editReq {{{ title (toCamelCase .EntityName) }}}EditReq) (e error) {
var obj model.{{{ title (toCamelCase .EntityName) }}} var obj model.{{{ title (toCamelCase .EntityName) }}}
err := service.db.Where("{{{ $.PrimaryKey }}} = ?{{{ if contains .AllFields "is_delete" }}} AND is_delete = ?{{{ end }}}", editReq.Id{{{ if contains .AllFields "is_delete" }}}, 0{{{ end }}}).Limit(1).First(&obj).Error err := service.db.Where("{{{ $.PrimaryKey }}} = ?{{{ if contains .AllFields "is_delete" }}} AND is_delete = ?{{{ end }}}", editReq.{{{ title (toCamelCase .PrimaryKey) }}}{{{ if contains .AllFields "is_delete" }}}, 0{{{ end }}}).Limit(1).First(&obj).Error
// //
if e = response.CheckErrDBNotRecord(err, "数据不存在!"); e != nil { if e = response.CheckErrDBNotRecord(err, "数据不存在!"); e != nil {
return return
@@ -182,9 +183,9 @@ func (service {{{ toCamelCase .EntityName }}}Service) Edit(editReq {{{ title (to
} }
// Del {{{ .FunctionName }}}删除 // Del {{{ .FunctionName }}}删除
func (service {{{ toCamelCase .EntityName }}}Service) Del(id int) (e error) { func (service {{{ toCamelCase .EntityName }}}Service) Del({{{ title (toCamelCase .PrimaryKey) }}} int) (e error) {
var obj model.{{{ title (toCamelCase .EntityName) }}} var obj model.{{{ title (toCamelCase .EntityName) }}}
err := service.db.Where("{{{ $.PrimaryKey }}} = ?{{{ if contains .AllFields "is_delete" }}} AND is_delete = ?{{{ end }}}", id{{{ if contains .AllFields "is_delete" }}}, 0{{{ end }}}).Limit(1).First(&obj).Error err := service.db.Where("{{{ $.PrimaryKey }}} = ?{{{ if contains .AllFields "is_delete" }}} AND is_delete = ?{{{ end }}}", {{{ title (toCamelCase .PrimaryKey) }}}{{{ if contains .AllFields "is_delete" }}}, 0{{{ end }}}).Limit(1).First(&obj).Error
// //
if e = response.CheckErrDBNotRecord(err, "数据不存在!"); e != nil { if e = response.CheckErrDBNotRecord(err, "数据不存在!"); e != nil {
return return

View File

@@ -1,8 +1,8 @@
package monitor_project package monitor_project
import ( import (
"fmt"
"net/http" "net/http"
"strconv"
"time" "time"
"x_admin/core/request" "x_admin/core/request"
"x_admin/core/response" "x_admin/core/response"
@@ -13,7 +13,9 @@ import (
"golang.org/x/sync/singleflight" "golang.org/x/sync/singleflight"
) )
type MonitorProjectHandler struct{} type MonitorProjectHandler struct {
requestGroup singleflight.Group
}
// @Summary 错误项目列表 // @Summary 错误项目列表
// @Tags monitor_project-错误项目 // @Tags monitor_project-错误项目
@@ -27,7 +29,7 @@ type MonitorProjectHandler struct{}
// @Success 200 {object} response.Response{data=response.PageResp{lists=[]MonitorProjectResp}} "成功" // @Success 200 {object} response.Response{data=response.PageResp{lists=[]MonitorProjectResp}} "成功"
// @Failure 400 {object} string "请求错误" // @Failure 400 {object} string "请求错误"
// @Router /api/admin/monitor_project/list [get] // @Router /api/admin/monitor_project/list [get]
func (hd MonitorProjectHandler) List(c *gin.Context) { func (hd *MonitorProjectHandler) List(c *gin.Context) {
var page request.PageReq var page request.PageReq
var listReq MonitorProjectListReq var listReq MonitorProjectListReq
if response.IsFailWithResp(c, util.VerifyUtil.VerifyQuery(c, &page)) { if response.IsFailWithResp(c, util.VerifyUtil.VerifyQuery(c, &page)) {
@@ -45,14 +47,14 @@ func (hd MonitorProjectHandler) List(c *gin.Context) {
// @Produce json // @Produce json
// @Success 200 {object} response.Response{data=[]MonitorProjectResp} "成功" // @Success 200 {object} response.Response{data=[]MonitorProjectResp} "成功"
// @Router /api/admin/monitor_project/listAll [get] // @Router /api/admin/monitor_project/listAll [get]
var sg singleflight.Group // var sg singleflight.Group
func (hd MonitorProjectHandler) ListAll(c *gin.Context) { func (hd *MonitorProjectHandler) ListAll(c *gin.Context) {
res, err, shared := sg.Do("key", func() (any, error) { res, err, _ := hd.requestGroup.Do("monitor_project:listAll", func() (any, error) {
v, err := Service.ListAll() v, err := Service.ListAll()
return v, err return v, err
}) })
fmt.Printf("v: %v, shared: %v\n", res, shared) // fmt.Printf("v: %v, shared: %v\n", res, shared)
// var listReq MonitorProjectListReq // var listReq MonitorProjectListReq
// if response.IsFailWithResp(c, util.VerifyUtil.VerifyQuery(c, &listReq)) { // if response.IsFailWithResp(c, util.VerifyUtil.VerifyQuery(c, &listReq)) {
@@ -68,12 +70,16 @@ func (hd MonitorProjectHandler) ListAll(c *gin.Context) {
// @Param id query int false "项目id." // @Param id query int false "项目id."
// @Success 200 {object} response.Response{data=MonitorProjectResp} "成功" // @Success 200 {object} response.Response{data=MonitorProjectResp} "成功"
// @Router /api/admin/monitor_project/detail [get] // @Router /api/admin/monitor_project/detail [get]
func (hd MonitorProjectHandler) Detail(c *gin.Context) { func (hd *MonitorProjectHandler) Detail(c *gin.Context) {
var detailReq MonitorProjectDetailReq var detailReq MonitorProjectDetailReq
if response.IsFailWithResp(c, util.VerifyUtil.VerifyQuery(c, &detailReq)) { if response.IsFailWithResp(c, util.VerifyUtil.VerifyQuery(c, &detailReq)) {
return return
} }
res, err := Service.Detail(detailReq.Id) res, err, _ := hd.requestGroup.Do("monitor_project:Detail:"+strconv.Itoa(detailReq.Id), func() (any, error) {
v, err := Service.Detail(detailReq.Id)
return v, err
})
// fmt.Printf("v: %v, shared: %v\n", res, shared)
response.CheckAndRespWithData(c, res, err) response.CheckAndRespWithData(c, res, err)
} }
@@ -86,12 +92,13 @@ func (hd MonitorProjectHandler) Detail(c *gin.Context) {
// @Param projectType body string false "项目类型go java web node php 等." // @Param projectType body string false "项目类型go java web node php 等."
// @Success 200 {object} response.Response "成功" // @Success 200 {object} response.Response "成功"
// @Router /api/admin/monitor_project/add [post] // @Router /api/admin/monitor_project/add [post]
func (hd MonitorProjectHandler) Add(c *gin.Context) { func (hd *MonitorProjectHandler) Add(c *gin.Context) {
var addReq MonitorProjectAddReq var addReq MonitorProjectAddReq
if response.IsFailWithResp(c, util.VerifyUtil.VerifyJSON(c, &addReq)) { if response.IsFailWithResp(c, util.VerifyUtil.VerifyJSON(c, &addReq)) {
return return
} }
response.CheckAndResp(c, Service.Add(addReq)) createId, e := Service.Add(addReq)
response.CheckAndRespWithData(c, createId, e)
} }
// @Summary 错误项目编辑 // @Summary 错误项目编辑
@@ -104,12 +111,12 @@ func (hd MonitorProjectHandler) Add(c *gin.Context) {
// @Param projectType body string false "项目类型go java web node php 等." // @Param projectType body string false "项目类型go java web node php 等."
// @Success 200 {object} response.Response "成功" // @Success 200 {object} response.Response "成功"
// @Router /api/admin/monitor_project/edit [post] // @Router /api/admin/monitor_project/edit [post]
func (hd MonitorProjectHandler) Edit(c *gin.Context) { func (hd *MonitorProjectHandler) Edit(c *gin.Context) {
var editReq MonitorProjectEditReq var editReq MonitorProjectEditReq
if response.IsFailWithResp(c, util.VerifyUtil.VerifyJSON(c, &editReq)) { if response.IsFailWithResp(c, util.VerifyUtil.VerifyJSON(c, &editReq)) {
return return
} }
response.CheckAndResp(c, Service.Edit(editReq)) response.CheckAndRespWithData(c, editReq.Id, Service.Edit(editReq))
} }
// @Summary 错误项目删除 // @Summary 错误项目删除
@@ -119,7 +126,7 @@ func (hd MonitorProjectHandler) Edit(c *gin.Context) {
// @Param id body int false "项目id." // @Param id body int false "项目id."
// @Success 200 {object} response.Response "成功" // @Success 200 {object} response.Response "成功"
// @Router /api/admin/monitor_project/del [post] // @Router /api/admin/monitor_project/del [post]
func (hd MonitorProjectHandler) Del(c *gin.Context) { func (hd *MonitorProjectHandler) Del(c *gin.Context) {
var delReq MonitorProjectDelReq var delReq MonitorProjectDelReq
if response.IsFailWithResp(c, util.VerifyUtil.VerifyJSON(c, &delReq)) { if response.IsFailWithResp(c, util.VerifyUtil.VerifyJSON(c, &delReq)) {
return return
@@ -135,7 +142,7 @@ func (hd MonitorProjectHandler) Del(c *gin.Context) {
// @Param projectName query string false "项目名称." // @Param projectName query string false "项目名称."
// @Param projectType query string false "项目类型go java web node php 等." // @Param projectType query string false "项目类型go java web node php 等."
// @Router /api/admin/monitor_project/ExportFile [get] // @Router /api/admin/monitor_project/ExportFile [get]
func (hd MonitorProjectHandler) ExportFile(c *gin.Context) { func (hd *MonitorProjectHandler) ExportFile(c *gin.Context) {
var listReq MonitorProjectListReq var listReq MonitorProjectListReq
if response.IsFailWithResp(c, util.VerifyUtil.VerifyQuery(c, &listReq)) { if response.IsFailWithResp(c, util.VerifyUtil.VerifyQuery(c, &listReq)) {
return return
@@ -156,7 +163,7 @@ func (hd MonitorProjectHandler) ExportFile(c *gin.Context) {
// @Summary 错误项目导入 // @Summary 错误项目导入
// @Tags monitor_project-错误项目 // @Tags monitor_project-错误项目
// @Produce json // @Produce json
func (hd MonitorProjectHandler) ImportFile(c *gin.Context) { func (hd *MonitorProjectHandler) ImportFile(c *gin.Context) {
file, _, err := c.Request.FormFile("file") file, _, err := c.Request.FormFile("file")
if err != nil { if err != nil {
c.String(http.StatusInternalServerError, "文件不存在") c.String(http.StatusInternalServerError, "文件不存在")
@@ -169,9 +176,9 @@ func (hd MonitorProjectHandler) ImportFile(c *gin.Context) {
c.String(http.StatusInternalServerError, err.Error()) c.String(http.StatusInternalServerError, err.Error())
return return
} }
for _, t := range importList { // for _, t := range importList {
fmt.Printf("%#v", t) // fmt.Printf("%#v", t)
} // }
err = Service.ImportFile(importList) err = Service.ImportFile(importList)
response.CheckAndResp(c, err) response.CheckAndResp(c, err)
} }

View File

@@ -41,13 +41,13 @@ func (service monitorProjectService) SetCache(obj model.MonitorProject) bool {
if e != nil { if e != nil {
return false return false
} }
return util.RedisUtil.Set("MonitorProject:id:"+strconv.Itoa(obj.Id), str, 3600) return util.RedisUtil.HSet("MonitorProject", strconv.Itoa(obj.Id), str, 3600)
} }
// 获取缓存 // 获取缓存
func (service monitorProjectService) GetCache(id int) (model.MonitorProject, error) { func (service monitorProjectService) GetCache(id int) (model.MonitorProject, error) {
var obj model.MonitorProject var obj model.MonitorProject
str := util.RedisUtil.Get("MonitorProject:id:" + strconv.Itoa(id)) str := util.RedisUtil.HGet("MonitorProject", strconv.Itoa(id))
if str == "" { if str == "" {
return obj, errors.New("获取缓存失败") return obj, errors.New("获取缓存失败")
} }
@@ -61,7 +61,7 @@ func (service monitorProjectService) GetCache(id int) (model.MonitorProject, err
// 删除缓存 // 删除缓存
func (service monitorProjectService) RemoveCache(obj model.MonitorProject) bool { func (service monitorProjectService) RemoveCache(obj model.MonitorProject) bool {
return util.RedisUtil.Del("{{{ toCamelCase .EntityName }}}:id:" + strconv.Itoa(obj.Id)) return util.RedisUtil.HDel("MonitorProject", strconv.Itoa(obj.Id))
} }
// List 错误项目列表 // List 错误项目列表
@@ -147,16 +147,17 @@ func (service monitorProjectService) Detail(id int) (res MonitorProjectResp, e e
} }
// Add 错误项目新增 // Add 错误项目新增
func (service monitorProjectService) Add(addReq MonitorProjectAddReq) (e error) { func (service monitorProjectService) Add(addReq MonitorProjectAddReq) (createId int, e error) {
var obj model.MonitorProject var obj model.MonitorProject
response.Copy(&obj, addReq) response.Copy(&obj, addReq)
obj.ProjectKey = util.ToolsUtil.MakeUuid() obj.ProjectKey = util.ToolsUtil.MakeUuid()
err := service.db.Create(&obj).Error err := service.db.Create(&obj).Error
if e = response.CheckMysqlErr(err); e != nil { if e = response.CheckMysqlErr(err); e != nil {
return e return 0, e
} }
service.SetCache(obj) service.SetCache(obj)
createId = obj.Id
e = response.CheckErr(err, "添加失败") e = response.CheckErr(err, "添加失败")
return return
} }
@@ -194,7 +195,7 @@ func (service monitorProjectService) Del(id int) (e error) {
// 删除 // 删除
obj.IsDelete = 1 obj.IsDelete = 1
err = service.db.Save(&obj).Error err = service.db.Save(&obj).Error
util.RedisUtil.Del("MonitorProject:id:" + strconv.Itoa(obj.Id)) service.RemoveCache(obj)
e = response.CheckErr(err, "Del Save err") e = response.CheckErr(err, "Del Save err")
return return
} }

View File

@@ -38,5 +38,5 @@ func MonitorProjectRoute(rg *gin.RouterGroup) {
r.POST("/monitor_project/edit", middleware.RecordLog("错误项目编辑"), handle.Edit) r.POST("/monitor_project/edit", middleware.RecordLog("错误项目编辑"), handle.Edit)
r.POST("/monitor_project/del", middleware.RecordLog("错误项目删除"), handle.Del) r.POST("/monitor_project/del", middleware.RecordLog("错误项目删除"), handle.Del)
r.GET("/monitor_project/ExportFile", middleware.RecordLog("错误项目导出"), handle.ExportFile) r.GET("/monitor_project/ExportFile", middleware.RecordLog("错误项目导出"), handle.ExportFile)
r.POST("/monitor_project/ImportFile", handle.ImportFile) r.POST("/monitor_project/ImportFile", middleware.RecordLog("错误项目导入"), handle.ImportFile)
} }

View File

@@ -5,6 +5,7 @@ import (
"fmt" "fmt"
"log" "log"
"os" "os"
"time"
"github.com/spf13/viper" "github.com/spf13/viper"
) )
@@ -14,24 +15,26 @@ var Config = loadConfig(".")
// #region envConfig // #region envConfig
// envConfig 环境配置 // envConfig 环境配置
type envConfig struct { type envConfig struct {
RootPath string // 项目根目录 RootPath string // 项目根目录
GinMode string `mapstructure:"GIN_MODE"` // gin运行模式 GinMode string `mapstructure:"GIN_MODE"` // gin运行模式
PublicUrl string `mapstructure:"PUBLIC_URL"` // 对外发布的Url PublicUrl string `mapstructure:"PUBLIC_URL"` // 对外发布的Url
OssDomain string `mapstructure:"OSS_DOMAIN"` // OSS域名 OssDomain string `mapstructure:"OSS_DOMAIN"` // OSS域名
ServerPort int `mapstructure:"SERVER_PORT"` // 服务运行端口 ServerPort int `mapstructure:"SERVER_PORT"` // 服务运行端口
DisallowModify bool `mapstructure:"DISALLOW_MODIFY"` // 禁止修改操作 (演示功能,限制POST请求) DisallowModify bool `mapstructure:"DISALLOW_MODIFY"` // 禁止修改操作 (演示功能,限制POST请求)
PublicPrefix string // 资源访问前缀 PublicPrefix string // 资源访问前缀
UploadDirectory string `mapstructure:"UPLOAD_DIRECTORY"` // 上传文件路径 UploadDirectory string `mapstructure:"UPLOAD_DIRECTORY"` // 上传文件路径
RedisUrl string `mapstructure:"REDIS_URL"` // Redis源配置 RedisUrl string `mapstructure:"REDIS_URL"` // Redis源配置
RedisPoolSize int // Redis连接池大小 // RedisPoolSize int // Redis连接池大小
DatabaseUrl string `mapstructure:"DATABASE_URL"` // 数据源配置 RedisMaxIdleConns int // Redis空闲连接池最大值
DbTablePrefix string // Mysql表前缀 RedisConnMaxLifetime time.Duration // Redis连接可复用的最大时间(秒默认60秒)
DbDefaultStringSize uint // 数据库string类型字段的默认长度 DatabaseUrl string `mapstructure:"DATABASE_URL"` // 数据源配置
DbMaxIdleConns int // 数据库空闲连接池最大值 DbTablePrefix string // Mysql表前缀
DbMaxOpenConns int // 数据库连接池最大值 DbDefaultStringSize uint // 数据库string类型字段的默认长度
DbConnMaxLifetimeSeconds int16 // 连接可复用的最大时间(秒默认28800秒)请根据这个sql查处的时间设置 show variables like 'wait_timeout' DbMaxIdleConns int // 数据库空闲连接池最大值
Version string // 版本 DbMaxOpenConns int // 数据库连接池最大值
Secret string // 系统加密字符 DbConnMaxLifetimeSeconds int16 // 连接可复用的最大时间(秒默认28800秒)请根据这个sql查处的时间设置 show variables like 'wait_timeout'
Version string // 版本
Secret string // 系统加密字符
RedisPrefix string // Redis键前缀 RedisPrefix string // Redis键前缀
UploadImageSize int64 // 上传图片限制 UploadImageSize int64 // 上传图片限制
@@ -75,8 +78,10 @@ func loadConfig(envPath string) envConfig {
// 上传文件路径 // 上传文件路径
UploadDirectory: "/tmp/uploads/x_admin-go/", UploadDirectory: "/tmp/uploads/x_admin-go/",
// Redis源配置 // Redis源配置
RedisUrl: "redis://localhost:6379", RedisUrl: "redis://localhost:6379",
RedisPoolSize: 100, // RedisPoolSize: 100,
RedisMaxIdleConns: 80,
RedisConnMaxLifetime: 60 * time.Second,
// 数据源配置 // 数据源配置
DatabaseUrl: "x_admin:x_admin@tcp(localhost:3306)/x_admin?charset=utf8mb4&parseTime=True&loc=Local", DatabaseUrl: "x_admin:x_admin@tcp(localhost:3306)/x_admin?charset=utf8mb4&parseTime=True&loc=Local",
DbTablePrefix: "x_", DbTablePrefix: "x_",

View File

@@ -17,7 +17,10 @@ func initRedis() *redis.Client {
if err != nil { if err != nil {
log.Fatal("initRedis redis.ParseURL err: ", err) log.Fatal("initRedis redis.ParseURL err: ", err)
} }
opt.PoolSize = config.Config.RedisPoolSize // opt.PoolSize = config.Config.RedisPoolSize
opt.MaxIdleConns = config.Config.RedisMaxIdleConns
opt.ConnMaxLifetime = config.Config.RedisConnMaxLifetime
client := redis.NewClient(opt) client := redis.NewClient(opt)
ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second) ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
defer cancel() defer cancel()

View File

@@ -35,6 +35,7 @@ require (
require ( require (
filippo.io/edwards25519 v1.1.0 // indirect filippo.io/edwards25519 v1.1.0 // indirect
github.com/KyleBanks/depth v1.2.1 // indirect github.com/KyleBanks/depth v1.2.1 // indirect
github.com/benbjohnson/clock v1.3.0 // indirect
github.com/bytedance/sonic v1.11.6 // indirect github.com/bytedance/sonic v1.11.6 // indirect
github.com/bytedance/sonic/loader v0.1.1 // indirect github.com/bytedance/sonic/loader v0.1.1 // indirect
github.com/cespare/xxhash/v2 v2.2.0 // indirect github.com/cespare/xxhash/v2 v2.2.0 // indirect
@@ -84,6 +85,7 @@ require (
github.com/xuri/nfp v0.0.0-20230919160717-d98342af3f05 // indirect github.com/xuri/nfp v0.0.0-20230919160717-d98342af3f05 // indirect
github.com/yusufpapurcu/wmi v1.2.3 // indirect github.com/yusufpapurcu/wmi v1.2.3 // indirect
go.uber.org/multierr v1.11.0 // indirect go.uber.org/multierr v1.11.0 // indirect
go.uber.org/ratelimit v0.3.1 // indirect
golang.org/x/arch v0.8.0 // indirect golang.org/x/arch v0.8.0 // indirect
golang.org/x/crypto v0.23.0 // indirect golang.org/x/crypto v0.23.0 // indirect
golang.org/x/exp v0.0.0-20231108232855-2478ac86f678 // indirect golang.org/x/exp v0.0.0-20231108232855-2478ac86f678 // indirect

View File

@@ -2,6 +2,8 @@ filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA=
filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4=
github.com/KyleBanks/depth v1.2.1 h1:5h8fQADFrWtarTdtDudMmGsC7GPbOAu6RVB3ffsVFHc= github.com/KyleBanks/depth v1.2.1 h1:5h8fQADFrWtarTdtDudMmGsC7GPbOAu6RVB3ffsVFHc=
github.com/KyleBanks/depth v1.2.1/go.mod h1:jzSb9d0L43HxTQfT+oSA1EEp2q+ne2uh6XgeJcm8brE= github.com/KyleBanks/depth v1.2.1/go.mod h1:jzSb9d0L43HxTQfT+oSA1EEp2q+ne2uh6XgeJcm8brE=
github.com/benbjohnson/clock v1.3.0 h1:ip6w0uFQkncKQ979AypyG0ER7mqUSBdKLOgAle/AT8A=
github.com/benbjohnson/clock v1.3.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA=
github.com/bsm/ginkgo/v2 v2.12.0 h1:Ny8MWAHyOepLGlLKYmXG4IEkioBysk6GpaRTLC8zwWs= github.com/bsm/ginkgo/v2 v2.12.0 h1:Ny8MWAHyOepLGlLKYmXG4IEkioBysk6GpaRTLC8zwWs=
github.com/bsm/ginkgo/v2 v2.12.0/go.mod h1:SwYbGRRDovPVboqFv0tPTcG1sN61LM1Z4ARdbAV9g4c= github.com/bsm/ginkgo/v2 v2.12.0/go.mod h1:SwYbGRRDovPVboqFv0tPTcG1sN61LM1Z4ARdbAV9g4c=
github.com/bsm/gomega v1.27.10 h1:yeMWxP2pV2fG3FgAODIY8EiRE3dy0aeFYt4l7wh6yKA= github.com/bsm/gomega v1.27.10 h1:yeMWxP2pV2fG3FgAODIY8EiRE3dy0aeFYt4l7wh6yKA=
@@ -203,6 +205,8 @@ go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
go.uber.org/ratelimit v0.3.1 h1:K4qVE+byfv/B3tC+4nYWP7v/6SimcO7HzHekoMNBma0=
go.uber.org/ratelimit v0.3.1/go.mod h1:6euWsTB6U/Nb3X++xEUXA8ciPJvr19Q/0h1+oDcJhRk=
go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8= go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8=
go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=

View File

@@ -0,0 +1,29 @@
package middleware
import (
"net/http"
"time"
"github.com/gin-gonic/gin"
"go.uber.org/ratelimit"
)
// 限制每秒请求数量
// r := rg.Group("/", middleware.RateLimiterMiddleware(200))
func RateLimiterMiddleware(rate int) gin.HandlerFunc {
rl := ratelimit.New(rate)
return func(c *gin.Context) {
// Try to take a token from the rate limiter.
now := rl.Take()
// Check if we've waited longer than expected. If so, this means the rate
// limit has been exceeded.
if now.After(time.Now()) {
c.AbortWithStatus(http.StatusTooManyRequests)
return
}
c.Next()
}
}

View File

@@ -2,7 +2,6 @@ package util
import ( import (
"context" "context"
"fmt"
"strconv" "strconv"
"time" "time"
@@ -46,8 +45,8 @@ func (l *RedisUtil) Get(key string) string {
func (l *RedisUtil) Set(key string, val string, expiresInSeconds int) { func (l *RedisUtil) Set(key string, val string, expiresInSeconds int) {
//设置阈值达到即clear缓存 //设置阈值达到即clear缓存
rdsResult := l.Rdb.Set(context.Background(), key, val, time.Duration(expiresInSeconds)*time.Second) l.Rdb.Set(context.Background(), key, val, time.Duration(expiresInSeconds)*time.Second)
fmt.Println("rdsResult: ", rdsResult.String(), "rdsErr: ", rdsResult.Err())
if expiresInSeconds > 0 { if expiresInSeconds > 0 {
// 缓存失效时间 // 缓存失效时间
nowTime := time.Now().Unix() + int64(expiresInSeconds) nowTime := time.Now().Unix() + int64(expiresInSeconds)