从零开始实现基于go-zero框架的微服务电商项目(三)——gorm、redis、腾讯云SMS、validate、md5加密、日志输入到kafka的添加

项目地址:liuxianloveqiqi/XianShop: 使用go-zero搭建的电商项目 (github.com)

开始

我们在service里面新建一个utils包,里面就放上面的一些加入

gorm和redis的初始化

在common包下新建文件init_system.go,添加:

package commonimport ("context""fmt""github.com/redis/go-redis/v9""github.com/zeromicro/go-zero/core/logx""gorm.io/driver/mysql""gorm.io/gorm""gorm.io/gorm/schema"
)// gorm初始化
func InitGorm(MysqlDataSourece string) *gorm.DB {// 将日志写进kafkalogx.SetWriter(*LogxKafka())db, err := gorm.Open(mysql.Open(MysqlDataSourece),&gorm.Config{NamingStrategy: schema.NamingStrategy{//TablePrefix:   "tech_", // 表名前缀,`User` 的表名应该是 `t_users`SingularTable: true, // 使用单数表名,启用该选项,此时,`User` 的表名应该是 `t_user`},})if err != nil {panic("连接mysql数据库失败, error=" + err.Error())} else {fmt.Println("连接mysql数据库成功")}return db
}// redis初始化
func InitRedis(add, password string, db int) *redis.Client {​    rdb := redis.NewClient(&redis.Options{​       Addr:     add,
​       Password: password,
​       DB:       db,
​    })
​    _, err := rdb.Ping(context.Background()).Result()
​    if err != nil {​       panic("连接redis失败, error=" + err.Error())
​    }
​    fmt.Println("redis连接成功")
​    return rdb
}

日志输出到kafka

请参考官方:logx | go-zero

在common包下建kafka_logx.go,我这里就是封装了一下官方的写法:

package commonimport ("github.com/zeromicro/go-queue/kq""github.com/zeromicro/go-zero/core/logx""strings"
)type KafkaWriter struct {Pusher *kq.Pusher
}func NewKafkaWriter(pusher *kq.Pusher) *KafkaWriter {return &KafkaWriter{Pusher: pusher,}
}func (w *KafkaWriter) Write(p []byte) (n int, err error) {// writing log with newlines, trim them.if err := w.Pusher.Push(strings.TrimSpace(string(p))); err != nil {return 0, err}return len(p), nil
}
func LogxKafka() *logx.Writer {pusher := kq.NewPusher([]string{"localhost:9092"}, "log")defer pusher.Close()writer := logx.NewWriter(NewKafkaWriter(pusher))return &writer
}

==注意!==下面都是先在rpc里面写,然后api直接调自己的rpc,所以业务处理部分是在rpc里面写的,api直接调就行。

接着在user/rpc下的config里面添加redis和gorm

package configimport ("github.com/zeromicro/go-zero/core/stores/cache""github.com/zeromicro/go-zero/zrpc"
)type Config struct {zrpc.RpcServerConfMysql struct {DataSource string}CacheRedis cache.CacheConfRedis      struct {Host stringPass stringDB   int}Credential struct {SecretId  stringSecretKey string}
}

在svc下的servicecontext.go下添加gorm和redis并调用common里面的初始化

package svcimport ("XianShop/service/common""XianShop/service/user/model""XianShop/service/user/rpc/internal/config""github.com/redis/go-redis/v9""github.com/zeromicro/go-zero/core/stores/sqlx""gorm.io/gorm"
)type ServiceContext struct {Config    config.ConfigUserModel model.UserModelRdb       *redis.ClientDbEngine  *gorm.DB
}func NewServiceContext(c config.Config) *ServiceContext {coon := sqlx.NewMysql(c.Mysql.DataSource)db := common.InitGorm(c.Mysql.DataSource)rdb := common.InitRedis(c.Redis.Host, c.Redis.Pass, c.Redis.DB)db.AutoMigrate(&model.User{})return &ServiceContext{Config:    c,UserModel: model.NewUserModel(coon, c.CacheRedis),Rdb:       rdb,DbEngine:  db,}
}

这样之后我们就可以在logic里面调用gorm和redis

腾讯云SMS短信服务

首先在腾讯云搜索sms点击短信,按照指引创造好模版等待审核,完成后根据官方文档配置:

在utils包下建sms.go

