Session实现原理
客户对向服务器端发送请求后,Session 创建在服务器端,返回Sessionid给客户端浏览器保存在本地,
当下次发送请求的时候,在请求头中传递sessionId获取对应的从服务器上获取对应的Sesison
Session常见问题
Session 保证在那里?
答案:存放在服务器上
关闭浏览器Session会失效吗
答案:不会消失
我们开始分析SESSION的一个原理,这是要重点的去给大家讲的,SESSION的原理,我们在讲SESSION原理的时候要快一点,
localhost:8080/createSession?nameValue=zhangsan
http://localhost:8080/getSession
SESSION常见的问题,浏览器关闭了SESSION,SESSION会失效吗,这个是为空的,既然是为空的,在这里我们做一件事,
localhost:8080/createSession?nameValue=leon644,这个时候我们是不是可以把值存放进去了,这个时候我们再查一下,
http://localhost:8080/getSession, 8080-leon644,是不是查得到,这个是属于一个非常基础的知识,浏览器关闭session
会失效吗,这是第一个问题,第二个问题是SESSION存放在哪里,有没有人能告诉我答案的,SESSION肯定是存放在服务器端上的,
浏览器关闭SESSION,SESSION会失效吗,肯定不会失效的,为什么呢,这是我要重点去讲的,在这个地方我去给大家画一个图,
画一个什么图呢,在这个地方我们写一下,叫做客户端,我们举一反三,然后把它去copy一遍,是不是叫做服务器端的,这个地方我们
叫做服务器端,你们要记住,我们发起http请求的话,客户端和服务器端要进行通信的时候,在这个时候大家一定要思考一下,
走的是请求,英文叫做request,那么举一反三,如果服务器端响应给客户端的时候,这个时候我们叫做response,这个你们肯定都知道,
response的英文怎么说,我们叫做响应,响应的过程我们叫做response,那么这个地方你们肯定就知道了,本身来说一个HTTP通信的话,
http通讯本身就是基于请求和响应的过程,既然他基于请求和响应的话,这个时候客户端我们可以理解为浏览器,这个地方大家去看,
你们看代码
Cookie: JSESSIONID=66115D0AA6ACFCF82AA61999799F571A
存入Session sessionid:信息66115D0AA6ACFCF82AA61999799F571A,nameValue:zhangsan,serverPort:8080
这个时候本地是会把SESSIONID保存起来,这表示什么意思呢,http://localhost:8080/createSession?nameValue=zhangsan
这是第一次请求,也就是什么意思,也就是客户端向服务器端发起createSession请求的时候,创建session,返回sessionId
打开开发者工具里面,当你再去查询的时候,客户端是不是会读取到本地的sessionId,存放到请求头里面去,是不是能够查到
这个值,在请求头里面是不是有sessionId,客户端它会读取到本地的sessionId,然后存放到请求头里面去,他这边是不是就查
对应的结果,你们有没有发现一个问题,为什么响应头里面没有显示全,createSession的时候响应头里面为什么没有sessionId,
但是请求头里面有sessionId,这是什么原因,你们不觉得不对劲吗,客户端发起一个createSession请求的时候,通过响应头
把sessionId响应给客户端,响应头里面没有返回sessionId给客户端,但是请求头里面有,这是什么原因,是因为你第一次
创建完了之后,
Set-Cookie: JSESSIONID=A8E197E167C7750BB9D19D1B8F420B5B; Path=/; HttpOnly
Cookie: JSESSIONID=66115D0AA6ACFCF82AA61999799F571A
读取缓存中的,在这边你们把缓存全部清掉看,因为它已经有了,清除缓存,他是不是会把本地的sessionId全部给清除掉,
这个之后,是不是返回来sessionId看到没有,
Set-Cookie: JSESSIONID=A8E197E167C7750BB9D19D1B8F420B5B; Path=/; HttpOnly
是不是就是这个sessionId,首先客户端向服务端发起请求的时候,它会返回一个sessionId给客户端,通过响应头返回给客户端的,
那么浏览器捕获到响应头,获取到对应的sessionId的时候,保存在本地的,保存在本地之后,当你在这边getSession的时候,
他是不是直接读取本地的sessionId,存放在请求头里面,是不是这样的,是不是可以查到里面的信息了,是不是这样的,
当我第二次重新加载的时候,他是不是没有返回sessionId,因为本地cookie已经缓存了sessionId了,我可以复用的,
这就是session的整个原理过程,比较简单,那么这边我要总结一下,你们知道session肯定是存在服务器端的,是存放在
客户端的,只是sessionId是存放在客户端进行保存的
4.0.0
com.learn
demo
0.0.1-SNAPSHOT
org.springframework.boot
spring-boot-starter-parent
2.0.0.RELEASE
2.8.0
1.8
1.8
UTF-8
UTF-8
zh_CN
org.projectlombok
lombok
org.springframework.boot
spring-boot-starter-web
com.alibaba
fastjson
1.2.47
org.springframework.boot
spring-boot-starter-test
test
org.apache.commons
commons-pool2
org.apache.maven.plugins
maven-compiler-plugin
1.8
org.springframework.boot
spring-boot-maven-plugin
com.learn.WxMpApplication
repackage
server:
port: 8080
spring:
redis:
database: 0
host: 59.110.138.145
port: 6666
password: 1234
jedis:
pool:
max-active: 8
max-wait: -1
max-idle: 8
min-idle: 0
timeout: 10000
redis:
hostname: 59.110.138.145
port: 6666
password: 1234
package com.learn.controller;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
*
* @author Leon.Sun
*
*/
@SpringBootApplication
@RestController
public class TestSessionController {
/**
* 这表示端口号
* 这是读取配置文件里面的
* 为什么这么做的目的
* 目的是为了区分服务器不同的节点
*
*
* @return
*/
@Value("${server.port}")
private String serverPort;
@RequestMapping("/")
public String index() {
return serverPort;
}
// 创建session 会话
/**
* 这段代码表示什么意思呢
* 表示他会去创建一个SESSION
* 就是通过拿到request对象
*
* 比如现在客户端发起一个createSession请求
* 如果他一旦发起createSession请求的时候
* 那么这个时候你们去看一段代码
* 看一段什么代码呢
*
*
*
* @param request
* @param nameValue
* @return
*/
@RequestMapping("/createSession")
public String createSession(HttpServletRequest request, String nameValue) {
/**
* 看一下这段代码
* 表示什么意思呢
* getSession()他这里面可以传true或者false
* 不知道你们有没有印象
* 你们现在可能不理解true和false什么意思
* 不理解没关系
* 待会讲集群的时候你们瞬间就理解了
* 默认是true
* 这段代码表示什么意思呢
* 默认 创建一个session
* 创建一个SESSION的时候
* 默认值是true
* 一旦是为true的情况下的时候
* 没有找到对应的SESSION的时候
* 自动创建SESSION
* 他如果去自动创建这样的一个SESSION的时候
* 一个SESSION他和什么相似
* session分为sessionId和sessionValue
* 这个你们知道吧
* 这个我相信你们知道
* 那么在这里我问大家一个问题
* session他和什么比较相似
* 我不说map集合
* session和我们之前学的什么知识比较相似
* 和TOKEN
* 不是cookie
* 他和token非常相似
* session本身来说是不是临时的
* 是不是一个临时的
* 他如果是临时的话
* 不是永久有效的
* 既然是临时的话
* 和token是不是很相似
* 因为我令牌也是做临时的
* sessionId和token令牌也是非常相似的
* 保证临时且唯一
* 这个你们一定要记住
* 我在后面会讲到
* 很多公司分布式SESSION用什么解决呢
* 就用token解决
* 没有用到Spring-Session
* 客户端向服务器端肯定会发起一个createSession请求
* 如果在发起createSession请求的时候
* 注意看代码
* 服务器端接收到客户端请求之后
* 会创建一个session
* 创建完一个session之后
* 通过响应头返回一个sessionId
* 这个是请求的过程
* 这个叫做请求过程
* 那么反过来再看
* 叫做响应的过程
* 注意看一下
* 请求和响应过程
* 第二次请求的时候是这样的过程
* 这个时候什么意思呢
* 客户端向服务器端发起请求的时候
* 它会返回一个sessionId
* 返回一个sessionId给客户端
* 是不是浏览器
* 浏览器它会怎么做呢
* 浏览器获取到sessionId以后
* 保存在本地
* 既然他的sessionId是保存在本地的话
* 那么他和什么技术比较相似
* 想想他和什么技术比较相似
* 是不是叫做cookie
* 是不是非常非常相似
* 那么浏览器这个时候要怎么做呢
* 那么在这边我要讲的是什么呢
* 第二次请求
* 客户端读取到本地的sessionId
* 存放在请求头中
* 服务器端从请求头中获取到对应的sessionId
* 使用sessionId在本地内存中查询
* 你们现在可能还不明白什么意思
* 在这里我们打开我们的开发者工具
* 当我们发起一个createSession请求的时候
* 看一下它是一个什么过程
* 我们把日志打开
* 一旦向createSession
* 首先默认是为true的
* 他如果没有sessionId的话
* 创建一个session
* 创建一个SESSION之后
* 返回一个sessionId
* 对应的是存放的值
* 我故意把这个session打印出来了
* 对应的值是存放在对应的sessionId里面的
* 那你们注意看一个效果
* 我在这个地方去查询的时候
* 我们再次发起请求
* 找到netWork
* 找到响应头
* 响应头是不是把sessionId返回给客户端
* 也就是一个SESSIONID
* 客户端拿到sessionId保存在本地了
*
*
*/
HttpSession session = request.getSession();
System.out.println(
"存入Session sessionid:信息" + session.getId() + ",nameValue:" + nameValue + ",serverPort:" + serverPort);
/**
* 在这里存放一个nameValue这个值
*
*/
session.setAttribute("name", nameValue);
return "success-" + serverPort;
}
// 获取session 会话
/**
* 这里有一个获取SESSION
*
*
* @param request
* @return
*/
@RequestMapping("/getSession")
public Object getSession(HttpServletRequest request) {
// 设置为true 情况下的时候,客户端使用对应的sessionid 查询不到对应的sesison 会直接创建一个新的session
// 设置为false 情况下的时候,客户端使用对应的sessionid 查询不到对应的sesison 不 会直接创建一个新的session
/**
* 这里表示获取SESSION
*
*
*/
HttpSession session = request.getSession(false);
if (session == null) {
return serverPort + " 该服务器上没有存放对应的session值";
}
System.out.println("获取Session sessionid:信息" + session.getId() + "serverPort:" + serverPort);
/**
* 这里直接获取getName
*
*
*/
Object value = session.getAttribute("name");
return serverPort + "-" + value;
}
}
package com.learn;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
/**
*
* @author Leon.Sun
*
*/
@SpringBootApplication
public class AppSession {
public static void main(String[] args) {
/**
* 我们直接启动这个项目
*
*/
SpringApplication.run(AppSession.class, args);
}
}