Session的底层实现原理

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是存放在客户端进行保存的
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.learn</groupId>
  <artifactId>demo</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.0.0.RELEASE</version>
		<relativePath /> <!-- lookup parent from repository -->
	</parent>
	<properties>
		<weixin-java-mp.version>2.8.0</weixin-java-mp.version>
		<maven.compiler.source>1.8</maven.compiler.source>
		<maven.compiler.target>1.8</maven.compiler.target>
		<maven.compiler.encoding>UTF-8</maven.compiler.encoding>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
		<project.build.locales>zh_CN</project.build.locales>
	</properties>

	<dependencies>
		<dependency>
			<groupId>org.projectlombok</groupId>
			<artifactId>lombok</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
			<!-- <exclusions> <exclusion> <groupId>com.fasterxml.jackson.core</groupId> 
				<artifactId>jackson-databind</artifactId> </exclusion> </exclusions> -->
		</dependency>
		<!-- https://mvnrepository.com/artifact/com.alibaba/fastjson -->
		<dependency>
			<groupId>com.alibaba</groupId>
			<artifactId>fastjson</artifactId>
			<version>1.2.47</version>
		</dependency>
		<!-- Testing Dependencies -->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>
		<!-- <dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-data-redis</artifactId>
		</dependency> -->
		<!--spring session 与redis应用基本环境配置,需要开启redis后才可以使用,不然启动Spring boot会报错 -->
		<!-- <dependency>
			<groupId>org.springframework.session</groupId>
			<artifactId>spring-session-data-redis</artifactId>
		</dependency> -->
		<dependency>
			<groupId>org.apache.commons</groupId>
			<artifactId>commons-pool2</artifactId>
		</dependency>
		<!-- <dependency>
			<groupId>redis.clients</groupId>
			<artifactId>jedis</artifactId>
		</dependency> -->

	</dependencies>
	<build>
		<plugins>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-compiler-plugin</artifactId>
				<configuration>
					<source>1.8</source>
					<target>1.8</target>
				</configuration>
			</plugin>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
				<configuration>
					<maimClass>com.learn.WxMpApplication</maimClass>
				</configuration>
				<executions>
					<execution>
						<goals>
							<goal>repackage</goal>
						</goals>
					</execution>
				</executions>

			</plugin>
		</plugins>
	</build>

</project>
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);
	}

}

 

  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值