package utilsimport ("context""encoding/json""fmt""github.com/redis/go-redis/v9""github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common""github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common/errors""github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common/profile"sms "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/sms/v20210111""math/rand""strings""time"
)func SMS(phone, secretId, secretKey string, ctx context.Context, rdb *redis.Client) string {// 实例化一个认证对象,入参需要传入腾讯云账户密钥对secretId,secretKey.credential := common.NewCredential(secretId,secretKey,)// 实例化一个认证对象,入参需要传入腾讯云账户密钥对secretId,secretKey.//credential := common.NewCredential(// "你的accessKeyId",//    "你的accessKeySecret",//)cpf := profile.NewClientProfile()cpf.HttpProfile.ReqMethod = "POST"cpf.HttpProfile.Endpoint = "sms.tencentcloudapi.com"client, _ := sms.NewClient(credential, "ap-beijing", cpf)/* 实例化一个请求对象,根据调用的接口和实际情况*/request := sms.NewSendSmsRequest()// 应用 ID 可前往 [短信控制台](https://console.cloud.tencent.com/smsv2/app-manage) 查看request.SmsSdkAppId = common.StringPtr("1400797992")// 短信签名内容: 使用 UTF-8 编码,必须填写已审核通过的签名request.SignName = common.StringPtr("我的学习记录网")/* 模板 ID: 必须填写已审核通过的模板 ID */request.TemplateId = common.StringPtr("1729324")/* 模板参数: 模板参数的个数需要与 TemplateId 对应模板的变量个数保持一致,若无模板参数,则设置为空*/code1 := GenerateSmsCode(6)fmt.Println(code1, "ZHESHICODE")request.TemplateParamSet = common.StringPtrs([]string{code1, "3"})/* 下发手机号码,采用 E.164 标准,+[国家或地区码][手机号]* 示例如:+8613711112222, 其中前面有一个+号 ,86为国家码,13711112222为手机号,最多不要超过200个手机号*/phoneWithPrefix := "+86" + phonerequest.PhoneNumberSet = common.StringPtrs([]string{phoneWithPrefix})//使用redis缓存rdb.Set(ctx, phone, code1, 3*time.Minute)fmt.Println(phone, "  ", code1)// 通过client对象调用想要访问的接口,需要传入请求对象response, err := client.SendSms(request)// 处理异常if _, ok := err.(*errors.TencentCloudSDKError); ok {fmt.Printf("An API error has returned: %s", err)return ""}// 非SDK异常,直接失败。实际代码中可以加入其他的处理。if err != nil {panic(err)}b, _ := json.Marshal(response.Response)// 打印返回的json字符串fmt.Printf("%s", b)return code1
}// GenerateSmsCode 生成验证码;length代表验证码的长度
func GenerateSmsCode(length int) string {numberic := [10]byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}rand.Seed(time.Now().Unix())var sb strings.Builderfor i := 0; i < length; i++ {fmt.Fprintf(&sb, "%d", numberic[rand.Intn(len(numberic))])}return sb.String()
}

然后改成自己的:

红色的地方是根据自己的情况可以改动的,最后那个模版参数那里,是有几个参数填几个,一一对应的关系,比如我的模版是这样的

这里的{1}就被code1代替了,{2}就被“3”代替

然后我们还需要secretId, secretKey,在腾讯云的密钥管理那里拿,然后copy到etcd到yaml文件下,就是上面一节中

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MXGgvVip-1682644996846)(/Users/liuxian/Pictures/typora图片/image-20230428084246948.png)]

validate校验参数

在utils包下新建validate.go,我这里参考golang中使用validator进行数据校验及自定义翻译器_go语言validator自定义验证信息_秋叶原の黑猫的博客-CSDN博客做了一些封装,因为博主使用的gin

