[golang gin框架] 41.Gin商城项目-微服务实战之后台Rbac微服务(用户登录 、Gorm数据库配置单独抽离、 Consul配置单独抽离)

news2024/11/28 10:38:55
上一节抽离了captcha验证码功能,集成了验证码微服务功能,这一节来看看后台Rbac功能,并抽离其中的用户登录,管理员管理,角色管理,权限管理等功能作为微服务来调用

一.引入

后台操作从登录到后台首页,然后其中的管理员管理,角色管理,权限管理等功能可以抽离出来作为 一个Rbac微服务,因为他们都是共同关系的,并且使用人员也不是太多,当然,也可以每个管理功能单独作为一个微服务来进行操作

二.创建权限管理Rbac微服务服务端以及实现后台用户登录微服务

1.生成权限管理Rbac微服务代码

在server目录下运行: go-micro new service rbac,生成 rbac微服务服务端代码

2.编写proto/rbac.proto文件,实现用户登录微服务逻辑

在这个文件中编写 用户登录相关代码,可参考: [golang gin框架] 13.Gin 商城项目-配置公共基类实现公共的成功,失败提示页面 用户登录、退出登录、以及权限判断
参考代码 controllers/admin/loginController.go如下:
//执行登录操作
func (con LoginController) DoIndex(c *gin.Context) {
    //获取表单中的数据
    captchaId := c.PostForm("captchaId")     // 验证码id
    verifyValue := c.PostForm("verifyValue") //验证码的值
    //获取用户名以及密码
    username := c.PostForm("username")
    password := c.PostForm("password")

    // 1.判断验证码是否验证成功: 这里调用的是上一节验证码微服务的功能
    if flag := models.VerifyCaptcha(captchaId, verifyValue); flag {
        //2.查询数据库,判断用户以及密码是否正确
        userinfo := []models.Manager{}
        password = models.Md5(password)
        models.DB.Where("username = ? and password = ? ", username, password).Find(&userinfo)
        if len(userinfo) > 0 {
            //3.执行登录,保存用户信息,执行跳转操作
            session := sessions.Default(c)
            //注意: session.Set没法保存结构体对应的切片,所以需要把结构体转换成json字符串
            userinfoSlice, _ := json.Marshal(userinfo)
            session.Set("userinfo_admin", string(userinfoSlice))
            session.Save()
            con.Success(c, "登录成功", "/admin")
        } else {
            con.Error(c, "用户名或密码错误", "/admin/login")
        }
    } else {
        con.Error(c, "验证码验证失败", "/admin/login")
    }
}

从上面可以看出:在权限管理Rbac微服务中要实现:

//2.查询数据库,判断用户以及密码是否正确
userinfo := []models.Manager{}
password = models.Md5(password)
models.DB.Where("username = ? and password = ? ", username, password).Find(&userinfo)

而实现上面的逻辑,则需要连接数据库,创建数据模型,这里使用GORM方式

(1).创建数据模型

在models下创建manager.go,可参考[golang gin框架] 13.Gin 商城项目-配置公共基类实现公共的成功,失败提示页面 用户登录、退出登录、以及权限判断

package models

//管理员表

type Manager struct { // 结构体首字母大写, 和数据库表名对应, 默认访问数据表users, 可以设置访问数据表的方法
	Id  int
	Username string
	Password string
	Mobile string
	Email string
	Status int
	RoleId int
	AddTime int
	IsSuper int
}

//配置数据库操作的表名称
func (Manager) TableName() string {
	return "manager"
}

(2).创建conf/app.ini文件

在微服务项目Rbac下创建conf/app.ini配置文件,一些配置,如:数据库配置,redis配置,consul配置信息都可以放到该文件下,以便使用,使用了这个文件下的配置,改变里面的数据不用重启项目,具体参考:[golang gin框架] 9.Gin GORM 中使用事务以及go-ini加载.ini配置文件

app_name   = rbac
# possible values: DEBUG, INFO, WARNING, ERROR, FATAL

[mysql]
ip       = 127.0.0.1
port     = 3306
user     = root
password = 123456
database = ginshop

[consul]
#指定微服务的ip,一般一个微服务对应一台服务器,当在同一台服务器上有多个微服务时,以不同端口区分
addr   = localhost:8082

(3).定义initInt.go文件

在models下创建initInt.go文件,自动初始化app.ini,很多地方调用app.ini时,就可以从这里介入,该文件目的是减少代码的复用

