广州高端品牌网站建设后台管理便捷,制作大型网站开发,现在建设网站都用什么软件,百度官网网页版文章目录简介建表protohandler商品小结简介
商品微服务主要在于表的设计#xff0c;建哪些表#xff1f;表之间的关系是怎样的#xff1f; 主要代码就是 CURD表和字段的设计是一个比较有挑战性的工作#xff0c;比较难说清楚#xff0c;也需要经验的积累#xff0c;这里…
文章目录简介建表protohandler商品小结简介
商品微服务主要在于表的设计建哪些表表之间的关系是怎样的 主要代码就是 CURD表和字段的设计是一个比较有挑战性的工作比较难说清楚也需要经验的积累这里关注点在微服务暂时先 “借鉴” 别人的设计一般需要多次迭代才能设计出比较合理的表结构 我们将商品相关的服务都放在这部分方便建表和管理微服务并不是越多越好分成太多服务可能会让系统太复杂难以管理 如何划分微服务需要积累经验也有针对性的方法可以套用需要单独学习
建表
新建商品微服务 Service 层直接把 user_srv 的目录拷过来整体替换相关路径 表设计及相关操作主要有四张表 放个商品表的结构// 商品表
// 某一个具体的商品
type Goods struct {BaseModelCategoryID int32 gorm:type:int;not nullCategory Category // 一对多/一对一BrandsID int32 gorm:type:int;not nullBrands Brands // 一对一OnSale bool gorm:default:false;not nullShipFree bool gorm:default:false;not nullIsNew bool gorm:default:false;not nullIsHot bool gorm:default:false;not nullName string gorm:type:varchar(50);not nullGoodsSn string gorm:type:varchar(50);not nullClickNum int32 gorm:type:int;default:0;not nullSoldNum int32 gorm:type:int;default:0;not nullFavNum int32 gorm:type:int;default:0;not nullMarketPrice float32 gorm:not nullShopPrice float32 gorm:not nullGoodsBrief string gorm:type:varchar(100);not nullImages GormList gorm:type:varchar(1000);not nullDescImages GormList gorm:type:varchar(1000);not nullGoodsFrontImage string gorm:type:varchar(200);not null
}对字段的限制一般都要求 not null也就是必须有值然后限制用户必须输入或者我们设置 default 设置为 null 带来的问题 定义 model 注意表之间的关联关系查看 gorm 文档了解使用方式 生成表结构 新建数据库直接在109.128机器上操作方便启动项目CREATE DATABASE IF NOT EXISTS shop_goods_srv DEFAULT CHARSET utf8 COLLATE utf8_general_ci;一个微服务对应一个数据库要和其他微服务隔离开还是在 model/main 下面运行一次 main 方法即可 运行 sql 文件导入数据将上面创建的表结构全部删掉不删也行因为 SQL 文件里包含了建表语句
proto
proto 文件的设计又是一个重点首先要根据页面进行需求分析前端页面和后台管理页面需要哪些接口传递哪些参数会有什么响应接口定义也不是一蹴而就的后面可能会修改不必在一开始追求完美protoc -I . goods.proto --go_outpluginsgrpc:. 生成 stub 文件 遇到点小问题empty.proto 找不到拷过来放到 proto/google/protobuf 下面试试 定义 Service 层Server端接口handler直接搜 GoodsServer将接口定义拷过来 这里接口太多我们分在不同 handler 文件实现不着急实现先把接口定义拷过去修改一下引用因为没有实现的话项目无法启动再修改 main.go 和 nacos 配置文件本地/中心配置启动项目看能否注册成功
handler
具体实现各接口先从品牌和轮播图开始这里放个获取品牌列表的例子// 品牌
func (s *GoodsServer) BrandList(ctx context.Context, req *proto.BrandFilterRequest) (*proto.BrandListResponse, error) {brandListResponse : proto.BrandListResponse{}var brands []model.Brands// 分页第几页每页数量// Scopes 需要传一个匿名函数进去在里面做一些判断并查询数据result : global.DB.Scopes(Paginate(int(req.Pages), int(req.PagePerNums))).Find(brands)if result.Error ! nil {return nil, result.Error}var total int64global.DB.Model(model.Brands{}).Count(total) // 单独再获取一次品牌总数brandListResponse.Total int32(total)// 准备响应数据单个品牌的BrandInfoResponse 和品牌列表的 brandListResponse要根据 proto 定义的 message 安排好var brandResponses []*proto.BrandInfoResponsefor _, brand : range brands {brandResponses append(brandResponses, proto.BrandInfoResponse{Id: brand.ID,Name: brand.Name,Logo: brand.Logo,})}brandListResponse.Data brandResponsesreturn brandListResponse, nil
}回答一个上一篇的问题查询数据时不传表名传入 model 定义的 struct 就可以吗 是的比如 DB.First(model.Brands{})因为 struct 名就是表名改表名也是通过绑在 struct 上的函数进行的 商品分类 先看 GetAllCategorysList这里比较 tricky因为有多级分类需要同时查询两级 subCategory我们希望得到的数据格式[{id:xxx,name:,level:1,is_tab:false,parent:13xxx,sub_category:[id:xxx,name:,level:1,is_tab:false,sub_category:[id:xxx,name:,]]}
]通过 gorm 提供的预加载反向查询实现条件查询一级目录global.DB.Where(model.Category{Level: 1})反向查询两级子类目Preload(SubCategory.SubCategory)再贴一个获取子分类的函数grpc 的接口实现都是三步走// 获取子分类传入一级或二级类别ID
func (s *GoodsServer) GetSubCategory(ctx context.Context, req *proto.CategoryListRequest) (*proto.SubCategoryListResponse, error) {// 1.准备返回值categoryListResponse : proto.SubCategoryListResponse{} // total, info(parent), sub// 2.根据请求参数查询数据判空var category model.Categoryif result : global.DB.First(category, req.Id); result.RowsAffected 0 {return nil, status.Errorf(codes.NotFound, 商品分类不存在)}// 3.填充返回值各字段-InfocategoryListResponse.Info proto.CategoryInfoResponse{Id: category.ID,Name: category.Name,Level: category.Level,IsTab: category.IsTab,ParentCategory: category.ParentCategoryID,}var subCategorys []model.Categoryvar subCategoryResponse []*proto.CategoryInfoResponse// 如果要获取三级子分类默认获取下面一级//preloads : SubCategory//if category.Level 1 {// preloads SubCategory.SubCategory//}// 只有在一级时才有获取三级的需求但是这里没必要这里把这个接口做的小一点限制在只获取下一级需要三级的话再在二级一一请求global.DB.Where(model.Category{ParentCategoryID: req.Id}).Find(subCategorys)for _, subCategory : range subCategorys {subCategoryResponse append(subCategoryResponse, proto.CategoryInfoResponse{Id: subCategory.ID,Name: subCategory.Name,Level: subCategory.Level,IsTab: subCategory.IsTab,ParentCategory: subCategory.ParentCategoryID,})}// 3.填充返回值各字段-SubCategoryscategoryListResponse.SubCategorys subCategoryResponsereturn categoryListResponse, nil
}这里需要写接口测试可以在 test 目录写 UT 或者每个 handler 新建目录在 main 函数运行看效果一个目录下只能有一个main 品牌分类 查询品牌和分类数据表这是个中间表内容较多相关操作也较为复杂一点 model 定义如下type GoodsCategoryBrand struct {BaseModelCategoryID int32 gorm:type:int;index:idx_category_brand,unique // 外键Category Category // 外键约束约束谁就指向谁BrandsID int32 gorm:type:int;index:idx_category_brand,unique // 外键Brands Brands
}这些接口都是给 web 层调用但有的是给用户准备数据有的是给后台管理员准备
商品
商品接口关系到最终展示给用户的数据最重要注这部分有很多入口搜索、新品、热门、价格区间、商品分类都需要调用接口获取对应商品这些都可以看做是查询条件注意下面几点 条件是可以叠加的所有用 localDB 接收前面过滤出的数据体分类条件要考虑层级 后续会集成 elastic 用于搜索
小结
快速开发了商品微服务的 Service 层服务配置项还是和 user_srv 相同包括 nacosmysqlconsulserverConfig不需要更改定义接下来是商品微服务 API 层的快速开发