package utilsimport ("context""errors""fmt""github.com/go-playground/locales/en""github.com/go-playground/locales/zh"ut "github.com/go-playground/universal-translator""github.com/go-playground/validator/v10"enTranslations "github.com/go-playground/validator/v10/translations/en"zhTranslations "github.com/go-playground/validator/v10/translations/zh""reflect""regexp""strings"
)const (ValidatorKey  = "ValidatorKey"TranslatorKey = "TranslatorKey"locale        = "chinese"
)func TransInit(ctx context.Context) context.Context {//设置支持语言chinese := zh.New()english := en.New()//设置国际化翻译器uni := ut.New(chinese, chinese, english)//设置验证器val := validator.New()//根据参数取翻译器实例trans, _ := uni.GetTranslator(locale)//翻译器注册到validatorswitch locale {case "chinese":zhTranslations.RegisterDefaultTranslations(val, trans)//使用fld.Tag.Get("comment")注册一个获取tag的自定义方法val.RegisterTagNameFunc(func(fld reflect.StructField) string {return fld.Tag.Get("comment")})val.RegisterValidation("phone", func(fl validator.FieldLevel) bool {phone := fl.Field().String()//使用正则表达式验证手机号码pattern := `^1[3456789]\d{9}$`matched, _ := regexp.MatchString(pattern, phone)return matched})// 在TransInit函数中添加电话号码翻译信息zhTranslations.RegisterDefaultTranslations(val, trans)val.RegisterTranslation("phone", trans, func(ut ut.Translator) error {return ut.Add("phone", "{0}格式不正确,必须为手机号码", true)}, func(ut ut.Translator, fe validator.FieldError) string {t, _ := ut.T("phone", fe.Field())return t})case "english":enTranslations.RegisterDefaultTranslations(val, trans)val.RegisterTagNameFunc(func(fld reflect.StructField) string {return fld.Tag.Get("en_comment")})}ctx = context.WithValue(ctx, ValidatorKey, val)ctx = context.WithValue(ctx, TranslatorKey, trans)return ctx
}func DefaultGetValidParams(ctx context.Context, params interface{}) error {ctx = TransInit(ctx)err := validate(ctx, params)if err != nil {return err}return nil
}func validate(ctx context.Context, params interface{}) error {//获取验证器val, ok := ctx.Value(ValidatorKey).(*validator.Validate)if !ok {return errors.New("Validator not found in context")}//获取翻译器tran, ok := ctx.Value(TranslatorKey).(ut.Translator)fmt.Println(val, tran)if !ok {return errors.New("Translator not found in context")}err := val.Struct(params)//如果数据效验不通过,则将所有err以切片形式输出if err != nil {errs := err.(validator.ValidationErrors)sliceErrs := []string{}for _, e := range errs {//使用validator.ValidationErrors类型里的Translate方法进行翻译sliceErrs = append(sliceErrs, e.Translate(tran))}return errors.New(strings.Join(sliceErrs, ","))}return nil
}

如果后续想加入自定义的校验,可以参考phone的校验

md5加密

在utils包下建md5.go

package utilsimport ("crypto/md5""crypto/rand""encoding/hex""math/big"
)func GeneratePassword(length int) string {// 定义密码包含的字符集charset := "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789~!@#$%^&*()_+`-={}|[]\\:\";'<>,.?/"// 定义密码长度// 这里可以根据实际需求进行调整passwordLength := length// 初始化密码切片password := make([]byte, passwordLength)// 生成随机密码for i := 0; i < passwordLength; i++ {charIndex, err := rand.Int(rand.Reader, big.NewInt(int64(len(charset))))if err != nil {panic(err)}password[i] = charset[charIndex.Int64()]}return string(password)
}// md5加密
func Md5(pasaword string) string {hash := md5.New()hash.Write([]byte(pasaword))passwordHash := hash.Sum(nil)// 将密码转换为16进制储存passwordHash16 := hex.EncodeToString(passwordHash)return passwordHash16
}// 加盐值加密
func Md5Password(password, salt string) string {return Md5(password + salt)
}// 解密
func ValidMd5Password(password, salt, dataPwd string) bool {return Md5Password(password, salt) == dataPwd
}

我这里做了个加盐处理,减少被破译的可能性,在业务部分直接调Md5Password()输入密码和盐值就可以了

,然后还做了个随机密码,因为用户在手机验证码登陆的时候,要给密码一个随机值

总结

这一章我们引入了gorm、redis、腾讯云SMS短信服务、validate校验参数、md5加密和解密、日志输入到kafka,下一章我们将完成api的编写。

感谢

如果你觉得我的文章对你有帮忙,欢迎点赞,关注,star!有问题可以在评论区直接提出来,感谢大家的阅读!