package models

//自动初始化app.ini:这里很多地方都要用到

import (
	"fmt"
	"os"
	"gopkg.in/ini.v1"
)

var Config *ini.File
var iniErr error

func init() {
	Config, iniErr = ini.Load("./conf/app.ini")
	if iniErr != nil {
		fmt.Printf("Fail to read file: %v", iniErr)
		os.Exit(1)
	}
}

 (4).创建initMysql.go

在models下创建initMysql.go文件,该文件目的是创建mysql数据库连接引擎

package models

//https://gorm.io/zh_CN/docs/connecting_to_the_database.html
//微服务项目中: 推荐一个微服务对应一个数据库
import (
	"fmt"
	"gorm.io/driver/mysql"
	"gorm.io/gorm"
)

var DB *gorm.DB
var err error

func init() {
	//读取.ini里面的数据库配置,相关配置从initIni.go中读取
	ip := Config.Section("mysql").Key("ip").String()
	port := Config.Section("mysql").Key("port").String()
	user := Config.Section("mysql").Key("user").String()
	password := Config.Section("mysql").Key("password").String()
	database := Config.Section("mysql").Key("database").String()

	// dsn := "root:123456@tcp(192.168.0.6:3306)/gin?charset=utf8mb4&parseTime=True&loc=Local"
	dsn := fmt.Sprintf("%v:%v@tcp(%v:%v)/%v?charset=utf8mb4&parseTime=True&loc=Local", user, password, ip, port, database)
	DB, err = gorm.Open(mysql.Open(dsn), &gorm.Config{
		QueryFields: true, //打印sql
		//SkipDefaultTransaction: true, //禁用事务
	})
	// DB.Debug()
	if err != nil {
		fmt.Println(err)
	}
}

 (5).编写proto/rbac.proto文件

编写proto/rbac.proto文件,实现微服务相关数据逻辑,可参考:[golang gin框架] 39.Gin商城项目-微服务实战之微服务架构

syntax = "proto3";

package rbac;

option go_package = "./proto/rbac";

service Rbac {
    //登录操作
	rpc Login(LoginRequest) returns (LoginResponse) {}
}

//用户信息model:参考models/manager.go,一一对应
message ManagerModel{
	int64 id=1;
	string username=2;
	string password=3;
	string mobile=4;
	string email=5;
	int64 status=6;
	int64 roleId=7;
	int64 addTime=8;
	int64 isSuper=9;
}

//登录请求参数
message LoginRequest{
	string username=1;
	string password=2;
}

//登录返回参数
message LoginResponse{
	bool isLogin=1;
	repeated ManagerModel userlist=2;  //因为在client端需要返回用户相关信息userinfo,故定义一个切片
}

(6).生成proto相关文件

参考[golang 微服务] 7. go-micro框架介绍,go-micro脚手架,go-micro结合consul搭建微服务案例,windows下运行 Makefile里面的proto下的代码 :protoc --proto_path=. --micro_out=. --go_out=:. proto/captcha.proto, 当然,如果是初次使用go-micro,则还需运行init下面的代码(@go xxx),引入相关包

   

(7).初始化服务端项目

初始化项目,引入项目所需要的包

go mod init rbac
go mod tidy

如果出现:

F:\www\go-data\src\go_code\micro\shop\server\rbac>go mod tidy
go: finding module for package go-micro.dev/v4/client
go: finding module for package gopkg.in/ini.v1
go: finding module for package go-micro.dev/v4
go: finding module for package go-micro.dev/v4/logger
go: finding module for package go-micro.dev/v4/server
go: finding module for package gorm.io/gorm
go: finding module for package gorm.io/driver/mysql
go: finding module for package go-micro.dev/v4/api
go: finding module for package google.golang.org/protobuf/proto
go: finding module for package google.golang.org/protobuf/reflect/protoreflect
go: finding module for package google.golang.org/protobuf/runtime/protoimpl
go: found go-micro.dev/v4 in go-micro.dev/v4 v4.10.2
go: found go-micro.dev/v4/logger in go-micro.dev/v4/logger v1.18.0
go: found gopkg.in/ini.v1 in gopkg.in/ini.v1 v1.67.0
go: found gorm.io/driver/mysql in gorm.io/driver/mysql v1.5.1
go: found gorm.io/gorm in gorm.io/gorm v1.25.2
go: found go-micro.dev/v4/api in go-micro.dev/v4/api v1.18.0
go: found go-micro.dev/v4/client in go-micro.dev/v4/client v1.18.0
go: found go-micro.dev/v4/server in go-micro.dev/v4/server v1.18.0
go: found google.golang.org/protobuf/proto in google.golang.org/protobuf v1.31.0
go: found google.golang.org/protobuf/reflect/protoreflect in google.golang.org/protobuf v1.31.0
go: found google.golang.org/protobuf/runtime/protoimpl in google.golang.org/protobuf v1.31.0
go: rbac/proto/rbac imports
        go-micro.dev/v4/api: go-micro.dev/v4/api@v1.18.0: parsing go.mod:
        module declares its path as: github.com/micro/go-micro
                but was required as: go-micro.dev/v4/api

