• 27、用户操作srv、web服务实现


    需求分析:收藏、收货地址管理、留言,我们可以统一成用户的操作,所以我们新建一个服务userop_srv来进行实现

    一、快速启动userop_srv

    1 - 快速生成项目

    • userop_srv:将inventory_srv下除了tmp以外的文件直接拷贝到userop_srv中;将inventory_srv在选中文件夹中替换成userop_srv
      在这里插入图片描述

    2 - 表结构设计

    • userop_srv/model/userop.go
    package model
    
    const (
    	LEAVING_MESSAGES = iota + 1
    	COMPLAINT
    	INQUIRY
    	POST_SALE
    	WANT_TO_BUY
    )
    
    type LeavingMessages struct {
    	BaseModel
    
    	User        int32  `gorm:"type:int;index"`
    	MessageType int32  `gorm:"type:int comment '留言类型: 1(留言),2(投诉),3(询问),4(售后),5(求购)'"`
    	Subject     string `gorm:"type:varchar(100)"`
    
    	Message string
    	File    string `gorm:"type:varchar(200)"`
    }
    
    func (LeavingMessages) TableName() string {
    	return "leavingmessages"
    }
    
    type Address struct {
    	BaseModel
    
    	User         int32  `gorm:"type:int;index"`
    	Province     string `gorm:"type:varchar(10)"`
    	City         string `gorm:"type:varchar(10)"`
    	District     string `gorm:"type:varchar(20)"`
    	Address      string `gorm:"type:varchar(100)"`
    	SignerName   string `gorm:"type:varchar(20)"`
    	SignerMobile string `gorm:"type:varchar(11)"`
    }
    
    type UserFav struct {
    	BaseModel
    
    	User  int32 `gorm:"type:int;index:idx_user_goods,unique"`
    	Goods int32 `gorm:"type:int;index:idx_user_goods,unique"`
    }
    
    func (UserFav) TableName() string {
    	return "userfav"
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 数据库新建:mxshop_userop_srv
      在这里插入图片描述

    • userop_srv/model/main/main.go:创建表结构

    package main
    
    import (
    	"fmt"
    	"gorm.io/driver/mysql"
    	"gorm.io/gorm"
    	"gorm.io/gorm/logger"
    	"gorm.io/gorm/schema"
    	"log"
    	"nd/userop_srv/global"
    	"nd/userop_srv/initialize"
    	"nd/userop_srv/model"
    	"os"
    	"time"
    )
    
    func main() {
    	initialize.InitConfig()
    	dsn := fmt.Sprintf("root:jiushi@tcp(%s:3306)/mxshop_userop_srv?charset=utf8mb4&parseTime=True&loc=Local", global.ServerConfig.MysqlInfo.Host)
    
    	newLogger := logger.New(
    		log.New(os.Stdout, "\r\n", log.LstdFlags), // io writer
    		logger.Config{
    			SlowThreshold: time.Second, // 慢 SQL 阈值
    			LogLevel:      logger.Info, // Log level
    			Colorful:      true,        // 禁用彩色打印
    		},
    	)
    
    	// 全局模式
    	db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{
    		NamingStrategy: schema.NamingStrategy{
    			SingularTable: true,
    		},
    		Logger: newLogger,
    	})
    	if err != nil {
    		panic(err)
    	}
    
    	_ = db.AutoMigrate(&model.LeavingMessages{}, &model.UserFav{}, model.Address{})
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43

    在这里插入图片描述

    3 - nacos与yaml配置

    • 添加nacos配置
      在这里插入图片描述
    • 克隆inventory的配置:对应修改为userop即可
    {
      "name": "userop_srv",
      "host": "192.168.78.1",
      "tags": ["imooc", "bobby", "userop", "srv"],
      "mysql": {
        "host": "192.168.78.131",
        "port": 3306,
        "user": "root",
        "password": "jiushi",
        "db": "mxshop_userop_srv"
      },
      "consul": {
        "host": "192.168.78.131",
        "port": 8500
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • yaml修改命名空间id
    host: '192.168.78.131'
    port: 8848
    namespace: '167f44f6-8d47-4b13-a01a-e2a570dabaab'
    user: 'nacos'
    password: 'nacos'
    dataid: 'userop_srv.json'
    group: 'comp'
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    4 - proto接口定义

    • userop_srv/proto/address.proto
    syntax = "proto3";
    import "google/protobuf/empty.proto";
    option go_package = ".;proto";
    
    service Address{
      rpc GetAddressList(AddressRequest) returns(AddressListResponse); //查看地址
      rpc CreateAddress(AddressRequest) returns(AddressResponse); //新增地址
      rpc DeleteAddress(AddressRequest) returns(google.protobuf.Empty); //删除地址
      rpc UpdateAddress(AddressRequest) returns(google.protobuf.Empty); //修改地址
    }
    
    message AddressRequest{
      int32 id = 1;
      int32 userId = 2;
      string province = 3;
      string city = 4;
      string district = 5;
      string address = 6;
      string signerName = 7;
      string signerMobile = 8;
    }
    
    message  AddressResponse{
      int32 id = 1;
      int32 userId = 2;
      string province = 3;
      string city = 4;
      string district = 5;
      string address = 6;
      string signerName = 7;
      string signerMobile = 8;
    }
    
    
    message AddressListResponse {
      int32 total = 1;
      repeated AddressResponse data = 2;
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • userop_srv/proto/message.proto
    syntax = "proto3";
    option go_package = ".;proto";
    
    service Message{
    rpc MessageList(MessageRequest) returns(MessageListResponse); //批量获取留言信息
    rpc CreateMessage(MessageRequest) returns(MessageResponse); //添加留言
    }
    
    message MessageRequest{
    int32 id = 1;
    int32 userId = 2;
    int32 messageType = 3;
    string subject = 4;
    string message = 5;
    string file = 6;
    }
    
    message  MessageResponse{
    int32 id = 1;
    int32 userId = 2;
    int32 messageType = 3;
    string subject = 4;
    string message = 5;
    string file = 6;
    }
    
    message MessageListResponse {
    int32 total = 1;
    repeated MessageResponse data = 2;
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • userop_srv/proto/userfav.proto
    syntax = "proto3";
    import "google/protobuf/empty.proto";
    option go_package = ".;proto";
    
    service UserFav{
      rpc GetFavList(UserFavRequest) returns(UserFavListResponse); //过滤收藏信息
      rpc AddUserFav(UserFavRequest) returns(google.protobuf.Empty); //添加收藏
      rpc DeleteUserFav(UserFavRequest) returns(google.protobuf.Empty); //删除收藏
      rpc GetUserFavDetail(UserFavRequest) returns(google.protobuf.Empty); //查看用户是否已经收藏某件商品
    }
    
    message UserFavRequest{
      int32 userId = 1;
      int32 goodsId = 2;
    }
    message UserFavResponse{
      int32 userId = 1;
      int32 goodsId = 2;
    }
    
    message UserFavListResponse {
      int32 total = 1;
      repeated UserFavResponse data = 2;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • userop_srv/proto/gen_proto.bat:使用bat生成proto
    protoc --go_out=. --go_opt=paths=import --go-grpc_out=. --go-grpc_opt=paths=import *.proto
    
    • 1

    在这里插入图片描述

    • userop_srv/main.go:修改对应的proto注册及默认启动端口
    func main() {
    	IP := flag.String("ip", "0.0.0.0", "ip地址")
    	Port := flag.Int("port", 50061, "端口号") // 这个修改为0,如果我们从命令行带参数启动的话就不会为0
    
    	//初始化
    	initialize.InitLogger()
    	initialize.InitConfig()
    	initialize.InitDB()
    	zap.S().Info(global.ServerConfig)
    
    	flag.Parse()
    	zap.S().Info("ip: ", *IP)
    	if *Port == 0 {
    		*Port, _ = utils.GetFreePort()
    	}
    	zap.S().Info("port: ", *Port)
    
    	server := grpc.NewServer()
    	proto.RegisterAddressServer(server, &proto.UnimplementedAddressServer{})
    	proto.RegisterMessageServer(server, &proto.UnimplementedMessageServer{})
    	proto.RegisterUserFavServer(server, &proto.UnimplementedUserFavServer{})
    	//省略。。。
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    5 - 启动userop_srv服务

    在这里插入图片描述


    二、service的handle实现

    1 - handle_base

    • userop_srv/handler/handle_base.go:因为我们拆分了3个handle,所以将公共部分UserOpServer结构和分页逻辑提取出来
    package handler
    
    import (
    	"gorm.io/gorm"
    	"nd/userop_srv/proto"
    )
    
    type UserOpServer struct {
    	proto.UnimplementedAddressServer
    	proto.UnimplementedUserFavServer
    	proto.UnimplementedMessageServer
    }
    
    func Paginate(page, pageSize int) func(db *gorm.DB) *gorm.DB {
    	return func(db *gorm.DB) *gorm.DB {
    		if page == 0 {
    			page = 1
    		}
    
    		switch {
    		case pageSize > 100:
    			pageSize = 100
    		case pageSize <= 0:
    			pageSize = 10
    		}
    
    		offset := (page - 1) * pageSize
    		return db.Offset(offset).Limit(pageSize)
    	}
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31

    2 - handle_address

    • userop_srv/handler/handle_address.go
    package address
    
    import (
    	"context"
    	"github.com/gin-gonic/gin"
    	"go.uber.org/zap"
    	"net/http"
    	"strconv"
    	"web_api/userop_web/api"
    	"web_api/userop_web/forms"
    	"web_api/userop_web/global"
    	"web_api/userop_web/models"
    	"web_api/userop_web/proto"
    )
    
    func List(ctx *gin.Context) {
    	request := &proto.AddressRequest{}
    
    	claims, _ := ctx.Get("claims")
    	currentUser := claims.(*models.CustomClaims)
    
    	if currentUser.AuthorityId != 2 {
    		userId, _ := ctx.Get("userId")
    		request.UserId = int32(userId.(uint))
    	}
    
    	rsp, err := global.AddressClient.GetAddressList(context.Background(), request)
    	if err != nil {
    		zap.S().Errorw("获取地址列表失败")
    		api.HandleGrpcErrorToHttp(err, ctx)
    		return
    	}
    
    	reMap := gin.H{
    		"total": rsp.Total,
    	}
    
    	result := make([]interface{}, 0)
    	for _, value := range rsp.Data {
    		reMap := make(map[string]interface{})
    		reMap["id"] = value.Id
    		reMap["user_id"] = value.UserId
    		reMap["province"] = value.Province
    		reMap["city"] = value.City
    		reMap["district"] = value.District
    		reMap["address"] = value.Address
    		reMap["signer_name"] = value.SignerName
    		reMap["signer_mobile"] = value.SignerMobile
    
    		result = append(result, reMap)
    	}
    
    	reMap["data"] = result
    
    	ctx.JSON(http.StatusOK, reMap)
    }
    
    func New(ctx *gin.Context) {
    	addressForm := forms.AddressForm{}
    	if err := ctx.ShouldBindJSON(&addressForm); err != nil {
    		api.HandleValidatorError(ctx, err)
    		return
    	}
    
    	userId, _ := ctx.Get("userId")
    	rsp, err := global.AddressClient.CreateAddress(context.Background(), &proto.AddressRequest{
    		UserId:       int32(userId.(uint)),
    		Province:     addressForm.Province,
    		City:         addressForm.City,
    		District:     addressForm.District,
    		Address:      addressForm.Address,
    		SignerName:   addressForm.SignerName,
    		SignerMobile: addressForm.SignerMobile,
    	})
    
    	if err != nil {
    		zap.S().Errorw("新建地址失败")
    		api.HandleGrpcErrorToHttp(err, ctx)
    		return
    	}
    
    	ctx.JSON(http.StatusOK, gin.H{
    		"id": rsp.Id,
    	})
    }
    
    func Delete(ctx *gin.Context) {
    	id := ctx.Param("id")
    	i, err := strconv.ParseInt(id, 10, 32)
    	if err != nil {
    		ctx.Status(http.StatusNotFound)
    		return
    	}
    	userId, _ := ctx.Get("userId")
    	_, err = global.AddressClient.DeleteAddress(context.Background(), &proto.AddressRequest{
    		Id:     int32(i),
    		UserId: int32(userId.(uint)),
    	})
    	if err != nil {
    		zap.S().Errorw("删除地址失败")
    		api.HandleGrpcErrorToHttp(err, ctx)
    		return
    	}
    
    	ctx.JSON(http.StatusOK, gin.H{
    		"msg": "删除成功",
    	})
    }
    
    func Update(ctx *gin.Context) {
    	addressForm := forms.AddressForm{}
    	if err := ctx.ShouldBindJSON(&addressForm); err != nil {
    		api.HandleValidatorError(ctx, err)
    		return
    	}
    
    	id := ctx.Param("id")
    	i, err := strconv.ParseInt(id, 10, 32)
    	if err != nil {
    		ctx.Status(http.StatusNotFound)
    		return
    	}
    
    	userId, _ := ctx.Get("userId")
    
    	_, err = global.AddressClient.UpdateAddress(context.Background(), &proto.AddressRequest{
    		Id:           int32(i),
    		UserId:       int32(userId.(uint)),
    		Province:     addressForm.Province,
    		City:         addressForm.City,
    		District:     addressForm.District,
    		Address:      addressForm.Address,
    		SignerName:   addressForm.SignerName,
    		SignerMobile: addressForm.SignerMobile,
    	})
    	if err != nil {
    		zap.S().Errorw("更新地址失败")
    		api.HandleGrpcErrorToHttp(err, ctx)
    		return
    	}
    	ctx.JSON(http.StatusOK, gin.H{})
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143

    3 - handle_message

    • userop_srv/handler/handle_message.go
    package handler
    
    import (
    	"context"
    
    	"nd/userop_srv/global"
    	"nd/userop_srv/model"
    	"nd/userop_srv/proto"
    )
    
    func (*UserOpServer) MessageList(ctx context.Context, req *proto.MessageRequest) (*proto.MessageListResponse, error) {
    	var rsp proto.MessageListResponse
    	var messages []model.LeavingMessages
    	var messageList []*proto.MessageResponse
    
    	result := global.DB.Where(&model.LeavingMessages{User: req.UserId}).Find(&messages)
    	rsp.Total = int32(result.RowsAffected)
    
    	for _, message := range messages {
    		messageList = append(messageList, &proto.MessageResponse{
    			Id:          message.ID,
    			UserId:      message.User,
    			MessageType: message.MessageType,
    			Subject:     message.Subject,
    			Message:     message.Message,
    			File:        message.File,
    		})
    	}
    
    	rsp.Data = messageList
    	return &rsp, nil
    }
    
    func (*UserOpServer) CreateMessage(ctx context.Context, req *proto.MessageRequest) (*proto.MessageResponse, error) {
    	var message model.LeavingMessages
    
    	message.User = req.UserId
    	message.MessageType = req.MessageType
    	message.Subject = req.Subject
    	message.Message = req.Message
    	message.File = req.File
    
    	global.DB.Save(&message)
    
    	return &proto.MessageResponse{Id: message.ID}, nil
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47

    4 - handle_userfav

    • userop_srv/handler/handle_userfav.go
    package handler
    
    import (
    	"context"
    	"google.golang.org/protobuf/types/known/emptypb"
    
    	"google.golang.org/grpc/codes"
    	"google.golang.org/grpc/status"
    	"nd/userop_srv/global"
    	"nd/userop_srv/model"
    	"nd/userop_srv/proto"
    )
    
    func (*UserOpServer) GetFavList(ctx context.Context, req *proto.UserFavRequest) (*proto.UserFavListResponse, error) {
    	var rsp proto.UserFavListResponse
    	var userFavs []model.UserFav
    	var userFavList []*proto.UserFavResponse
    	//查询用户的收藏记录
    	//查询某件商品被哪些用户收藏了
    	result := global.DB.Where(&model.UserFav{User: req.UserId, Goods: req.GoodsId}).Find(&userFavs)
    	rsp.Total = int32(result.RowsAffected)
    
    	for _, userFav := range userFavs {
    		userFavList = append(userFavList, &proto.UserFavResponse{
    			UserId:  userFav.User,
    			GoodsId: userFav.Goods,
    		})
    	}
    
    	rsp.Data = userFavList
    
    	return &rsp, nil
    }
    
    func (*UserOpServer) AddUserFav(ctx context.Context, req *proto.UserFavRequest) (*emptypb.Empty, error) {
    	var userFav model.UserFav
    
    	userFav.User = req.UserId
    	userFav.Goods = req.GoodsId
    
    	global.DB.Save(&userFav)
    
    	return &emptypb.Empty{}, nil
    }
    
    func (*UserOpServer) DeleteUserFav(ctx context.Context, req *proto.UserFavRequest) (*emptypb.Empty, error) {
    	if result := global.DB.Unscoped().Where("goods=? and user=?", req.GoodsId, req.UserId).Delete(&model.UserFav{}); result.RowsAffected == 0 {
    		return nil, status.Errorf(codes.NotFound, "收藏记录不存在")
    	}
    	return &emptypb.Empty{}, nil
    }
    
    func (*UserOpServer) GetUserFavDetail(ctx context.Context, req *proto.UserFavRequest) (*emptypb.Empty, error) {
    	var userfav model.UserFav
    	if result := global.DB.Where("goods=? and user=?", req.GoodsId, req.UserId).Find(&userfav); result.RowsAffected == 0 {
    		return nil, status.Errorf(codes.NotFound, "收藏记录不存在")
    	}
    	return &emptypb.Empty{}, nil
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60

    5 - proto注册修改

    • userop_srv/main.go:因为之前我们使用userop_srv/handler/handle_base.go统一定义了UserOpServer结构,所以我们在注册的时候可以将3个都注册成&handler.UserOpServer{}
    func main() {
    	IP := flag.String("ip", "0.0.0.0", "ip地址")
    	Port := flag.Int("port", 50061, "端口号") // 这个修改为0,如果我们从命令行带参数启动的话就不会为0
    
    	//初始化
    	initialize.InitLogger()
    	initialize.InitConfig()
    	initialize.InitDB()
    	zap.S().Info(global.ServerConfig)
    
    	flag.Parse()
    	zap.S().Info("ip: ", *IP)
    	if *Port == 0 {
    		*Port, _ = utils.GetFreePort()
    	}
    	zap.S().Info("port: ", *Port)
    
    	server := grpc.NewServer()
    	proto.RegisterAddressServer(server, &handler.UserOpServer{})
    	proto.RegisterMessageServer(server, &handler.UserOpServer{})
    	proto.RegisterUserFavServer(server, &handler.UserOpServer{})
    	//省略。。。
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    三、handle接口测试

    • userop_srv/tests/userop/main.go:这里简单调用下3个查询接口,没有报错即可,其他的等我们在web服务中调用检查
    package main
    
    import (
    	"context"
    	"google.golang.org/grpc"
    	"google.golang.org/grpc/credentials/insecure"
    	"nd/userop_srv/proto"
    	"nd/userop_srv/tests"
    )
    
    var userFavClient proto.UserFavClient
    var messageClient proto.MessageClient
    var addressClient proto.AddressClient
    var conn *grpc.ClientConn
    
    func TestAddressList() {
    	_, err := addressClient.GetAddressList(context.Background(), &proto.AddressRequest{
    		UserId: 1,
    	})
    	if err != nil {
    		panic(err)
    	}
    }
    
    func TestMessageList() {
    	_, err := messageClient.MessageList(context.Background(), &proto.MessageRequest{
    		UserId: 1,
    	})
    	if err != nil {
    		panic(err)
    	}
    }
    
    func TestUserFav() {
    	_, err := userFavClient.GetFavList(context.Background(), &proto.UserFavRequest{
    		UserId: 1,
    	})
    	if err != nil {
    		panic(err)
    	}
    }
    func Init() {
    	var err error
    	conn, err = grpc.Dial(tests.TargetAddr, grpc.WithTransportCredentials(insecure.NewCredentials()))
    	if err != nil {
    		panic(err)
    	}
    	userFavClient = proto.NewUserFavClient(conn)
    	messageClient = proto.NewMessageClient(conn)
    	addressClient = proto.NewAddressClient(conn)
    }
    
    func main() {
    	Init()
    
    	TestAddressList()
    	TestMessageList()
    	TestUserFav()
    	conn.Close()
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61

    在这里插入图片描述


    四、快速启动userop_web

    1 - 快速生成项目

    • userop_web:将order_web下除了tmp以外的文件直接拷贝到userop_web中;将order_web在选中文件夹中替换成userop_web
      在这里插入图片描述

    2 - api修改

    • userop_web/api/address/api_address.go
    package address
    
    import (
    	"context"
    	"github.com/gin-gonic/gin"
    	"go.uber.org/zap"
    	"net/http"
    	"strconv"
    	"web_api/userop_web/api"
    	"web_api/userop_web/forms"
    	"web_api/userop_web/global"
    	"web_api/userop_web/models"
    	"web_api/userop_web/proto"
    )
    
    func List(ctx *gin.Context) {
    	request := &proto.AddressRequest{}
    
    	claims, _ := ctx.Get("claims")
    	currentUser := claims.(*models.CustomClaims)
    
    	if currentUser.AuthorityId != 2 {
    		userId, _ := ctx.Get("userId")
    		request.UserId = int32(userId.(uint))
    	}
    
    	rsp, err := global.AddressClient.GetAddressList(context.Background(), request)
    	if err != nil {
    		zap.S().Errorw("获取地址列表失败")
    		api.HandleGrpcErrorToHttp(err, ctx)
    		return
    	}
    
    	reMap := gin.H{
    		"total": rsp.Total,
    	}
    
    	result := make([]interface{}, 0)
    	for _, value := range rsp.Data {
    		reMap := make(map[string]interface{})
    		reMap["id"] = value.Id
    		reMap["user_id"] = value.UserId
    		reMap["province"] = value.Province
    		reMap["city"] = value.City
    		reMap["district"] = value.District
    		reMap["address"] = value.Address
    		reMap["signer_name"] = value.SignerName
    		reMap["signer_mobile"] = value.SignerMobile
    
    		result = append(result, reMap)
    	}
    
    	reMap["data"] = result
    
    	ctx.JSON(http.StatusOK, reMap)
    }
    
    func New(ctx *gin.Context) {
    	addressForm := forms.AddressForm{}
    	if err := ctx.ShouldBindJSON(&addressForm); err != nil {
    		api.HandleValidatorError(ctx, err)
    		return
    	}
    
    	userId, _ := ctx.Get("userId")
    	rsp, err := global.AddressClient.CreateAddress(context.Background(), &proto.AddressRequest{
    		UserId:       int32(userId.(uint)),
    		Province:     addressForm.Province,
    		City:         addressForm.City,
    		District:     addressForm.District,
    		Address:      addressForm.Address,
    		SignerName:   addressForm.SignerName,
    		SignerMobile: addressForm.SignerMobile,
    	})
    
    	if err != nil {
    		zap.S().Errorw("新建地址失败")
    		api.HandleGrpcErrorToHttp(err, ctx)
    		return
    	}
    
    	ctx.JSON(http.StatusOK, gin.H{
    		"id": rsp.Id,
    	})
    }
    
    func Delete(ctx *gin.Context) {
    	id := ctx.Param("id")
    	i, err := strconv.ParseInt(id, 10, 32)
    	if err != nil {
    		ctx.Status(http.StatusNotFound)
    		return
    	}
    	_, err = global.AddressClient.DeleteAddress(context.Background(), &proto.AddressRequest{Id: int32(i)})
    	if err != nil {
    		zap.S().Errorw("删除地址失败")
    		api.HandleGrpcErrorToHttp(err, ctx)
    		return
    	}
    
    	ctx.JSON(http.StatusOK, gin.H{
    		"msg": "删除成功",
    	})
    }
    
    func Update(ctx *gin.Context) {
    	addressForm := forms.AddressForm{}
    	if err := ctx.ShouldBindJSON(&addressForm); err != nil {
    		api.HandleValidatorError(ctx, err)
    		return
    	}
    
    	id := ctx.Param("id")
    	i, err := strconv.ParseInt(id, 10, 32)
    	if err != nil {
    		ctx.Status(http.StatusNotFound)
    		return
    	}
    
    	_, err = global.AddressClient.UpdateAddress(context.Background(), &proto.AddressRequest{
    		Id:           int32(i),
    		Province:     addressForm.Province,
    		City:         addressForm.City,
    		District:     addressForm.District,
    		Address:      addressForm.Address,
    		SignerName:   addressForm.SignerName,
    		SignerMobile: addressForm.SignerMobile,
    	})
    	if err != nil {
    		zap.S().Errorw("更新地址失败")
    		api.HandleGrpcErrorToHttp(err, ctx)
    		return
    	}
    	ctx.JSON(http.StatusOK, gin.H{})
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • userop_web/api/message/api_message.go
    package message
    
    import (
    	"context"
    	"github.com/gin-gonic/gin"
    	"go.uber.org/zap"
    	"net/http"
    	"web_api/userop_web/api"
    	"web_api/userop_web/forms"
    	"web_api/userop_web/global"
    	"web_api/userop_web/models"
    	"web_api/userop_web/proto"
    )
    
    func List(ctx *gin.Context) {
    	request := &proto.MessageRequest{}
    
    	userId, _ := ctx.Get("userId")
    	claims, _ := ctx.Get("claims")
    	model := claims.(*models.CustomClaims)
    	if model.AuthorityId == 1 {
    		request.UserId = int32(userId.(uint))
    	}
    
    	rsp, err := global.MessageClient.MessageList(context.Background(), request)
    	if err != nil {
    		zap.S().Errorw("获取留言失败")
    		api.HandleGrpcErrorToHttp(err, ctx)
    		return
    	}
    
    	reMap := map[string]interface{}{
    		"total": rsp.Total,
    	}
    	result := make([]interface{}, 0)
    	for _, value := range rsp.Data {
    		reMap := make(map[string]interface{})
    		reMap["id"] = value.Id
    		reMap["user_id"] = value.UserId
    		reMap["type"] = value.MessageType
    		reMap["subject"] = value.Subject
    		reMap["message"] = value.Message
    		reMap["file"] = value.File
    
    		result = append(result, reMap)
    	}
    	reMap["data"] = result
    
    	ctx.JSON(http.StatusOK, reMap)
    }
    
    func New(ctx *gin.Context) {
    	userId, _ := ctx.Get("userId")
    
    	messageForm := forms.MessageForm{}
    	if err := ctx.ShouldBindJSON(&messageForm); err != nil {
    		api.HandleValidatorError(ctx, err)
    		return
    	}
    
    	rsp, err := global.MessageClient.CreateMessage(context.Background(), &proto.MessageRequest{
    		UserId:      int32(userId.(uint)),
    		MessageType: messageForm.MessageType,
    		Subject:     messageForm.Subject,
    		Message:     messageForm.Message,
    		File:        messageForm.File,
    	})
    
    	if err != nil {
    		zap.S().Errorw("添加留言失败")
    		api.HandleGrpcErrorToHttp(err, ctx)
    		return
    	}
    	ctx.JSON(http.StatusOK, gin.H{
    		"id": rsp.Id,
    	})
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • userop_web/api/user_fav/api_user_fav.go
    package user_fav
    
    import (
    	"context"
    	"github.com/gin-gonic/gin"
    	"go.uber.org/zap"
    	"net/http"
    	"strconv"
    	"web_api/userop_web/api"
    	"web_api/userop_web/forms"
    	"web_api/userop_web/global"
    	"web_api/userop_web/proto"
    )
    
    func List(ctx *gin.Context) {
    	userId, _ := ctx.Get("userId")
    	userFavRsp, err := global.UserFavClient.GetFavList(context.Background(), &proto.UserFavRequest{
    		UserId: int32(userId.(uint)),
    	})
    	if err != nil {
    		zap.S().Errorw("获取收藏列表失败")
    		api.HandleGrpcErrorToHttp(err, ctx)
    		return
    	}
    
    	ids := make([]int32, 0)
    	for _, item := range userFavRsp.Data {
    		ids = append(ids, item.GoodsId)
    	}
    
    	if len(ids) == 0 {
    		ctx.JSON(http.StatusOK, gin.H{
    			"total": 0,
    		})
    		return
    	}
    
    	//请求商品服务
    	goods, err := global.GoodsSrvClient.BatchGetGoods(context.Background(), &proto.BatchGoodsIdInfo{
    		Id: ids,
    	})
    	if err != nil {
    		zap.S().Errorw("[List] 批量查询【商品列表】失败")
    		api.HandleGrpcErrorToHttp(err, ctx)
    		return
    	}
    
    	reMap := map[string]interface{}{
    		"total": userFavRsp.Total,
    	}
    
    	goodsList := make([]interface{}, 0)
    	for _, item := range userFavRsp.Data {
    		data := gin.H{
    			"id": item.GoodsId,
    		}
    
    		for _, good := range goods.Data {
    			if item.GoodsId == good.Id {
    				data["name"] = good.Name
    				data["shop_price"] = good.ShopPrice
    			}
    		}
    
    		goodsList = append(goodsList, data)
    	}
    	reMap["data"] = goodsList
    	ctx.JSON(http.StatusOK, reMap)
    }
    
    func New(ctx *gin.Context) {
    	userFavForm := forms.UserFavForm{}
    	if err := ctx.ShouldBindJSON(&userFavForm); err != nil {
    		api.HandleValidatorError(ctx, err)
    		return
    	}
    
    	//缺少一步, 这个时候应该去商品服务查询一下这个是否存在
    	userId, _ := ctx.Get("userId")
    	_, err := global.UserFavClient.AddUserFav(context.Background(), &proto.UserFavRequest{
    		UserId:  int32(userId.(uint)),
    		GoodsId: userFavForm.GoodsId,
    	})
    
    	if err != nil {
    		zap.S().Errorw("添加收藏记录失败")
    		api.HandleGrpcErrorToHttp(err, ctx)
    		return
    	}
    
    	ctx.JSON(http.StatusOK, gin.H{})
    }
    
    func Delete(ctx *gin.Context) {
    	id := ctx.Param("id")
    	i, err := strconv.ParseInt(id, 10, 32)
    	if err != nil {
    		ctx.Status(http.StatusNotFound)
    		return
    	}
    
    	userId, _ := ctx.Get("userId")
    	_, err = global.UserFavClient.DeleteUserFav(context.Background(), &proto.UserFavRequest{
    		UserId:  int32(userId.(uint)),
    		GoodsId: int32(i),
    	})
    	if err != nil {
    		zap.S().Errorw("删除收藏记录失败")
    		api.HandleGrpcErrorToHttp(err, ctx)
    		return
    	}
    
    	ctx.JSON(http.StatusOK, gin.H{
    		"msg": "删除成功",
    	})
    }
    
    func Detail(ctx *gin.Context) {
    	goodsId := ctx.Param("id")
    	goodsIdInt, err := strconv.ParseInt(goodsId, 10, 32)
    	if err != nil {
    		ctx.Status(http.StatusNotFound)
    		return
    	}
    	userId, _ := ctx.Get("userId")
    	_, err = global.UserFavClient.GetUserFavDetail(context.Background(), &proto.UserFavRequest{
    		UserId:  int32(userId.(uint)),
    		GoodsId: int32(goodsIdInt),
    	})
    	if err != nil {
    		zap.S().Errorw("查询收藏状态失败")
    		api.HandleGrpcErrorToHttp(err, ctx)
    		return
    	}
    
    	ctx.Status(http.StatusOK)
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138

    3 - config修改

    • userop_web/config/config.go
    package config
    
    type SrvConfig struct {
    	Name string `mapstructure:"name" json:"name"`
    }
    
    type JWTConfig struct {
    	SigningKey string `mapstructure:"key" json:"key"`
    }
    
    type ConsulConfig struct {
    	Host string `mapstructure:"host" json:"host"`
    	Port int    `mapstructure:"port" json:"port"`
    }
    
    type ServerConfig struct {
    	Name          string       `mapstructure:"name" json:"name"`
    	Host          string       `mapstructure:"host" json:"host"`
    	Tags          []string     `mapstructure:"tags" json:"tags"`
    	Port          int          `mapstructure:"port" json:"port"`
    	GoodsSrvInfo  SrvConfig    `mapstructure:"goods_srv" json:"goods_srv"`
    	UserOpSrvInfo SrvConfig    `mapstructure:"userop_srv" json:"userop_srv"`
    	JWTInfo       JWTConfig    `mapstructure:"jwt" json:"jwt"`
    	ConsulInfo    ConsulConfig `mapstructure:"consul" json:"consul"`
    }
    
    type NacosConfig struct {
    	Host      string `mapstructure:"host"`
    	Port      uint64 `mapstructure:"port"`
    	Namespace string `mapstructure:"namespace"`
    	User      string `mapstructure:"user"`
    	Password  string `mapstructure:"password"`
    	DataId    string `mapstructure:"dataid"`
    	Group     string `mapstructure:"group"`
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36

    4 - form表单修改

    • userop_web/forms/form_address.go
    package forms
    
    type AddressForm struct {
    	Province    string `form:"province" json:"province" binding:"required"`
    	City string `form:"city" json:"city" binding:"required"`
    	District string `form:"district" json:"district" binding:"required"`
    	Address string `form:"address" json:"address" binding:"required"`
    	SignerName string `form:"signer_name" json:"signer_name" binding:"required"`
    	SignerMobile string `form:"signer_mobile" json:"signer_mobile" binding:"required"`
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • userop_web/forms/form_message.go
    package forms
    
    type MessageForm struct {
    	MessageType    int32 `form:"type" json:"type" binding:"required,oneof=1 2 3 4 5"`
    	Subject string `form:"subject" json:"subject" binding:"required"`
    	Message string `form:"message" json:"message" binding:"required"`
    	File string `form:"file" json:"file" binding:"required"`
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • userop_web/forms/form_user_fav.go
    package forms
    
    type UserFavForm struct {
    	GoodsId    int32 `form:"goods" json:"goods" binding:"required"`
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    5 - 从srv拷贝proto文件

    在这里插入图片描述

    6 - global修改

    • userop_web/global/global.go
    package global
    
    import (
    	ut "github.com/go-playground/universal-translator"
    
    	"web_api/userop_web/config"
    	"web_api/userop_web/proto"
    )
    
    var (
    	Trans ut.Translator
    
    	ServerConfig *config.ServerConfig = &config.ServerConfig{}
    
    	NacosConfig *config.NacosConfig = &config.NacosConfig{}
    
    	GoodsSrvClient proto.GoodsClient
    
    	MessageClient proto.MessageClient
    	AddressClient proto.AddressClient
    	UserFavClient proto.UserFavClient
    )
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    7 - router修改

    • userop_web/router/router_address.go
    package router
    
    import (
    	"github.com/gin-gonic/gin"
    	"web_api/userop_web/api/address"
    	"web_api/userop_web/middlewares"
    )
    
    func InitAddressRouter(Router *gin.RouterGroup) {
    	//AddressRouter := Router.Group("address").Use(middlewares.JWTAuth())
    	AddressRouter := Router.Group("address").Use(middlewares.SetUserId())
    	{
    		AddressRouter.GET("", address.List)
    		AddressRouter.DELETE("/:id", address.Delete)
    		AddressRouter.POST("", address.New)
    		AddressRouter.PUT("/:id", address.Update)
    	}
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • userop_web/router/router_message.go
    package router
    
    import (
    	"github.com/gin-gonic/gin"
    	"web_api/userop_web/api/message"
    	"web_api/userop_web/middlewares"
    )
    
    func InitMessageRouter(Router *gin.RouterGroup) {
    	//MessageRouter := Router.Group("message").Use(middlewares.JWTAuth())
    	MessageRouter := Router.Group("message").Use(middlewares.SetUserId())
    	{
    		MessageRouter.GET("", message.List) // 轮播图列表页
    		MessageRouter.POST("", message.New) //新建轮播图
    	}
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • userop_web/router/router_user_fav.go
    package router
    
    import (
    	"github.com/gin-gonic/gin"
    	"web_api/userop_web/api/user_fav"
    	"web_api/userop_web/middlewares"
    )
    
    func InitUserFavRouter(Router *gin.RouterGroup) {
    	//UserFavRouter := Router.Group("userfavs").Use(middlewares.JWTAuth())
    	UserFavRouter := Router.Group("userfavs").Use(middlewares.SetUserId())
    	{
    		UserFavRouter.DELETE("/:id", user_fav.Delete) // 删除收藏记录
    		UserFavRouter.GET("/:id", user_fav.Detail)    // 获取收藏记录
    		UserFavRouter.POST("", user_fav.New)          //新建收藏记录
    		UserFavRouter.GET("", user_fav.List)          //获取当前用户的收藏
    	}
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • userop_web/initialize/init_router.go:初始化router修改
    package initialize
    
    import (
    	"github.com/gin-gonic/gin"
    
    	"web_api/userop_web/middlewares"
    	"web_api/userop_web/router"
    )
    
    func Routers() *gin.Engine {
    	Router := gin.Default()
    
    	//配置跨域
    	Router.Use(middlewares.Cors())
    	ApiGroup := Router.Group("/up/v1")
    
    	router.InitAddressRouter(ApiGroup)
    	router.InitMessageRouter(ApiGroup)
    	router.InitUserFavRouter(ApiGroup)
    
    	return Router
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    8 - 初始化连接修改

    • userop_web/initialize/init_srv_conn.go
    package initialize
    
    import (
    	"fmt"
    	_ "github.com/mbobakov/grpc-consul-resolver" // It's important
    	"go.uber.org/zap"
    	"google.golang.org/grpc"
    	"google.golang.org/grpc/credentials/insecure"
    	"web_api/userop_web/global"
    	"web_api/userop_web/proto"
    )
    
    func InitSrvConn() {
    	consulInfo := global.ServerConfig.ConsulInfo
    	goodsConn, err := grpc.Dial(
    		fmt.Sprintf("consul://%s:%d/%s?wait=14s", consulInfo.Host, consulInfo.Port, global.ServerConfig.GoodsSrvInfo.Name),
    		grpc.WithTransportCredentials(insecure.NewCredentials()),
    		grpc.WithDefaultServiceConfig(`{"loadBalancingPolicy": "round_robin"}`),
    	)
    	if err != nil {
    		zap.S().Fatal("[InitSrvConn] 连接 【商品服务失败】")
    	}
    
    	global.GoodsSrvClient = proto.NewGoodsClient(goodsConn)
    
    	userOpConn, err := grpc.Dial(
    		fmt.Sprintf("consul://%s:%d/%s?wait=14s", consulInfo.Host, consulInfo.Port, global.ServerConfig.UserOpSrvInfo.Name),
    		grpc.WithTransportCredentials(insecure.NewCredentials()),
    		grpc.WithDefaultServiceConfig(`{"loadBalancingPolicy": "round_robin"}`),
    	)
    	if err != nil {
    		zap.S().Fatal("[InitSrvConn] 连接 【用户操作服务失败】")
    	}
    
    	global.UserFavClient = proto.NewUserFavClient(userOpConn)
    	global.MessageClient = proto.NewMessageClient(userOpConn)
    	global.AddressClient = proto.NewAddressClient(userOpConn)
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39

    9 - nacos配置与yaml修改

    • 克隆配置:注意需要添加userop_srv服务;端口修改为8085
      在这里插入图片描述
    {
      "host": "192.168.78.1",
      "name": "userop_web",
      "port": 8085,
      "tags": ["mxshop","imooc","bobby","userop","web"],
      "goods_srv": {
        "name": "goods_srv"
      },
      "userop_srv": {
        "name": "userop_srv"
      },
      "jwt": {
        "key": "VYLDYq3&hGWjWqF$K1ih"
      },
      "consul": {
        "host": "192.168.78.131",
        "port": 8500
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • yaml修改空间id
    host: '192.168.124.51'
    port: 8848
    namespace: '167f44f6-8d47-4b13-a01a-e2a570dabaab'
    user: 'nacos'
    password: 'nacos'
    dataid: 'userop_web.json'
    group: 'zsz'
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    在这里插入图片描述


    五、YApi测试userop_web

    测试需要启动goods_srv服务、userop_srv服务、userop_web服务

    1 - 收藏YApi测试

    在这里插入图片描述
    在这里插入图片描述

    • 查询用户收藏列表
      在这里插入图片描述
    • 查询用户是否收藏某商品
      在这里插入图片描述
    • 删除某件商品的收藏
      在这里插入图片描述

    2 - 地址YApi测试

    • 添加地址
      在这里插入图片描述
    • 地址列表

    在这里插入图片描述

    • 更新地址
      在这里插入图片描述
    • 删除地址
      在这里插入图片描述

    3 - 留言YApi测试

    • 添加留言
      在这里插入图片描述
    • 留言列表
      在这里插入图片描述

    六、完整源码

    • 完整源码下载mxshop_srvsV10.0rar
    • 源码说明:(nacos的ip配置自行修改,全局变量DEV_CONFIG设置:1=zsz,2=comp,3=home)
      • goods_srv/model/sql/mxshop_goods.sql:包含了建表语句
      • other_import/api.json:YApi的导入文件
      • other_import/nacos_config_export_user.zip:nacos的user配置集导入文件
      • other_import/nacos_config_export_goods.zip:nacos的goods配置集导入文件
      • other_import/nacos_config_export_inventory.zip:nacos的inventory的配置导入文件
      • other_import/nacos_config_export_orders.zip:nacos的orders的配置导入文件
      • other_import/nacos_config_export_userop.zip:nacos的userop的配置导入文件
  • 相关阅读:
    Hexagon_V65_Programmers_Reference_Manual(41)
    spring boot 使用AOP+自定义注解+反射实现操作日志记录修改前数据和修改后对比数据,并保存至日志表
    IBO对中文A文学课程IA有何规定?
    试用期生存指南
    CloudCompare&PCL ICP配准(点到面)
    vite的搭建与使用
    node.js+express 做301重定向实验
    JavaEE初阶—详解JVM(八股文)
    基于变压器的手持式超声图像中乳腺病变的分类不一致性测量表征
    如何写单元测试
  • 原文地址:https://blog.csdn.net/qq23001186/article/details/126322483