目录
一. Cookie
1.1 设置cookie
- 是由网景公司的前雇员卢在1993年3月发明的
- 由来:以前的公司在十点到十点半是上午茶的时间,有个人很喜欢吃小甜饼,吃的久了,身上就带了这个味道。他从别人经过的时候别人闻到了小甜饼的味道就知道是他,所以我们在请求的时候带上cookie就知道是谁了。
- 是一种会话跟踪技术。
- 由于http 请求是无状态的,第一次的请求-响应不会影响下一次的请求-响应。
- 是由服务器发出的,客户端保存的。
- 可分为内存Cookie和硬盘Cookie
new Cookie(k, v).setMaxAge(保存多少秒);
当setMaxAge()>0
时保存在硬盘上<= 0
的时候保存在内存中。
下面我们看代码实现:
@Controller("/qwe")
@RequestMapping("/qwe")
public class CookieTest {
@Autowired
private HttpServletRequest request;
@Autowired
private HttpServletResponse response;
@RequestMapping(value = "/asd",method = {RequestMethod.GET})
@ResponseBody
public String test(){
//创建两个cookie
Cookie cookie1 = new Cookie("teacher", "oneToThree");
Cookie cookie2 = new Cookie("worker_niudun", "nihaoa");
//指定cookie的资源路径
cookie1.setPath(request.getContextPath() + "/xxx/eee");
cookie2.setPath(request.getContextPath() + "/ggg");
//设置cookie有消息为10天
cookie1.setMaxAge(60 * 60 * 24 * 10);
System.out.println(request.getContextPath());
response.addCookie(cookie1);
response.addCookie(cookie2);
return "你好啊" + request.getContextPath();
}
}
cookie1.setPath(request.getContextPath() + "/xxx/eee");
这个的意思是以后访问http://localhost:8080/qwe/asd/
这个资源路径下的文件都会在请求头上带上这个cookie
我们试着访问下一个不存在的资源路径:结果显示带上了这个cookie
我们看下浏览器端显示的cookie信息:
1.2 获取cookie
@RequestMapping(value = "/asd/q",method = {RequestMethod.GET})
@ResponseBody
public void getCookieName(){
Cookie[] cookies = request.getCookies();
for (Cookie cookie:cookies) {
System.out.println(cookie.getName());
}
}
在request请求中我们可以看到:
二. 域属性空间对比
- ServletContext :域属性是整个范围的 可以跨会话共享数据
- HttpSession :会话范围 可以跨请求共享数据
- HttpServletRequest: 一次请求范围内 可以跨Servlet请求数据 但必须在一个请求中
在保证需求的情况下使用小范围的比较好,节省服务器内存,安全性更高(数据放的时间越长 约占内存 也越不安全) - Session:同一会话可以跨请求传递数据。
三. Session
- 是一个会话 可跨请求共享数据
3.1 怎么使用?
首先我们新建一个请求/a
然后我们分别往request域,session域中放入数据,看我们另外一个请求能否拿到数据
@RequestMapping(value = "/a",method = {RequestMethod.GET})
@ResponseBody
public void test() throws IOException {
String username = "lisi";
//参数放入request域中
request.setAttribute("user", username);
//获取session
HttpSession session = request.getSession();
//像session中写入属性
session.setAttribute("username", username);
response.getWriter().println("username:"+username);
}
我们新建的请求/b
RequestMapping(value = "/b",method = {RequestMethod.GET})
@ResponseBody
public void getCookieName() throws IOException {
String str = "";
//从request域中读取属性
str = request.getParameter("user");
//获取session
HttpSession session = request.getSession(false);
String username = "";
//从Session域中读取指定属性
if(session != null){
username = (String) session.getAttribute("username");
}
response.getWriter().println("user:"+str);
response.getWriter().println("username:"+username);
response.getWriter().println("session:"+session);
}
- 结果展示
结果中我们可以看到request 域里面的数据只能在一个请求中,session的数据可以在不同请求。
3.2 对于request.getSession()的用法
- 若要像
session
写入数据则用getSession(true)
即getSession()
。意义是有老的用老的,没有则创建一个新的 - 若要使从
session
读取数据则使用getSession(false)
意义是有老的用老的没有则返回null 。因为新的session
也没有我们要的数据。
3.3 Session 工作原理
服务区会为每一个会话维护一个session 不同的会话对应不同的session,那么系统是如何识别每一个各个不同的sesion对象呢?如何做到统一会话过程中使用的是同一个session呢?
-
(一)写入
Session
列表
服务器对应的Seesion是以map的形式进行管理的,这个map称为Session列表,key是一个32位的随字符串,这个字符串称为JSESSIONID
,value则是session对象的引用。
服务器servlet
遇到request.getSession()
的时候 会自动生成一个Map.Entry对象
,key为根据某种算法生成的JSESSIONID
,value是新创建的session对象。就把这个<K, V>写到session列表中了。 -
(二)服务器生成并发送Cookie
在上一步骤,服务器生成map对象后同时生成一个cookie
放到响应头中,name就是JSESSIONID
,value就是这个32位的字符串。
SESSION=OWM5NDdiMjItOTRjMC00ZThlLTg4YjctZGY4MzEyYzEwN2Fi
- (三)客户端接受并发送cookie
客户端接受到这个cookie
会把这个保存到浏览器的缓存中。只要浏览器不关闭,cookie
就不会消失。
当用户提交第二次请求的时候会把缓存中的cookie
带上,放到请求头中一起发到服务器中。如下图:在request
中带上了刚才服务器生成的cookie
。
SESSION=OWM5NDdiMjItOTRjMC00ZThlLTg4YjctZGY4MzEyYzEwN2Fi
- (四)从Session列表中寻找
服务器从请求中读取到客户端发来的cookie
,然后拿着这个cookie中的32位字符串去自己的session
列表中查找,找到了对应的session对象,然后可以开始对该对对象的域属性读写操作。
3.4 Session 失效
-
- 在项目的web.xml中设置
单位是分钟
<session-config>
<session-timeout>15</session-timeout>
</session-config>
-
- 手动调用
session
的invalidate
方法session.invalidate();
- 手动调用
对于用户来说:关闭浏览器算是会话结束
对于服务器来说:session失效算会话结束
3.5 禁用Cookie后使用重定向跳转时Session的跟踪
使用response.encodeRedirectURL(uri);
来对重定向进行session跟踪
@RequestMapping(value = "/a",method = {RequestMethod.GET})
@ResponseBody
public void test() throws IOException {
String username = "lisi";
request.setAttribute("user", username);
HttpSession session = request.getSession();
session.setAttribute("username", username);
System.out.println("/a session:"+session);
String uri = "/qqq/b";
uri = response.encodeRedirectURL(uri);
response.sendRedirect(uri);
}
3.6 禁用Cookie后使用非重定向跳转时Session的跟踪
使用response.encodeURL(uri);
@RequestMapping(value = "/a",method = {RequestMethod.GET})
@ResponseBody
public void test() throws IOException {
String username = "lisi";
request.setAttribute("user", username);
HttpSession session = request.getSession();
session.setAttribute("username", username);
System.out.println("/a session:"+session);
String uri = "/qqq/b";
uri = response.encodeURL(uri);
response.getWriter().println("<a href='"+uri+"> 跳转</a>到Servlet");
}