说明下载"go-micro.dev/v4"这个包失败了,这时则需运行命令 go get go-micro.dev/v4,如图:

 然后再次执行go mod tidy就可以了,这样项目中import包就会引入,不会变红

(8).编写handler/rbac.go用户登录微服务逻辑

因为要实现

//2.查询数据库,判断用户以及密码是否正确
userinfo := []models.Manager{}
password = models.Md5(password)
models.DB.Where("username = ? and password = ? ", username, password).Find(&userinfo)
		

所以在handler/rbac.go 中需要返回用户相关信息,实现用户登录逻辑代码如下:

package handler

import (
	"context"
	"rbac/models"
	pb "rbac/proto/rbac"
)

type Rbac struct{}

//后台用户登录的微服务
func (e *Rbac) Login(ctx context.Context, req *pb.LoginRequest, res *pb.LoginResponse) error {
	managerList := []models.Manager{}
	err := models.DB.Where("username=? AND password=?", req.Username, req.Password).Find(&managerList).Error

	//处理数据
	var templist []*pb.ManagerModel
	for i := 0; i < len(managerList); i++ {
		templist = append(templist, &pb.ManagerModel{
			Id:       int64(managerList[i].Id),
			Username: managerList[i].Username,
			Password: managerList[i].Password,
			Mobile:   managerList[i].Mobile,
			Email:    managerList[i].Email,
			Status:   int64(managerList[i].Status),
			RoleId:   int64(managerList[i].RoleId),
			AddTime:  int64(managerList[i].AddTime),
			IsSuper:  int64(managerList[i].IsSuper),
		})
	}
	if len(managerList) > 0 {
		res.IsLogin = true
	} else {
		res.IsLogin = false
	}
	res.Userlist = templist

	return err
}

(9).配置consul服务发现 

在main.go配置consul服务发现

package main

import (
	"rbac/handler"
	"rbac/models"
	pb "rbac/proto/rbac"
	"go-micro.dev/v4"
	"go-micro.dev/v4/logger"
	"github.com/go-micro/plugins/v4/registry/consul"
)

var (
	service = "rbac"
	version = "latest"
)

func main() {
	//集成consul
	consulReg := consul.NewRegistry()
	// Create service

	//读取.ini里面的配置
	addr := models.Config.Section("consul").Key("addr").String()

	srv := micro.NewService(
		micro.Address(addr),  //指定微服务的ip:  选择注册服务器地址,也可以不配置,默认为本机,也可以选择consul集群中的client
		micro.Name(service),
		micro.Version(version),
		//注册consul
		micro.Registry(consulReg),
	)
	srv.Init(
		micro.Name(service),
		micro.Version(version),
	)

	// Register handler
	if err := pb.RegisterRbacHandler(srv.Server(), new(handler.Rbac)); err != nil {
		logger.Fatal(err)
	}
	// Run service
	if err := srv.Run(); err != nil {
		logger.Fatal(err)
	}
}

3.启动consul服务发现

在cmd中运行命令: consul agent -dev,具体参考:  [golang 微服务] 5. 微服务服务发现介绍,安装以及consul的使用,Consul集群

4.注册验证码微服务服务端到服务发现(consul)

rbac目录下运行go run main.go,然后在consul UI 查看,是否注册成功

注册成功了 

 三.创建权限管理Rbac微服务客户端

1.首先把server/rbac/proto文件夹复制到项目中

2.配置consul服务发现

在models下创建initRbacConsul.go,配置consul服务发现,以便调用,代码如下:

package models

//Rbac consul(服务发现)初始化配置
//微服务客户端配置: 初始化consul配置,当一个项目中多个微服务时,就很方便了
//建议:一个微服务对应一个客户端,这样好管理

import (
	"github.com/go-micro/plugins/v4/registry/consul"
	"go-micro.dev/v4"
	"go-micro.dev/v4/client"
	"go-micro.dev/v4/registry"
)

//RbacClient: 全局变量 在外部的包中可以调用
var RbacClient client.Client

//init 方法: 当程序运行时就会自动执行
func init() {
	consulRegistry := consul.NewRegistry(
		//指定微服务的ip:  选择注册服务器地址,默认为本机,也可以选择consul集群中的client,建议一个微服务对应一个consul集群的client
		registry.Addrs("127.0.0.1:8500"),
	)
	// Create service
	srv := micro.NewService(
		micro.Registry(consulRegistry),
	)
	srv.Init()

	RbacClient = srv.Client()
}

 在这里,也许没有引入,执行命令:go mod tidy引入对应的包

3.调用Rbac微服务 

controllers/login.goDoIndex方法中调用Rbac微服务 

原DoIndex方法代码如下: 


//执行登录操作
func (con LoginController) DoIndex(c *gin.Context) {
	//获取表单中的数据
	captchaId := c.PostForm("captchaId")     // 验证码id
	verifyValue := c.PostForm("verifyValue") //验证码的值
	//获取用户名以及密码
	username := c.PostForm("username")
	password := c.PostForm("password")

	// 1.判断验证码是否验证成功
	if flag := models.VerifyCaptcha(captchaId, verifyValue); flag {
		//2.查询数据库,判断用户以及密码是否正确
		userinfo := []models.Manager{}
		password = models.Md5(password)
		models.DB.Where("username = ? and password = ? ", username, password).Find(&userinfo)
		if len(userinfo) > 0 {
			//3.执行登录,保存用户信息,执行跳转操作
			session := sessions.Default(c)
			//注意: session.Set没法保存结构体对应的切片,所以需要把结构体转换成json字符串
			userinfoSlice, _ := json.Marshal(userinfo)
			session.Set("userinfo_admin", string(userinfoSlice))
			session.Save()
			con.Success(c, "登录成功", "/admin")
		} else {
			con.Error(c, "用户名或密码错误", "/admin/login")
		}
	} else {
		con.Error(c, "验证码验证失败", "/admin/login")
	}
}

 然后在//2.查询数据库,判断用户以及密码是否正确这一步调用Rbac微服务,代码修改如下:

//这里需要import (
//     "context"
//	 pbRbac "goshop/proto/rbac"
//    )

//执行登录操作
func (con LoginController) DoIndex(c *gin.Context) {
	//获取表单中的数据
	captchaId := c.PostForm("captchaId")     // 验证码id
	verifyValue := c.PostForm("verifyValue") //验证码的值
	//获取用户名以及密码
	username := c.PostForm("username")
	password := c.PostForm("password")

	// 1.判断验证码是否验证成功
	if flag := models.VerifyCaptcha(captchaId, verifyValue); flag {
		//2.查询数据库,判断用户以及密码是否正确
		//userinfo := []models.Manager{}
		//password = models.Md5(password)
		//models.DB.Where("username = ? and password = ? ", username, password).Find(&userinfo)
		//调用Rbac微服务
		rbacClient := pbRbac.NewRbacService("rbac", models.RbacClient)
		res, _ := rbacClient.Login(context.Background(), &pbRbac.LoginRequest{
			Username: username,
			Password: models.Md5(password),
		})
		//通过Rbac微服务结果,判断是否登录
		if res.IsLogin {
			//3.执行登录,保存用户信息,执行跳转操作
			session := sessions.Default(c)
			//注意: session.Set没法保存结构体对应的切片,所以需要把结构体转换成json字符串
			userinfoSlice, _ := json.Marshal(res.Userlist)  //res.Userlist:微服务返回的用户信息
			session.Set("userinfo_admin", string(userinfoSlice))
			session.Save()
			con.Success(c, "登录成功", "/admin")
		} else {
			con.Error(c, "用户名或密码错误", "/admin/login")
		}
	} else {
		con.Error(c, "验证码验证失败", "/admin/login")
	}
}

好了,权限管理Rbac微服务服客户端代码就ok了,接下来验证Rbac微服务是否成功