从零开始实现基于go-zero框架的微服务电商项目(三)——gorm、redis、腾讯云SMS、validate、md5加密、日志输入到kafka的添加相关推荐

  1. 项目是采用目前比较流行的 SpringBoot/SpringCloudAlibaba构建新零售微服务电商项目

    简介: 技术架构 项目是采用目前比较流行的 SpringBoot/SpringCloudAlibaba构建新零售微服务电商项目,从项目中台架构技术选型.模块设计.基础设施的构建.分布式解决方 案.互联 ...

  2. 新零售微服务电商项目SpringBoot/SpringCloudAlibaba

    技术架构–项目地址-新零售微服务电商项目 项目是采用目前比较流行的 SpringBoot/SpringCloudAlibaba构建新零售微服务电商项目,从项目中台架构技术选型.模块设计.基础设施的构建 ...

  3. 微服务电商项目技术全解析

    一.项目介绍 7d-mall-microservice 是一套微服务电商,其是在开源电商项目 mall-swarm 上进行了改造,采用了 Spring Cloud Hoxton & Aliba ...

  4. 《高楼的性能工程实战课》微服务电商项目技术全解析

    文章目录 一.项目介绍 二.整体结构 三.预备知识 1.什么是 SpringCloud ? 2.Spring .SpringBoot 和 Spring Cloud 的关系 3.Spring Cloud ...

  5. 蚂蚁课堂-第四期-基于springcloud构建微服务电商项目_阿里巴巴29个屌炸天的开源项目,你用过几个?附编程资料!!!...

    1. 分布式应用服务开发的一站式解决方案 Spring Cloud Alibaba Spring Cloud Alibaba 致力于提供分布式应用服务开发的一站式解决方案.此项目包含开发分布式应用服务 ...

  6. 基于Vue+SpringCloudAlibaba微服务电商项目实战-技术选型-004:快速整合微信公众号开发

    004:快速整合微信公众号开发 1 微信公众号开发项目演示 2 微信公众号开发设计原理 3 基于natapp将本地项目发布到外网 4 对接微信公众号测试平台 5 第三方微信框架快速实现微信开发 6 微 ...

  7. 基于Vue+SpringCloudAlibaba微服务电商项目实战-构建会员服务-011:基于Vue快速整合会员服务接口

    011:基于Vue快速整合会员服务接口 1 构建前端Vue项目调用后端接口实现联合登录效果演示 2 什么是微服务前后端分离开发的模式 3 联合登录接口接口简单回顾 4 前后端分离解决跨域的问题 5 V ...

  8. 基于SpringBoot的书城项目,带真支付功能的微服务电商项目

    目录 1.简介 2.技术栈 3.环境 4.配置 5.搭建 6.核心代码 7.界面展示 8.下载地址 1.简介 该系统分为前台展示和后台管理两大模块. 前台主要是为消费者服务.该子系统实现了注册,登录, ...

  9. 基于Vue+SpringCloudAlibaba微服务电商项目实战-商品服务-015:亿万级别商品详情页面实现动态优化

    015:亿万级别商品详情页面实现动态优化 1 亿万级别商品详情页面如何设计 2 使用Nginx缓存商品详情页面 3 使用FreeMarker生成静态化模板页面 4 openresty+lua实现亿级别 ...

最新文章

  1. oracle归档日志写满错误解决方法
  2. NSArray 过滤
  3. 深度学习元老Yann Lecun详解卷积神经网络
  4. Spring boot配置Servlet容器
  5. 有关struts2中用到 js 总结
  6. hdu4011(水贪心)
  7. 建筑与建筑群综合布线系统工程验收规范_如果这9个方面考虑周到 你的综合布线系统工程可以竣工验收了...
  8. TD8.0管理员工具
  9. 手机token记录、支付宝、个推、goeasy、手机前端框架、阿里大于、百度编辑器、秀米集成解决方案
  10. python DataScience数据分析笔记day06
  11. 计算机进程同步实验观察结果记录表,实验5 操作系统进程与文件管理 实验报告表 作业 5.doc...
  12. 典型2R机械臂结构分析 2R-manipulator Geometric Modeling
  13. 2014-人生旅途的节点
  14. 女生初级健身训练计划
  15. 形态学 - 边界提取
  16. 大厂秋招_春招面试全流程如何拿到大厂offer?Java进阶图谱
  17. mpp与mysql集群_MPPDB集群高可用设计
  18. 处理nginx 文件服务器 ,log文件中文乱码
  19. 雪城大学信息安全试验_国际信息安全系列讲座之二:雪城大学Heng Yin教授讲座通知...
  20. 会声会影X6-高级运动等效果的练习实践-与您分享...

热门文章

  1. vue实现图片滑动验证功能——功能实现
  2. 事件相关电位(ERP)在临床心理学中的运用
  3. Mac录屏软件:Record It
  4. GPS通信协议——最常用的NMEA0183协议
  5. Cadence PCB仿真使用Allegro PCB SI选择仿真类型的方法图文教程
  6. Python批量ping脚本
  7. [MFC] WS_EX_LAYERED 实现透明异形窗口(酷狗歌词、360加速球、窗口边缘阴影)
  8. Unity 3D 资源下载 || Unity 3D 综合案例
  9. Adobe Premiere Pro 打开webm格式插件的下载使用||如何解决Pr不能导入webm格式的问题?
  10. 大数据技术原理与应用(林子雨老师)慕课课后习题