淘宝做导航网站好自己用电脑做网站服务器吗

当前位置: 首页 > news >正文

淘宝做导航网站好,自己用电脑做网站服务器吗,免费软件 全免费,深入解析wordpress…分别实现了redigo中自动加前缀和session中自动加前缀 等有空了整理一个demo放到github上#xff0c;到时候求个小星星 在gin-contrib/sessions/redis库中redis的前缀是被封装起来了#xff0c;所以自定义前缀没有内部方法在这里我们自己实现一下NewStoreWithDBPrefix方法配…分别实现了redigo中自动加前缀和session中自动加前缀 等有空了整理一个demo放到github上到时候求个小星星 在gin-contrib/sessions/redis库中redis的前缀是被封装起来了所以自定义前缀没有内部方法在这里我们自己实现一下NewStoreWithDBPrefix方法配置文件可以看到引用的redis配置这样方面多个项目在同一个redis中方便管理也方便做单点登录 项目目录 app/ ├── common/ │ ├── global/ │ ├──── global.go ├── config/ │ ├── application.yaml ├── initialize/ │ ├── config.go │ ├── initialize.go │ ├── redis.go │ ├── store.go ├── middleware/ │ ├── middleware.go ├── router/ │ ├── router.go ├── main.go下面是代码实现 配置文件config/application.yaml redis: redisConfigaddr: 127.0.0.1port: 6379password: 123456db: 3size: 20max-idle: 24active: 10auth: trueprefix: demotimeout: 180 store:size: 10redis: *redisConfigkey-pairs: sessionKey全局变量common/global/global.go package globalimport (demo/configgithub.com/gin-contrib/sessionsgithub.com/robfig/cron/v3github.com/garyburd/redigo/redisut github.com/go-playground/universal-translatorgithub.com/jordan-wright/emailgo.uber.org/zapgorm.io/gorm )var (CONFIG config.ConfigDB *gorm.DBTrans *ut.TranslatorREDISPoll *redis.PoolRootDir stringEmailPool *email.PoolStore *sessions.StoreLogger *zap.SugaredLoggerCron cron.Cron ) 配置文件初始化initialize/config.go package initializeimport (fmtio/ioutillogospath/filepathstringsdemo/common/globaldemo/configgithub.com/joho/godotenvgopkg.in/yaml.v2 )/** 读取配置文件,最先被初始化*/func InitilizeConfig() {// 获取当前工作目录rootDir, err : os.Getwd()if err ! nil {log.Fatalf(Failed to get current working directory: %s, err)}// 这是单元测试if strings.HasSuffix(rootDir, service) || strings.HasSuffix(rootDir, command) || strings.HasSuffix(rootDir, util) || strings.HasSuffix(rootDir, model) {rootDir filepath.Dir(rootDir)}if strings.HasSuffix(rootDir, oss) {rootDir filepath.Dir(filepath.Dir(rootDir))}// rootDir /Users/dupeisheng.vendor/go/src/gitlab.bj.sensetime.com/entrymanage// 设置工作目录if err : os.Chdir(rootDir); err ! nil {log.Fatalf(Failed to change working directory: %s, err)}fmt.Println(工作目录, rootDir)// 加载.envgodotenv.Load(.env)// 设置当前环境mode : os.Getenv(Mode)fmt.Println(当前环境, mode)if mode ! {mode - mode}// 加载配置文件configPath : rootDir /config/application mode .yamlyamlFile, err : ioutil.ReadFile(configPath)if err ! nil {log.Panicf(Failed to read file , cause is %s, err.Error())}config : config.Config{}err yaml.Unmarshal(yamlFile, config)global.CONFIG configif err ! nil {fmt.Println(err.Error())} } session初始化initialize/store.go package initializeimport (fmtdemo/common/globalgithub.com/boj/redistoregithub.com/gin-contrib/sessionsgithub.com/gin-contrib/sessions/redisgithub.com/spf13/cast )const SessionMaxAge 8 * 3600func InitilizeStore() {var Store sessions.StoreStore, err : NewStoreWithDBPrefix(global.CONFIG.Store.Size,tcp,global.CONFIG.Store.Redis.Addr:global.CONFIG.Store.Redis.Port,global.CONFIG.Store.Redis.Password,cast.ToString(global.CONFIG.Store.Redis.Db),// []byte(global.CONFIG.Store.Redis.Prefix),[]byte(global.CONFIG.Store.KeyPairs),)if err ! nil {fmt.Println(创建Session-Redis存储失败 err.Error())}Store.Options(sessions.Options{MaxAge: SessionMaxAge,})global.Store Store }type store struct {*redistore.RediStore }func NewStoreWithDBPrefix(size int, network, address, password, DB string, keyPairs …[]byte) (redis.Store, error) {s, err : redistore.NewRediStoreWithDB(size, network, address, password, DB, keyPairs…)if err ! nil {return nil, err}// 这里设置前缀s.SetKeyPrefix(global.CONFIG.Store.Redis.Prefix :session:)return store{s}, nil }func (c store) Options(options sessions.Options) {c.RediStore.Options options.ToGorillaOptions() }redis初始化initialize/redis.go package initializeimport (fmtlogstringstimedemo/common/globaldemo/configgithub.com/garyburd/redigo/redisgithub.com/samber/logithub.com/spf13/cast )/** 初始化redis并赋值给全局变量*/func InitilizeRedis() {// 创建redis连接池global.REDISPoll GetRedisPool(global.CONFIG) }func GetRedisPool(config config.Config) *redis.Pool {return redis.Pool{MaxIdle: config.Redis.MaxIdle, // 最大空闲连接数MaxActive: config.Redis.Active, // 最大连接数IdleTimeout: time.Duration(config.Redis.Timeout) * time.Second,Wait: true, // 超过连接数后是否等待Dial: func() (redis.Conn, error) {redisUri : fmt.Sprintf(%s:%s, config.Redis.Addr, config.Redis.Port)var redisConn redis.Connvar err errorif config.Redis.Auth {redisConn, err redis.Dial(tcp, redisUri, redis.DialPassword(config.Redis.Password))} else {redisConn, err redis.Dial(tcp, redisUri)}if err ! nil {log.Println(获取连接失败: err.Error())return nil, err}// 添加 Redis 前缀if config.Redis.Prefix ! {redisConn PrefixedConn{Conn: redisConn, config: config.Redis}}return redisConn, nil},TestOnBorrow: func(c redis.Conn, t time.Time) error {if time.Since(t) time.Minute {return nil}, err : c.Do(PING)return err},} }// PrefixedConn 是一个实现了 redis.Conn 接口的自定义结构体它在键名前添加了前缀 type PrefixedConn struct {redis.Connconfig config.Redis }// 允许适配前缀的命令 var commandsWithPrefix []string{GET, SET, EXISTS, DEL, TYPE,RPUSH, LPOP, RPOP, LLEN, LRANGE,SADD, SREM, SISMEMBER, SMEMBERS, SCARD,HSET, HMSET, HGET, HGETALL,ZADD, ZRANGE, ZRANGEBYSCORE, ZREVRANGEBYSCORE, ZREM,INCR, INCRBY,WATCH, MULTI, EXEC, EXPIRE, }// Do 实现了 redis.Conn 接口的 Do 方法 func (c *PrefixedConn) Do(command string, args …any) (any, error) {// 执行命令前切换到数据库if , err : c.Conn.Do(SELECT, c.config.Db); err ! nil {return nil, err}command strings.ToUpper(command)// 判断是不是单独实现了命令 不用反射吧-性能问题switch command {case MGET:return c.MGET(args…)case MSET:return c.MSET(args…)}// 加前缀if len(args) 0 {key : args[0].(string)if lo.IndexOfstring ! -1 key ! {args[0] c.config.Prefix : key}}return c.Conn.Do(command, args…) }// MGET 实现了批量获取命令 func (c *PrefixedConn) MGET(args …any) (interface{}, error) {for i : range args {args[i] c.config.Prefix : cast.ToString(args[i])}return c.Conn.Do(MGET, args…) }// MSET 实现了批量设置命令 func (c *PrefixedConn) MSET(args …any) (interface{}, error) {for i : range args {if i%2 0 {args[i] c.config.Prefix : cast.ToString(args[i])}}return c.Conn.Do(MSET, args…) } gin路由router/router.go package routerimport (github.com/gin-contrib/corsgithub.com/gin-contrib/sessionsgithub.com/gin-gonic/gin ) // InitRouters 初始化路由 func InitRouters() *gin.Engine {// 创建默认带中间件的路由 Logger、Recoveryr : gin.Default()// 允许跨域r.Use(cors.Default())r.Use(sessions.Sessions(sessionID, *global.Store)) }下面是单点登录实现逻辑 middleware/middleware.go package middlewareimport (encoding/jsonnet/httpmyerror demo/common/errordemo/common/globaldemo/modeldemo/utilgithub.com/gin-contrib/sessionsgithub.com/gin-gonic/gingithub.com/gomodule/redigo/redisgithub.com/spf13/cast )const UserSessionExpireDuration 8 * 3600 const UserSessionMapPrefix session:user:type SessionData struct {Member model.Member json:member }// 保存登录信息 func GenerateSession(c *gin.Context, sessionData SessionData) error {c.Request.Header.Set(Cookie, )redisConn : global.REDISPoll.Get()defer redisConn.Close()sessionKey : UserSessionMapPrefix cast.ToString(sessionData.Member.ID)// 单点登录删除旧的登录态oldSessionID, err : redis.String(redisConn.Do(get, sessionKey))if err ! nil err ! redis.ErrNil {return err}, err redisConn.Do(del, oldSessionID)if err ! nil {return err}// 保存用户相关token : cast.ToString(sessionData.Member.ID) sessionData.Member.Name util.Md5(util.GetUUID()util.RandString(20))session : sessions.Default©by, err : json.Marshal(sessionData)if err ! nil {return err}session.Set(authenticated, true)session.Set(data, by)session.Set(member_id, sessionData.Member.ID)session.Set(membername, sessionData.Member.Name)session.Set(token, token)session.Save()sessionVal : session: session.ID(), err redisConn.Do(set, sessionKey, sessionVal, EX, UserSessionExpireDuration)return err }// 身份验证 func Authentication(ctx *gin.Context) {session : sessions.Default(ctx)if auth, ok : session.Get(authenticated).(bool); !ok || !auth {ctx.JSON(http.StatusUnauthorized, gin.H{code: myerror.SERVER_UNAUTHORIZED_ERROR,msg: myerror.SERVER_UNAUTHORIZED_ERROR.String(),})ctx.Abort()return}session.Save()// 保存用户相关信息到ctxmemberId : session.Get(member_id)memberName : session.Get(member_name)data : session.Get(data)var sessionData SessionDataif data ! nil {by : data.([]byte)err : json.Unmarshal(by, sessionData)if err ! nil {ctx.JSON(http.StatusUnauthorized, gin.H{code: myerror.SERVER_SYSTEM_ERROR,msg: myerror.SERVER_SYSTEM_ERROR.String(),})ctx.Abort()return}}ctx.Set(member_id, memberId)ctx.Set(member_name, memberName)ctx.Set(member_info, sessionData.Member)ctx.Set(data, data)// 登录续时redisConn : global.REDISPoll.Get()defer redisConn.Close()sessionKey : UserSessionMapPrefix cast.ToString(memberId)sessionVal : session: session.ID()redisConn.Do(set, sessionKey, sessionVal, EX, UserSessionExpireDuration)ctx.Next() }