四.校验权限管理Rbac微服务功能

1.先启动服务端

见 [golang gin框架] 40.Gin商城项目-微服务实战之Captcha验证码微服务代码, 这里还要启动验证码captcha微服务服务端代码才行

2.启动客户端

在项目根目录下运行 :go run main.go,启动项目

3.校验权限管理Rbac微服务操作是否成功 

访问后台登录页面,输入用户名,密码,验证码,看看是否成功 

 

 好了,权限管理Rbac微服务后台用户登录功能客户端操作完成,这里微服务操作的服务端,客户端功能大致与[golang gin框架] 40.Gin商城项目-微服务实战之Captcha验证码微服务类似,可参考该文章操作,下面一节继续讲解权限管理Rbac微服务的角色增删改查微服务功能

 [上一节][golang gin框架] 40.Gin商城项目-微服务实战之Captcha验证码微服务

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

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

相关文章

视频画面尺寸怎么裁剪?裁剪视频画面方法分享

如果我们的视频将在不同的平台或设备上播放&#xff0c;而这些设备具有不同的屏幕比例&#xff08;如16:9、4:3、1:1等&#xff09;&#xff0c;则可能需要裁剪来适应目标屏幕。这样观看起来会体验效果更佳&#xff0c;但是该怎么裁剪视频的画面呢&#xff1f;给大家分享几种裁…

力扣热门100题之最长连续序列【中等】

题目描述 给定一个未排序的整数数组 nums &#xff0c;找出数字连续的最长序列&#xff08;不要求序列元素在原数组中连续&#xff09;的长度。 请你设计并实现时间复杂度为 O(n) 的算法解决此问题。 示例 1&#xff1a; 输入&#xff1a;nums [100,4,200,1,3,2] 输出&…

Kotlin多平台最佳架构指南

在这篇文章中&#xff0c;我们将对 Kotlin 多平台移动端的最佳架构进行深入探讨。在2023年&#xff0c;作为 Android 开发者&#xff0c;我们会倾向于采用 MVVM 架构&#xff0c;因为它简单、灵活且易于测试。而作为 iOS 开发者&#xff0c;我们可能会选择 MVC、Viper 等架构。…

解决FLink:Missing required options are: slot.name

[ERROR] Could not execute SQL statement. Reason: org.apache.flink.table.api.ValidationException: One or more required options are missing.Missing required options are:slot.name解决 https://ververica.github.io/flink-cdc-connectors/release-2.4/content/connec…

JSR 规范详解和概述

JSR 规范详解 目录概述需求&#xff1a; 设计思路实现思路分析1.JSR 规范详解 参考资料和推荐阅读 Survive by day and develop by night. talk for import biz , show your perfect code,full busy&#xff0c;skip hardness,make a better result,wait for change,challenge …

Python计算特征值与特征向量案例+传统方法+雅可比Jacobi迭代法

目录 {1}几个例子&#x1f330; {2}特征值 {3}奇异矩阵 {4}特征向量 {5}特征值和特征向量的计算方法 特征值性质 特征向量性质 {6}巩固练习 {7}迭代法 什么时候收敛&#xff1f;收敛速度如何&#xff1f; {8}雅可比迭代法 {1}几个例子&#x1f330; 例1&#xff…

Moshi Vs Gson Vs Kotlin Serialisation性能PK

Moshi Vs Gson Vs Kotlin Serialisation 定义 Gson Gson 是一个Java序列化/反序列化库&#xff0c;用于将Java对象转换为JSON格式&#xff0c;以及将JSON格式转换回Java对象。 Moshi Moshi 是一个现代化的JSON库&#xff0c;适用于Android和Java。它使得将JSON解析为Java对…

Django基本数据库操作

Django基本数据库操作 文章目录 Django基本数据库操作&#x1f468;‍&#x1f3eb;内容一&#xff1a;基本数据库配置&#x1f468;‍&#x1f52c;内容二&#xff1a;ORM基本操作 &#x1f468;‍&#x1f3eb;内容一&#xff1a;基本数据库配置 &#x1f449;Django是一个流…

整车总线系列——FlexRay 四

整车总线系列——FlexRay 四 我是穿拖鞋的汉子&#xff0c;魔都中坚持长期主义的汽车电子工程师。 老规矩&#xff0c;分享一段喜欢的文字&#xff0c;避免自己成为高知识低文化的工程师&#xff1a; 没有人关注你。也无需有人关注你。你必须承认自己的价值&#xff0c;你不能…

