SpringMVC系列五之cookie与session
cookie与session的原理
介绍
类比
cookie类比于银行卡,session类比于银行系统中保存的个人信息,会话类比于去银行办业务。只有拿着cookie,银行工作人员根据cookie从银行系统拿到你的sessIon并做相关操作,业务才能完成。
作用
cookie与session的作用是用于在同一网站下,不同网页的跳转过程中,协同维护一个上下文。这个上下文通常叫做会话,cookie与session存放了一些全局性信息或者全局性变量。
形式
cookie是以文本的形式存在,它存放在客户端(每个浏览器都有自己的存放路径)
session是以内存块的形式存在,它在服务器内存中
区别
cookie适用于存放少量的基本信息,session适用于存放大量信息。
session比Cookie更具有安全性
session占用服务器性能,Session过多,增加服务器压力
单个cookie保存的数据不能超过4K,很多浏览器都限制一个站点最多保存20个cookie
使用场景
购物网站从登陆,选购商品,加入购物车,进行结算这个过程中,有多次网页的跳转,使用cookie和session来保存全局信息,使得购物车能看到加入的商品,结算能看到购物车要结算的商品。
注意:cookie和session一般都是同时使用,共同维护会话
流程图
下图展现了一个会话过程,黄色方框代表浏览器和服务器的会话,服务端为这个会话在内存中创建了一个session。服务段程序在每个与浏览器交互的过程中,都可以创建自定义cookie,也可以随时在session中存取数据。
cookie与session的程序实现
工程目录
搭建基本框架
- 创建动态网页工程(Dynamic web project)
- 将所需的jar包复制到lib目录下
- 编写web.xml
- 编写springmvc配置文件
- 编写index.jsp。
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>测试页</title>
</head>
<body>
<a href="login">请登录</a>
<h1>游客可浏览信息</h1>
<h1>游客可浏览信息</h1>
<h1>游客可浏览信息</h1>
<h1>游客可浏览信息</h1>
</body>
</html>
- 编写视图界面
在WEB-INF下创建view文件夹,在该文件夹下创建1个界面:login.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>测试页</title>
</head>
<body>
<form action="login" method="post">
用户:<input type="text" name="username" /><br/>
密码:<input type="text" name="password" /><br/>
<input type="submit" value="登录">
</form>
</body>
</html>
- 编写controller中的基本方法
package com.edu.tjdz.geng.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
@Controller
public class MyController {
//进入login.jsp
@RequestMapping(value="/login", method = RequestMethod.GET )
public String login() {
return "login";
}
//处理登录按钮发出的请求,进入登录后的界面loginSuccess.jsp
@RequestMapping(value="/login", method = RequestMethod.POST )
public String login(String username, String password) {
System.out.println("登录用户名为:" + username + ",密码为: " + password );
return "loginSuccess";
}
}
- 启动项目,测试基本框架是否有问题
cookies
jsessionid cookies
- 删除浏览器中全部cookie。(不同浏览器,删除方法不同,请自行百度,我使用的是谷歌浏览器)
- 在浏览器地址栏输入http://localhost:8080/SpringMVC07/(先不要敲回车,如果敲了重复步骤1和2),之后按F12,开启调试模式。
- 开启下面的界面后,再在地址栏敲回车。
- 捕捉请求信息:在SpringMVC07/这个请求中,找到ResponseHeaders,找到Set-Cookie,这个就是服务端发给浏览器的cookie要包含的信息。这个cookie的内容是JSESSIONID,它就是流程图中绿色session的id。(结合流程图理解)
- 点击请登录超链接
可以发现Request中的cookie中的内容依然是上面的JESSIONID值,没有变化
6. 使用任意数据登录,继续查看cookie
依然没有变化,
7.总结: jsessionid这个cookie自生成后,此后不论发生多少次网页跳转,只有浏览器不关闭,它的值一直不变。这个cookie产生于浏览器第一次访问该网站。在后续访问网站的其他网址时,浏览器每次发出请求都会携带上cookie,方便后台程序使用。
自定义cookie
cookie的本质就是一个名值对,它也可以由程序员自定义,可以在任意需要的时刻定义。
以登录为例,我在登录的时候创建两个cookie,分别存放用户名和密码
- 修改controller的login函数
package com.edu.tjdz.geng.controller;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletResponse;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
@Controller
public class MyController {
@RequestMapping(value="/login", method = RequestMethod.GET )
public String login() {
return "login";
}
//新生成cookie需要使用HttpServletResponse对象
@RequestMapping(value="/login", method = RequestMethod.POST )
public String login(String username, String password, HttpServletResponse response) {
System.out.println("登录用户名为:" + username + ",密码为: " + password );
//创建cookie信息,在构造函数中设置名字和值,第一个参数是名字,第二个参数是值。
Cookie userCookie = new Cookie("username", username);
Cookie pwdCookie = new Cookie("password", password);
//将cookie信息放到回应response中
response.addCookie(userCookie);
response.addCookie(pwdCookie);
return "loginSuccess";
}
}
- 在浏览器中输入如下网址,进入下面的网页中,并按F12
- 输入用户名和密码,点击登录,并捕捉请求和回应
登录按钮的请求触发了login(String username, String password, HttpServletResponse response) 这个函数执行,函数执行生成两个cookie信息,并将他们放到回应response中,浏览器收到回应就会在本地创建这两个cookie。
- 在登录成功界面任意写一个链接
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>登录成功</title>
</head>
<body>
<h1>欢迎登录</h1>
<a href="/student"></a>
</body>
</html>
在controller中写一个处理/student请求的方法get
package com.edu.tjdz.geng.controller;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletResponse;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
@Controller
public class MyController {
@RequestMapping(value="/student", method = RequestMethod.GET)
public String get() {
return "getSuccess";
}
@RequestMapping(value="/login", method = RequestMethod.GET )
public String login() {
return "login";
}
@RequestMapping(value="/login", method = RequestMethod.POST )
public String login(String username, String password, HttpServletResponse response) {
System.out.println("登录用户名为:" + username + ",密码为: " + password );
Cookie userCookie = new Cookie("username", username);
Cookie pwdCookie = new Cookie("password", password);
response.addCookie(userCookie);
response.addCookie(pwdCookie);
return "loginSuccess";
}
}
编写getSuccess.jsp页面
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>个人中心</title>
</head>
<body>
<h>进入个人中心</h>
</body>
</html>
- 刷新页面,点击个人中心,捕捉请求和回应
就可以发现新的cookie已经随着浏览器请求一起发送到了服务端
在服务端程序获取cookie
cookie 可以在服务端controller任意程序中获取,在SpringMVC中使用注解@CookieValue获取
注解中name为cookie的名字,required设置为false。这就可以在任意地方使用cookie中存放的信息了(把它看做一个全局变量)
- 修改controller中的get函数
@RequestMapping(value="/student", method = RequestMethod.GET)
public String get(@CookieValue(name = "JSESSIONID", required = false)String jid, @CookieValue(name = "username", required = false)String username,
@CookieValue(name = "password", required = false)String password) {
System.out.println("session id 是:" + jid);
System.out.println("当前登录用户名为:" + username + ",密码为: " + password );
return "getSuccess";
}
- 测试,点击个人中心,观察后台输出
输出
session
前端页面使用session
由于cookie的数量有限制,安全性也较低,为了满足更多需求,可以使用session。session是在第一次访问网站时创建出来的,我们使用时不需要再创建。Springmvc中可以使用注解@SessionAttributes使用session
- 在controller头部增加了注解SessionAttributes,修改get方法,增加update方法
package com.edu.tjdz.geng.controller;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletResponse;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.CookieValue;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.SessionAttributes;
import org.springframework.web.servlet.ModelAndView;
@SessionAttributes(value = {"message1","message2"})
@Controller
public class MyController {
@RequestMapping(value="/login", method = RequestMethod.GET )
public String login() {
return "login";
}
@RequestMapping(value="/login", method = RequestMethod.POST )
public String login(String username, String password, HttpServletResponse response) {
System.out.println("登录用户名为:" + username + ",密码为: " + password );
Cookie userCookie = new Cookie("username", username);
Cookie pwdCookie = new Cookie("password", password);
response.addCookie(userCookie);
response.addCookie(pwdCookie);
return "loginSuccess";
}
//get方法中使用modelAndView在session中存放信息
@RequestMapping(value="/student", method = RequestMethod.GET)
public ModelAndView get(@CookieValue(name = "JSESSIONID", required = false)String jid, @CookieValue(name = "username", required = false)String username,
@CookieValue(name = "password", required = false)String password) {
System.out.println("session id 是:" + jid);
System.out.println("当前登录用户名为:" + username + ",密码为: " + password );
ModelAndView modelAndView = new ModelAndView();
//modelAndView中的键值对也可以放在session中
//放置方法是把modelAndView中的键添加到Controller头部中注解@SessionAttributes中
//@SessionAttributes(value = {"message1","message2"})
modelAndView.addObject("message1", "ABCDEF");
modelAndView.addObject("message2", 123456);
modelAndView.setViewName("getSuccess");
return modelAndView;
}
@RequestMapping(value="/student", method = RequestMethod.PUT)
public String update() {
System.out.println("更新个人信息");
return "updateSuccess";
}
}
- 在页面中获取session中存放的信息
修改getSuccess.jsp,增加了一个修改个人信息的按钮
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>个人中心</title>
</head>
<body>
<h>进入个人中心</h>
<br/>
<br/>
<form action="student" method="post">
<input type="hidden" name="_method" value="put">
<input type="submit" value="修改个人信息">
</form>
</body>
</html>
增加修改个人信息的页面
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8" isErrorPage="true"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>更新个人信息</title>
</head>
<body>
<h>更新页面</h>
<h1>${message1} </h1>
<h1>${message2} </h1>
</body>
</html>
重新登录,点击个人中心,进入下面页面
点击修改个人信息,可以在页面上显示session中存放的信息
服务端使用session
- 修改controller的update方法
后台程序使用session,需要在函数参数列表中增加HttpSession session。
在函数内,通过session.getAttribute(键名)来获得对应的信息。
@RequestMapping(value="/student", method = RequestMethod.PUT)
public String update(HttpSession session) {
System.out.println("更新个人信息");
String message1 = (String) session.getAttribute("message1");
int message2 = (int) session.getAttribute("message2");
System.out.println("messaget1 是:" + message1 + " messaget2 是:" + message2 );
return "updateSuccess";
}
- 重新登录,点击个人中心,进入下面页面, 点击修改个人信息,观察eclipse后台输出
结果如下: