1.Session简单介绍

由于Http是无状态的协议,所以服务端需要记录用户的状态时,就需要某种机制来识别具体的用户,实现这个机制的方式就是session。

典型的场景比如购物车,当你点击下单按钮时,由于HTTP协议无状态,所以并不知道是哪个用户操作的,所以服务端要为特定的用户创建了特定的Session,用于标识这个用户,并且跟踪用户,这样才知道购物车里面有几本书。这个Session是保存在服务端的,有一个唯一标识。

那么服务器端是如何识别特定的客户的?

每次HTTP请求的时候,客户端都会发送相应的Cookie信息到服务端。实际上大多数的应用都是用 Cookie 来实现Session跟踪的,第一次创建Session的时候,服务端会在HTTP协议中告诉客户端,需要在 Cookie 里面记录一个Session ID,以后每次请求把这个会话ID发送到服务器,我就知道你是谁了。实现Session跟踪需要用到Cookie,如果客户端的浏览器禁用了 Cookie 怎么办?一般这种情况下,会使用一种叫做URL重写的技术来进行会话跟踪,即每次HTTP交互,URL后面都会被附加上一个诸如 sid=xxxxx 这样的参数,服务端据此来识别用户。

2.Session和Cookie的区别

1.Cookie数据存放在客户的浏览器上,Session数据放在服务器上,Session对象由服务器创建,开发人员可以调用request对象getSession方法得到session对象。

2.Cookie不是很安全,别人可以分析存放在本地的Cookie并进行Cookie欺骗,考虑到安全应当使用session。

3.Session会在一定时间内保存在服务器上。当访问增多,会比较占用你服务器的性能考虑到减轻服务器性能方面,应当使用Cookie。

4.单个cookie保存的数据不能超过4K,很多浏览器都限制一个站点最多保存20个cookie。

3.Session的实现原理

服务器是如何实现一个Session为一个用户浏览器服务的?

服务器创建session出来后,会把session的id号,以cookie的形式回写给客户机,这样,只要客户机的浏览器不关,再去访问服务器时,都会带着session的id号去,服务器发现客户机浏览器带session id过来了,就会使用内存中与之对应的session为之服务。

示例代码如下:

package test;

import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession; public class SessionTest extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException { response.setCharacterEncoding("UTF=8");
response.setContentType("text/html;charset=UTF-8");
//使用request对象的getSession()获取session,如果session不存在则创建一个
HttpSession session = request.getSession();
//将数据存储到session中
session.setAttribute("data", "考拉");
//获取session的Id
String sessionId = session.getId();
//判断session是不是新创建的
if (session.isNew()) {
response.getWriter().print("session创建成功,session的id是:"+sessionId);
}else {
response.getWriter().print("服务器已经存在该session了,session的id是:"+sessionId);
}
} public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}

先来看看上述代码中的两个方法:

getSession():获得当前请求的Session,如果没有则新创建一个。对应代码中的HttpSession session = request.getSession();

setSttribute(String name, Object value):将数据存储到Session中。

第一次访问时,服务器会创建一个新的sesion,并且把session的Id以cookie的形式发送给客户端浏览器,如下图所示:

刷新后得到如下的输出结果:

4.浏览器禁用Cookie后的Session处理

解决方案:URL重写

//用于对sendRedirect方法后的url地址进行重写
response.encodeRedirectURL(java.lang.String url)
//用于对表单action和超链接的url地址进行重写
response.encodeURL(java.lang.String url)

示例代码如下:

IndexServlet.java

package test;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; public class IndexServlet extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException { response.setContentType("text/html;charset=UTF-8");
PrintWriter out = response.getWriter();
//创建Session
request.getSession();
out.write("本网站有如下书:<br/>");
Set<Map.Entry<String,Book>> set = DB.getAll().entrySet();
for(Map.Entry<String,Book> me : set){
Book book = me.getValue();
String url =request.getContextPath()+ "/BuyServlet?id=" + book.getId();
//response. encodeURL(java.lang.String url)用于对表单action和超链接的url地址进行重写
url = response.encodeURL(url);//将超链接的url地址进行重写
out.println(book.getName() + " <a href='"+url+"'>购买</a><br/>");
}
} public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
} /**
* @author gacl
* 模拟数据库
*/
class DB{
private static Map<String,Book> map = new LinkedHashMap<String,Book>();
static{
map.put("1", new Book("1","javaweb开发"));
map.put("2", new Book("2","spring开发"));
map.put("3", new Book("3","hibernate开发"));
map.put("4", new Book("4","struts开发"));
map.put("5", new Book("5","ajax开发"));
} public static Map<String,Book> getAll(){
return map;
}
} class Book{ private String id;
private String name; public Book() {
super();
}
public Book(String id, String name) {
super();
this.id = id;
this.name = name;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}

BuyServlet.java

package test;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession; public class BuyServlet extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String id = request.getParameter("id");
Book book = DB.getAll().get(id); //得到用户想买的书
HttpSession session = request.getSession();
List<Book> list = (List) session.getAttribute("list"); //得到用户用于保存所有书的容器
if(list==null){
list = new ArrayList<Book>();
session.setAttribute("list", list);
}
list.add(book);
//response. encodeRedirectURL(java.lang.String url)用于对sendRedirect方法后的url地址进行重写
String url = response.encodeRedirectURL(request.getContextPath()+"/ListCartServlet");
System.out.println(url);
response.sendRedirect(url);
} public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
} }

ListCartServlet.java

package test;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.List;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession; public class ListCartServlet extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html;charset=UTF-8");
PrintWriter out = response.getWriter();
HttpSession session = request.getSession();
List<Book> list = (List) session.getAttribute("list");
if(list==null || list.size()==0){
out.write("对不起,您还没有购买任何商品!!");
return;
} //显示用户买过的商品
out.write("您买过如下商品:<br>");
for(Book book : list){
out.write(book.getName() + "<br/>");
}
} public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}

浏览器在禁用Cookie之后,查看网页的源代码,入下:

本网站有如下书:<br/>javaweb开发   <a href='/MyWebProject/BuyServlet;jsessionid=880313EDA076741E7A6A7DEEEB5CB266?id=1'>购买</a><br/>
spring开发 <a href='/MyWebProject/BuyServlet;jsessionid=880313EDA076741E7A6A7DEEEB5CB266?id=2'>购买</a><br/>
hibernate开发 <a href='/MyWebProject/BuyServlet;jsessionid=880313EDA076741E7A6A7DEEEB5CB266?id=3'>购买</a><br/>
struts开发 <a href='/MyWebProject/BuyServlet;jsessionid=880313EDA076741E7A6A7DEEEB5CB266?id=4'>购买</a><br/>
ajax开发 <a href='/MyWebProject/BuyServlet;jsessionid=880313EDA076741E7A6A7DEEEB5CB266?id=5'>购买</a><br/>

可以看出每个超链接后面都带上了session的Id。

浏览器没禁用Cookie之前,网页的源代码如下:

本网站有如下书:<br/>javaweb开发   <a href='/MyWebProject/BuyServlet?id=1'>购买</a><br/>
spring开发 <a href='/MyWebProject/BuyServlet?id=2'>购买</a><br/>
hibernate开发 <a href='/MyWebProject/BuyServlet?id=3'>购买</a><br/>
struts开发 <a href='/MyWebProject/BuyServlet?id=4'>购买</a><br/>
ajax开发 <a href='/MyWebProject/BuyServlet?id=5'>购买</a><br/>

所以,当浏览器禁用了cookie后,就可以用URL重写这种解决方案解决Session数据共享问题。而且response.encodeRedirectURL(java.lang.String url) 和response. encodeURL(java.lang.String url)是两个非常智能的方法,当检测到浏览器没有禁用cookie时,那么就不进行URL重写了。

5.Session对象的创建和销毁时机

5.1 Session对象的创建时机

在程序中第一次调用request.getSession()方法时就会创建一个新的Session,可以用isNew()方法来判断Session是不是新创建的。

//使用request对象的getSession()获取session,如果session不存在则创建一个
HttpSession session = request.getSession();
//获取session的Id
String sessionId = session.getId();
//判断session是不是新创建的
if (session.isNew()) {
response.getWriter().print("session创建成功,session的id是:"+sessionId);
}else {
response.getWriter().print("服务器已经存在session,session的id是:"+sessionId);
}

5.2 Session对象的销毁时机

session对象默认30分钟没有使用,则服务器会自动销毁session,在web.xml文件中可以手工配置session的失效时间,例如:

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5"
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<display-name></display-name> <welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list> <!-- 设置Session的有效时间:以分钟为单位-->
<session-config>
<session-timeout>15</session-timeout>
</session-config> </web-app>

当需要在程序中手动设置Session失效时,可以手工调用session.invalidate方法,摧毁session。

HttpSession session = request.getSession();
//手工调用session.invalidate方法,摧毁session
session.invalidate();

wx搜索“程序员考拉”,专注java领域,一个伴你成长的公众号!

java web 之Session的更多相关文章

  1. Java Web开发Session超时设置

    在Java Web开发中,Session为我们提供了很多方便,Session是由浏览器和服务器之间维护的.Session超时理解为:浏览器和服务器之间创建了一个Session,由于客户端长时间(休眠时 ...

  2. JAVA WEB快速入门之从编写一个JSP WEB网站了解JSP WEB网站的基本结构、调试、部署

    接上篇<JAVA WEB快速入门之环境搭建>,在完成了环境搭建后(JDK.Tomcat.IDE),现在是万事具备,就差写代码了,今天就来从编写一个JSP WEB网站了解JSP WEB网站的 ...

  3. java web session监听销毁跳转

    1.了解如何使用HttpSessionListener监听session的销毁. 2.了解如何使用HttpSessionBindingListener监听session的销毁. 一. 使用HttpSe ...

  4. Java web servers 间是如何实现 session 同步的

     Java web servers 间是如何实现 session 同步的 有一个多月的时间没有更新博客了,今天终于忙里偷闲,可以把近期的收获总结一下. 本文是关于Java web servers 之间 ...

  5. Java Web Session设置

    一.前言 在做 java web项目时,我们很多时候都要用到 Session,那么我就简单的写一下 Session 的写法. 二.代码实现 Servlet Session 的设置 package co ...

  6. java web session过期 跳转页面没有跳出frame的问题

    对于frame页面框架的java web项目,如果session过期执行跳转操作时,只在一个frame中(例如center frame)跳转到设置的login页面了,为了能直接跳转到最初的登录页面,就 ...

  7. Java Web(三) 会话机制,Cookie和Session详解(转载)

    https://www.cnblogs.com/whgk/p/6422391.html 很大一部分应该知道什么是会话机制,也能说的出几句,我也大概了解一点,但是学了之后几天不用,立马忘的一干二净,原因 ...

  8. Java Web Application使Session永不失效(利用cookie隐藏登录)

    在做 Web Application 时,因为 Web Project 有 session 自动失效的问题,所以如何让用户登录一次系统就能长时间运行三个月,就是个问题. 后来,看到 session 失 ...

  9. Java Web学习总结(10)——Session详解

    摘要:虽然session机制在web应用程序中被采用已经很长时间了,但是仍然有很多人不清楚session机制的本质,以至不能正确的应用这一技术.本文将详细讨论session的工作机制并且对在Java ...

随机推荐

  1. 8、insert、delete、update语句总结

    insert常用语句 > insert into tb1 (name,age) values('tom',33); > insert into tb1 (name,age) values( ...

  2. Linux 下 SSH 远程超时解决方案

    Linux 下 SSH 远程超时解决方案 今天突然看到一个问题说是如何解决SSH远程超时的问题. 找了一点资料.用于解决这个需求~ 第一种:OpenSSH 配置文件设置 位于112行的 "C ...

  3. 一个python 服务器程序性能分析

    该服务器为bono,启动11个进程. 1.设置cprofile 在启动服务的总入口设置cprofile if __name__=="__main__": import cProfi ...

  4. 为什么我会选择走 Java 这条路?

    阅读本文大概需要 2.8 分钟.   作者:黄小斜 文章来源:微信公众号[程序员江湖] 最近有一些小伙伴问我,为什么当初选择走Java这条路,为什么不做C++.前端之类的方向呢,另外还有一些声音:研究 ...

  5. linux入门 配置网络

    我因为有自己的ssr,因此想让虚拟机共享我的ssr,并且不想搞的太麻烦,特此记录一下 1. 获取本机的ip 在命令行里输入ipconfig /all 获取本机IP,如下图所示,我本机ip为10.3.7 ...

  6. Springboot第二篇:与前端fetch通信(附springboot解决跨域方法)

    说到与前端通信,明白人都知道这章肯定会写两部分的东西啦. 关于后台 ①首先回顾前文,上一章环境搭建如图: ②我们在maven.example.controller下添加一个文件,并附上如图代码: ③: ...

  7. [LnOI2019]加特林轮盘赌

    Luogu5249 轮流开枪打一个环上的人 , 每次\(p\)的概率打死 , \(p\)始终相同 , 从第\(1\)个人开始 , 求第\(k\)个人成为唯一幸存者的概率 \(19.3.30\) 官方题 ...

  8. JAVA数据结构--快速排序

    快排概念 快速排序(英语:Quicksort),又称划分交换排序(partition-exchange sort),一种排序算法,最早由东尼·霍尔提出.在平均状况下,排序个项目要(大O符号)次比较.在 ...

  9. makedown学习笔记(以后可能会用makedown写博客)

    学习手册 https://www.zybuluo.com/mdeditor?url=https%3A%2F%2Fwww.zybuluo.com%2Fstatic%2Feditor%2Fmd-help. ...

  10. 项目版本不同导致Eclipse报错问题——关于在JDK1.7环境中,运行JDK1.8环境下编写的项目

    本人电脑环境配置的是JDK1.7,朋友的是JDK1.8 ,我把她编的java文件导入到我电脑里的Eclipse(LUNA版本)的时候,项目出现一个红色叹号,当然运行是肯定出错了.SO我就开始了解决之旅 ...