机器学习方法与原则

机器学习方法与原则 评价指标 TODO 训练集、验证集与测试集 训练集与测试集 训练集&#xff08;作业&#xff09;&#xff1a; 模型可见样本标签&#xff0c;用于训练模型&#xff0c;样本数量有限。 在训练集上表现好的模型&#xff0c; 在其它未见样本上一定表现好么&am…

【Java】Clonable 接口

如何克隆一个引用所指的对象呢&#xff1f;首先一个前提&#xff0c;他是可克隆的&#xff0c;我们要实现一个Clonable 接口。我们来看一个这个接口&#xff1a; 可以发现里面是空的&#xff0c;我们把这种空接口叫做标记接口&#xff0c;作用就是表示当前对象是可以被克隆的。…

面试 | 双法妙解压缩字符串【遍历统计 + 双指针】

一、题目描述 原题传送门 二、思路分析 首先我们来分析一下解决本题所需要的思路 题目的意思很简单&#xff0c;就是统计原本的字符串中的每个字符出现的次数&#xff0c;然后以【字符&#xff0c;出现的次数】这样的结构来字符串&#xff0c;以起到一个压缩的效果&#xff0c…

Fiddler抓包实战,彻底打通接口测试(二)

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 请求查看 Inspec…

Spring简述IOC入门案例

文章目录 Spring学习笔记Spring&#xff1a;Spriing framework:IoC&#xff08;控制反转&#xff09;对象的创建控制权由程序转移到外部&#xff1a;DI( Dependency Injection )依赖注入&#xff1a; IoC入门案例&#xff1a;项目结构&#xff1a;applicationContext.xml:bookD…

mysql-5.7 Linux安装教程

通过命令下载&#xff1a; 下载到 cd /usr/local 这个路径下 wget http://dev.mysql.com/get/Downloads/MySQL-5.7/mysql-5.7.36-linux-glibc2.12-x86_64.tar.gz 解压&#xff1a; tar -zxvf mysql-5.7.36-linux-glibc2.12-x86_64.tar.gz 将解压的 重命名 为mysql mv mysql-5…

B/S架构的云HIS系统源码 技术架构:Angular+Nginx+ Java+Spring

基于云计算技术的B/S架构的HIS系统源码&#xff0c;为基层医疗机构提供标准化的、信息化的、可共享的医疗信息管理系统&#xff0c;实现医患事务管理和临床诊疗管理等标准医疗管理信息系统的功能。系统利用云计算平台的技术优势&#xff0c;建立统一的健康档案存储平台&#xf…

seatunnel hive source 未设置分隔符导致多个字段合并成一个的问题定位解决

seatunnel hive source 未设置分隔符导致多个字段没有切分全保存在一个字段中了,翻看源码发现分隔符是是通过delimiter设置的,只要设置这个delimiter","就可以了。 设置这个属性 delimiter“,” 他的默认值是\u0001,如果没有设置delimiter属性则会根据文件类型判断…

Flink写入数据到Doris

文章目录 1.Doris建表2.Doris依赖3.Bean实体类4.Doris业务写入逻辑5.测试写入类6.发送数据 1.Doris建表 Doris中建表 CREATE TABLE IF NOT EXISTS demo.user (id INT NOT NULL,name VARCHAR(255),age INT ) DISTRIBUTED BY HASH(id) PROPERTIES ("replication_num&qu…

前端工程化第三章:webpack5基础(下)

文章目录 1. TypeScript支持&#xff08;ts-loader&#xff09;1.1. ts-loader1.1.1. webpack.config.js1.1.2. tsconfig.json1.1.3. src/index.ts 1.2. 使用babel-loader将ts转换为js1.2.1. webpack.config.js1.2.2. src/index.ts 2. 代码规范检查&#xff08;Eslint&#xff…

「深度学习之优化算法」(十八)头脑风暴算法

1. 头脑风暴算法简介 (以下描述,均不是学术用语,仅供大家快乐的阅读)   可能大家对“头脑风暴”这个词不怎么熟,毕竟是外来词汇,其大概含义就是分组讨论,畅所欲言。   头脑风暴算法(Brain Storm Optimization)是根据人们进行“头脑风暴”讨论困难问题的解决方案的过…