[golang Web开发] 5.golang web开发:会话控制(Cookie,Session),处理静态资源

        http是无状态协议,服务器不能记录浏览器的访问状态,也就是说服务器不能区分中两次请求是否由一个客户端发出.这样的设计严重阻碍的 Web 程序的设计,如:在进行网购时,买了一条裤子,又买了一个手机,由于 http协议是无状态的,如果不通过其他手段,服务器是不能知道用户到底买了什么,而cookie就是解决方案之一.

一.Cookie

1.简介

        Cookie 实际上就是服务器保存在浏览器上的一段信息,浏览器有了Cookie之后,每次向服务器发送请求时都会同时将该信息发送给服务器,服务器收到请求后,就可以根据该信息处理请求

Cookie类型如下: 

2.cookie的运行原理

(1).第一次向服务器发送请求时在服务器端创建 Cookie

(2).将在服务器端创建的Cookie以响应头的方式发送给浏览器

(3).以后再发送请求时,浏览器就会携带着该Cookie

(4).服务器得到Cookie之后根据Cookie的信息来区分不同的用户

3.创建cookie并将它发送给浏览器

 

4.获取cookie

5.cookie的用途

(1).广告推荐

(2).免登录

二.Session

1.简介

        Cookie有一个非常大的局限,就是如果Cookie 很多,则无形的增加了客户端与服务端的数据传输量,而且由于浏览器对Cookie 数量的限制,注定不能在Cookie 中保存过多的信息,于是 Session 出现

        Session的作用就是在服务器端保存一些用户的数据,然后传递给用户一个特殊的 Cookie,  这个Cookie对应着这个服务器中的一个Session,通过它就可以获取到保存用户信息的 Session ,进而就知道是哪个用户在发送请求

        当然,由于 Session 存储在服务器中,肯定会消耗服务器的资源,所以 Session 一般都会有一个过期时间,服务器一般会定期检查并删除过期的 Session ,如果后来该用户再次访问服务器,可能就会面临重新登录等等措施,然后服务器新建一个 Session ,将 Session ID 通过 Cookie 的形式传送给客户端

2.运行原理

(1).第一次向服务器发送请求时创建Session,给它设置一个全局唯一的 ID (可以通过 UUID 生成)

(2).创建一个Cookie,将Cookie 的Value 设置为 Session 的ID值,并将 Cookie 发送给浏览器 · (3).以后再发送请求浏览器就会携带着该 Cookie

(4).服务器获取Cookie并根据它的 Value 值找到服务器中对应的 Session,也就知道了请求是哪个用户发的

3.实现

Session一般需要三个组件配合完成,它们分别是 ManagerProvider 和 Session 三个类(接口)

步骤:

(1).浏览器通过 HTTP 协议向服务器请求路径 /content 的网页资源,对应路径上有一个 Handler 函数接收请求,解析 HTTP header 中的 cookie,得到其中存储的 sessionID,然后把这个 ID 发给 Manager

(2).Manager 充当一个 session 管理器的角色,主要存储一些配置信息,比如 session 的存活时间,cookie 的名字等等。而所有的 session 存在 Manager 内部的一个 Provider 中。所以 Manager 会把 sid(sessionID)传递给 Provider,让它去找这个 ID 对应的具体是哪个 session

(3).Provider 就是一个容器,最常见的应该就是一个散列表,将每个 sid 和对应的 session一一映射起来。收到 Manager 传递的 sid 之后,它就找到 sid 对应的 session 结构,也就是 Session 结构,然后返回它

(4).Session 中存储着用户的具体信息,由 Handler 函数中的逻辑拿出这些信息,生成该用户的 HTML 网页,返回给客户端

下面就来说说,为什么分成 ManagerProvider 和 Session

先从最底层的 Session 说。既然 session 就是键值对,为啥不直接用哈希表,而是要抽象出这么一个数据结构呢?

第一,因为 Session 结构可能不止存储了一个哈希表,还可以存储一些辅助数据,比如 sid,访问次数,过期时间或者最后一次的访问时间,这样便于实现想 LRU、LFU 这样的算法。

第二,因为 session 可以有不同的存储方式。如果用编程语言内置的哈希表,那么 session 数据就是存储在内存中,如果数据量大,很容易造成程序崩溃,而且一旦程序结束,所有 session 数据都会丢失。所以可以有很多种 session 的存储方式,比如存入缓存数据库 Redis,或者存入 MySQL 等等。

因此,Session 结构提供一层抽象,屏蔽不同存储方式的差异,只要提供一组通用接口操纵键值对:

type Session interface {
    // 设置键值对
    Set(key, val interface{})
    // 获取 key 对应的值
    Get(key interface{}) interface{}
    // 删除键 key
    Delete(key interface{})
}

再说 Provider 为啥要抽象出来。我们上面那个图的 Provider 就是一个散列表,保存 sid 到 Session 的映射,但是实际中肯定会更加复杂。我们不是要时不时删除一些 session 吗,除了设置存活时间之外,还可以采用一些其他策略,比如 LRU 缓存淘汰算法,这样就需要 Provider 内部使用哈希链表这种数据结构来存储 session,因此,Provider 作为一个容器,就是要屏蔽算法细节,以合理的数据结构和算法组织 sid 和 Session 的映射关系,只需要实现下面这几个方法实现对 session 的增删查改:

type Provider interface {
    // 新增并返回一个 session
    SessionCreate(sid string) (Session, error)
    // 删除一个 session
    SessionDestroy(sid string)
    // 查找一个 session
    SessionRead(sid string) (Session, error)
    // 修改一个session
    SessionUpdate(sid string)
    // 通过类似 LRU 的算法回收过期的 session
    SessionGC(maxLifeTime int64)
}

最后说 Manager,大部分具体工作都委托给 Session 和 Provider 承担了,Manager 主要就是一个参数集合,比如 session 的存活时间,清理过期 session 的策略,以及 session 的可用存储方式。Manager 屏蔽了操作的具体细节,我们可以通过 Manager 灵活地配置 session 机制

三.处理静态资源

对于HTMl页面中的css以及js等静态文件,需要使用net/http包下的StripPrefix函数,FileServer函数,FileSystem函数,Dir函数,Open等函数

index.html模板文件中引入的css样式的地址如下:

<link type="text/css" rel="stylesheet" href="static/css/style.css" />

main.go文件对静态文件的处理

http.Handler("/static/", http.StripPrefix("/static/", http.FileServer(http.Dir("views/static"))))

* /static/会匹配以 /static/ 开发的路径, 当浏览器请求index.html页面的style.css文件时,static前缀会被替换为views/static,然后去views/static/css目录中去查找style.css 

[上一节][golang Web开发] 4.golang web开发:模板引擎

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值