Session技术
一、session概述
Session是服务器端技术,利用这个技术,服务器在运行时可以为每一个用户的浏览器创建一个其独享的HttpSession对象,由于session为用户浏览器独享,所以用户在访问服务器的web资源时,可以把各自的数据放在各自的session中,当用户再去访问服务器中的其它web资源时,其它web资源再从用户各自的session中取出数据为用户服务。
数据存储在服务端
服务端会为每一个客户端浏览器创建一个独享的session
Session也是一个域对象。域的范围是一个会话
session特点:
- session用于存储一次会话的多次请求的数据,存在服务器端
- session可以存储任意类型,任意大小的数据(只要内存放得下)
![](https://i-blog.csdnimg.cn/blog_migrate/553f2c8edec4bda6d61082b601564766.png)
![](https://i-blog.csdnimg.cn/blog_migrate/b2923a3c6000025613cbe0740c7cd6b3.png)
![](https://i-blog.csdnimg.cn/blog_migrate/564a64e74cce81005c00c9d42dafbf14.png)
getSession():会根据cookie的id到服务器去寻找这个id所对应的session对象,如果找不到,就会创建一个新的session,并给这个session分配一个唯一的id,并把他写入一个响应头(setCookie)返回给客户端(实际还是发送了一个cookie到客户端)
Cookie cookie = new Cookie("JESSIONID",session.getId());
cookie.setMaxAge(60*60*24);
response.addCookie(cookie);
客户端不关闭,服务器关闭后,两次获取的session不是同一个,确保数据不丢失:
session的钝化:在服务器正常关闭之前,将session对象序列化到硬盘上。
session的活化:在服务器启动后,将session文件转化为内存中的session对象。
![](https://i-blog.csdnimg.cn/blog_migrate/2116f08be5493440be9a5bbdf7f6140a.png)
![](https://i-blog.csdnimg.cn/blog_migrate/a0f32d253acbc38988dc2bf00574955f.png)
二、创建session
1)request.getSession() ;
此方法做了2件事:
①先看浏览器是否携带了一个名字叫JSESSIONiD的Cookie,如果没有,则直接创建一个新的session
② 如果有,则根据Cookie的值去服务端的内存中寻找id的值是此值的session.并且返回,找不到,创建新的返回
2) request.getSession(booleanflag) ;
如果flag为true,则相当于情况
如果flag为 false,则只查不创建三、延长session的生命
服务端发送的JSESSIONID默认情况下存储在客户端的缓存中,所以关闭浏览器,session的生命就结束了,要想多个关闭后还能用,那么必须创建一个新的
Cookie,名字也是JSESSIONID,设置存活时间,此时cookie存储在客户端的硬盘上,下次打开新的浏览器访问,浏览器会携带此Cookie,也就达到了关闭浏览器
还能使用此Session的效果了。
package com.hcx.session;
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;
//演示创建session
public class ServletSession1 extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
/**
* getsession()方法做了两件事:
* 1. 看客户端是否携带了JSESSIONIDCookie
* 2. 如果没有携带,创建一个新的session对象,并分配一个唯一的id,发送到客户端,存储在客户端的缓存中
* 如果携带了,将根据cookie的值(id)到服务端的内存中寻找session,如果找到了则返回此session为客户端服务,
* 如果找不到,则创建新的session对象,并并分配一个唯一的id,发送到客户端,存储在客户端的缓存中
*/
HttpSession session = request.getSession() ;
String id = session.getId() ;
System.out.println("111:" + id);
session.setAttribute("name", "张无忌") ;
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
package com.hcx.session;
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;
//演示从session中取出数据
public class ServletSession2 extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//获取session对象
HttpSession session = request.getSession() ;
System.out.println("222:" + session.getId());
//从session对象中获取数据
String name = (String) session.getAttribute("name") ;
System.out.println(name);
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
四、Session应用
1.加入购物车案例
package com.hcx.car.bean;
public class Book {
private String id ;
private String bookName ;
private String author ;
private float price ;
private String description ;
private int count ;
public Book(String id, String bookName, String author, float price,
String description) {
this.id = id;
this.bookName = bookName;
this.author = author;
this.price = price;
this.description = description;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getBookName() {
return bookName;
}
public void setBookName(String bookName) {
this.bookName = bookName;
}
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
public float getPrice() {
return price;
}
public void setPrice(float price) {
this.price = price;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public int getCount() {
return count;
}
public void setCount(int count) {
this.count = count;
}
@Override
public String toString() {
return "Book [id=" + id + ", bookName=" + bookName + ", author="
+ author + ", price=" + price + ", description=" + description
+ "]";
}
@Override
public boolean equals(Object obj) {
Book b = (Book)obj ;
return id.equals(b.id);//判断id是否一样,id一样就是买过这本书了 不一样就是没买过
}
}
BookUtils:
package com.hcx.car.utils;
import java.util.HashMap;
import java.util.Map;
import com.hcx.car.bean.Book;
public class BookUtils {
private static Map<String,Book> map = new HashMap<String,Book>() ;
static{
map.put("1", new Book("1","葵花宝典","安倍晋三",100,"欲练神功,必须先练好基本功")) ;
map.put("2", new Book("2","辟邪剑谱","陈冠希",80,"绝世好书")) ;
map.put("3", new Book("3","西游记","吴承恩",50,"一群小猴子的故事")) ;
map.put("4", new Book("4","水浒传","施耐庵",90,"三个女人和105个男人的故事")) ;
map.put("5", new Book("5","西厢记","阿娇",70,"好好看啊。。。。。。")) ;
map.put("6", new Book("6","神雕侠侣","金庸",100,"感天动地的旷世绝恋")) ;
map.put("7", new Book("7","红楼梦","葫芦娃",60,"男人的梦想。。。。。。。")) ;
}
//获取所有的书
public static Map<String,Book> getAllBook(){
return map ;
}
//根据书的id获取谋一本书
public static Book getBookById(String id){
return map.get(id) ;
}
}
ShowAllBookServlet:
package com.hcx.car.servlet;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Map;
import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.hcx.car.bean.Book;
import com.hcx.car.utils.BookUtils;
/**
* 功能有两个:
* 1. 显示所有的书的信息
* 2. 提供一个购物车的连接
* @author Administrator
*
*/
public class ShowAllBookServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
request.setCharacterEncoding("UTF-8") ;
response.setContentType("text/html;charset=UTF-8") ;
PrintWriter out = response.getWriter() ;
out.write("本站有以下好书:<br>") ;
//1.显示所有的书
//获取所有的书的集合
Map<String ,Book> map = BookUtils.getAllBook() ;
//遍历集合
for (Map.Entry<String, Book> entry : map.entrySet()) {
//拿到每一本的id
String id = entry.getKey() ;
//拿到每一本书
Book book = entry.getValue() ;
//输出书的名字
out.write(book.getBookName() + " <a href = '"+ request.getContextPath()+"/servlet/ShowBookDetailServlet?id=" + id +"'>显示详细信息</a><br>") ;
}
out.write("<br><br><br><br>") ;
//提供查看购物车的连接
out.write("<a href = '"+ request.getContextPath()+"/servlet/CarServlet'>查看购物车</a>") ;
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
package com.hcx.car.servlet;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.LinkedList;
import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.hcx.car.bean.Book;
import com.hcx.car.utils.BookUtils;
/**
* 此类完成两件事情:
* 1. 显示书的详细信息
* 2. 提供购物的连接,返回继续浏览的连接
* @author Administrator
*
*/
public class ShowBookDetailServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
request.setCharacterEncoding("UTF-8") ;
response.setContentType("text/html;charset=UTF-8") ;
PrintWriter out = response.getWriter() ;
//1.显示书的详细信息
//拿到页面传递的id
String id = request.getParameter("id") ;
//根据id获取书
Book book = BookUtils.getBookById(id) ;
//显示信息
out.write(book + " <a href = '" + request.getContextPath() +"/servlet/ShowAllBookServlet'>返回主页继续浏览</a><a href = '" + request.getContextPath()+ "/servlet/BuyServlet?id=" + id + "'>放入购物车</a><br>") ;
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
package com.hcx.car.servlet;
import java.io.IOException;
import java.io.PrintWriter;
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;
import com.hcx.car.bean.Book;
import com.hcx.car.utils.BookUtils;
//此servlet是将购买的书放入购物车
public class BuyServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
request.setCharacterEncoding("UTF-8") ;
response.setContentType("text/html;charset=UTF-8") ;
PrintWriter out = response.getWriter() ;
//获取页面传递的id
String id = request.getParameter("id") ;
//根据id找到书对象
Book book = BookUtils.getBookById(id) ;
//将书存入session对象中
HttpSession session = request.getSession() ;
//将书放入session中的一个集合中
List<Book> list = (List<Book>) session.getAttribute("carlist") ;
if(list == null){
//说明第一次购买书籍,此时session中是不存在list集合,需要手动创建
list = new ArrayList<Book>() ;
//将购买的书籍放入
book.setCount(1) ;
list.add(book) ;
//将list存入session
session.setAttribute("carlist", list) ;
}else{
//说明已经购买过书籍了
//判断购物车中是否已经购买过此书
int index = list.indexOf(book) ; //这里的这个方法跟重写equals方法有什么联系???????????????????????????
//indexOf(Object o) 找出指定元素第一次出现在集合中 的索引值
if(index == -1){
//说明没有买过此书
book.setCount(1) ;
list.add(book) ;
}else{
//说明买过了
Book b = list.get(index) ;
b.setCount(b.getCount() + 1) ;
}
//提醒用户,此书已经放入购物车中
out.write(book.getBookName() + " 已经放入购物车中,4秒后转向主页,低级<a href = '"+request.getContextPath()+"/servlet/ShowAllBookServlet'>此处</a>直接转向主页") ;
response.setHeader("Refresh", "4;url="+ request.getContextPath() + "/servlet/ShowAllBookServlet") ;
}
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
package com.hcx.car.servlet;
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;
import com.hcx.car.bean.Book;
//显示购物车中的内容
public class CarServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
request.setCharacterEncoding("UTF-8") ;
response.setContentType("text/html;charset=UTF-8") ;
PrintWriter out = response.getWriter() ;
HttpSession session = request.getSession() ;
//如果用户直接在地址栏中输入地址访问此servlet,那此时session是一个新创建的对象
if(session.isNew()){
//直接返回主页面
response.sendRedirect(request.getContextPath() + "/servlet/ShowAllBookServlet") ;
return ;
}
//先从session拿到购物车
List<Book> list = (List<Book>)session.getAttribute("carlist") ;
//如果用户直接从主页面上点击查看购物车过来,此时还没有购买任何书籍呢,所以提示用户会主页
if(list == null){
//用户首次访问购物车
out.write("你还没有购买任何书籍呢,2秒后转向主页") ;
response.setHeader("Refresh", "2;url="+ request.getContextPath() + "/servlet/ShowAllBookServlet") ;
return ;
}
//说明购买了书籍
out.write("你购买的书籍如下:<br> ") ;
out.write("书名\t数量\t总价格<br>") ;
for (int i = 0; i < list.size(); i++) {
Book b = list.get(i) ;
out.write(b.getBookName() + "\t" + b.getCount() + "\t" + b.getPrice() * b.getCount() + "<br>") ;
}
out.write("<br><br><a href = '" +request.getContextPath()+ "/servlet/ShowAllBookServlet'>返回主页面</a>") ;
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
![](https://i-blog.csdnimg.cn/blog_migrate/e43fb170241a10ce4bee17e4258933e1.png)
2.验证码登录
package com.hcx.servlet;
import java.io.IOException;
import java.io.PrintWriter;
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 LoginServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
request.setCharacterEncoding("UTF-8") ;
response.setContentType("text/html;charset=UTF-8") ;
PrintWriter out = response.getWriter() ;
//拿取页面传递的信息
String username = request.getParameter("username") ;
String pass = request.getParameter("pass") ;
String fcode = request.getParameter("code") ;
System.out.println(fcode);
//先验证验证码
if("".equals(fcode)){
out.write("验证码不能为空,2秒后转向登陆页面") ;
response.setHeader("Refresh", "2;url=" + request.getContextPath() + "/login.html") ;
return ;
}else{
//从session中拿到存储的验证码
HttpSession session = request.getSession() ;
String scode = (String) session.getAttribute("scode") ;
if(!scode.equalsIgnoreCase(fcode)){
out.write("验证码填写错误,2秒后转向登陆页面") ;
response.setHeader("Refresh", "2;url=" + request.getContextPath() + "/login.html") ;
return ;
}
if("张三".equals(username) && "111".equals(pass)){
//需要将用户名存入session
session.setAttribute("username", username) ;
request.getRequestDispatcher("MainServlet").forward(request, response) ;
}else{
out.write("用户名或者密码错误,2秒后转向登陆页面") ;
response.setHeader("Refresh", "2;url=" + request.getContextPath() + "/login.html") ;
}
}
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
package com.hcx.servlet;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.Random;
import javax.imageio.ImageIO;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.sun.org.apache.xerces.internal.xni.grammars.Grammar;
//输出验证码
public class ServletResponse3 extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//创建变量
int width = 120 ;
int height = 30 ;
//创建一个内存图像
BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB) ;
//创建画笔
Graphics g = image.getGraphics() ;
//指定边框的颜色
g.setColor(Color.RED) ;
//画图像的边框
g.drawRect(0, 0, width, height) ;
//填充一下矩形的背景色
//设定画笔的颜色
g.setColor(Color.YELLOW) ;
//填充矩形的背景
g.fillRect(1, 1, width-2, height-2) ;
//设置字体大小
g.setFont(new Font("幼圆",Font.BOLD + Font.ITALIC,22)) ;
//填充内容
Random r = new Random() ;
//设置画笔的颜色
g.setColor(Color.GRAY) ;
//画30条干扰线
for (int i = 0; i < 30; i++) {
g.drawLine(r.nextInt(width), r.nextInt(height), r.nextInt(width), r.nextInt(height)) ;
}
//设定画笔的颜色
g.setColor(Color.RED) ;
//随机产生4个汉字
String s = "我的博客IhavanoMoney" ;
//先将汉字转换为unicode编码
s = "\5317\uEAC\u4F0\u66A\u6AD\5BAIhavanoMoney" ;
StringBuffer sb = new StringBuffer() ;
for (int i = 0; i < 4; i++) {
char c = s.charAt(r.nextInt(s.length())) ;
sb.append(c) ;
int flag = r.nextBoolean()?1:-1 ;
g.drawString(c+"", 20 + 20*i + flag*r.nextInt(5), 23 + flag * r.nextInt(5)) ;
}
//将验证码存入session
request.getSession().setAttribute("scode", sb.toString()) ;
// //随机产生4个数字输出到页面
// for (int i = 0; i < 4; i++) {
// int n = r.nextInt(10) ;
// //画到到图片中
// g.drawString(n+"", 20 + 20*i, 20) ;
// }
//告诉客户端不要缓存图像
response.setHeader("Expires", -1 + "") ;
response.setHeader("Cache-control", "no-cache") ;
response.setHeader("Pragma", "no-cache") ;
//将图片输出到客户端
ImageIO.write(image, "jpg", response.getOutputStream()) ;
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
package com.hcx.servlet;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class MainServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
request.setCharacterEncoding("UTF-8") ;
response.setContentType("text/html;charset=UTF-8") ;
PrintWriter out = response.getWriter() ;
String name = (String)request.getSession().getAttribute("username") ;
out.write(name + ",欢迎你") ;
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
五、解决重复提交的问题
利用第三方变量:
在页面产生的时候同时给一个变量,同时为改变量赋一个值,当请求第一次提交后,把这个值改变:该变量存储在session中,把其删除即可。如果刷新,一个新的请求把刚才的信息又提交了一遍:当提交到服务端的时候,先判断该变量的值,如果该变量的值已经不存在了,就认为重复提交了,如果变量的值还在,则认为是第一次提交。
RegisterServletUI:package com.hcx.token;
import java.io.IOException;
import java.io.PrintWriter;
import java.net.URLEncoder;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.UUID;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import sun.misc.BASE64Encoder;
//此servlet的目的是产生页面,同时提供一个唯一的口令:token
public class RegisterServletUI extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
request.setCharacterEncoding("UTF-8") ;
response.setContentType("text/html;charset=UTF-8") ;
PrintWriter out = response.getWriter() ;
//产生一个唯一的值
String token = "" ;
//token = System.nanoTime() + "" ;
//采用第三种方式:数据指纹
token = UUID.randomUUID().toString() ;
try {
MessageDigest md = MessageDigest.getInstance("MD5") ;
byte[] bs = md.digest(token.getBytes()) ;
BASE64Encoder base = new BASE64Encoder() ;
token = base.encode(bs) ;
System.out.println("session:" + token);
} catch (NoSuchAlgorithmException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//由于数据指纹中可能存在特殊字符,因此再次进行编码
//将口令存入session
request.getSession().setAttribute("stoken", token) ;
//拿到错误信息显示
String error = (String) request.getAttribute("error") ;
if(error !=null){
out.write(error) ;
}
//创建页面
out.write("<form action = '" + request.getContextPath()+"/servlet/ResiterServlet' method = 'post'>") ;
out.write("姓名:<input type = 'text' name = 'username'> <br>") ;
out.write("<input type = 'hidden' name = 'ftoken' value = '" + token + "'> <br>") ;
out.write("<input type = 'submit' value = '注册'> <br>") ;
out.write("</form>") ;
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
package com.hcx.token;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
//完成注册的功能
public class ResiterServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
request.setCharacterEncoding("UTF-8") ;
response.setContentType("text/html;charset=UTF-8") ;
PrintWriter out = response.getWriter() ;
//拿到页面传递的数据
String name = request.getParameter("username") ;
String ftoken = request.getParameter("ftoken") ;
System.out.println("页面: " + ftoken);
//判断信息进行注册
if("".equals(name)){
//返回注册页面\
request.setAttribute("error", "用户名必须填写") ;
request.getRequestDispatcher("RegisterServletUI").forward(request, response) ;
}else{
//在注册用户的时候先判断口令,口令一致再进行注册,否则不允许注册
//注意,保存成功后要将口令从session中删除
//拿到session中存储的口令
String stoken = (String) request.getSession().getAttribute("stoken") ;
if(ftoken.equals(stoken)){
out.write("用户已保存到数据库中") ;
//删除口令
request.getSession().removeAttribute("stoken") ;
}else{
out.write("不要重复提交,2秒后转向注册页面") ;
response.setHeader("Refresh", "2;url=" + request.getContextPath() + "/servlet/RegisterServletUI") ;
}
}
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
六.url重写技术
当客户端浏览器禁止了所有的Cookie时,服务器发送的session在客户端的缓存里就不存在了,每次刷新都会被创建新的session。
此时,服务端还要向客户端服务,办法:
1.告诉客户端:不要禁止
客户端在访问网站的时候,该网站会先去检测:客户端浏览器是不是禁止了,如果禁止了,就会提示消息:不要禁止客户端的Cookie
2.url重写技术:
把session的id附加到网址后面,这样就能找到对应的session为其服务了。
encodeURL()这个方法的原理就是把id附加在了网址的后面
缺点:所有的URL都要重写,麻烦
package com.hcx.url;
import java.io.IOException;
import java.io.PrintWriter;
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 ServletSession1 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() ;
String id = session.getId() ;
session.setAttribute("name", "张三") ;
//只要将产生的id附加到每一个网址(url)之后,服务端就可以根据id找到对应的session对象为客户端服务
String url = request.getContextPath() + "/servlet/ServletSession2" ;
url = response.encodeURL(url) ;
out.write("<a href = '" + url+"'>访问ServletSession2</a>") ;
// System.out.println(session.getId());
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
package com.hcx.url;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class ServletSession2 extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String name = (String)request.getSession().getAttribute("name") ;
System.out.println(name);
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
七.session的状态
当我们创建了一个session后,此session就在服务器的内存里
当服务器里存在着很多没用的session时,希望可以把这些没用的session清除掉:
利用Tomcat的一种机制:固化或搁置:把session序列化到硬盘上,
固化或搁置:停止服务器时,把有用的session序列化到硬盘上。
再次启动时:把有用的session重新激活,读取到内存里(激活或活化)
![](https://i-blog.csdnimg.cn/blog_migrate/28bf552fbfb817948e9fc75c39106fc3.png)
当服务器停止的时候,内存中的session将会固化到硬盘上,路径在\work\Catalina\localhost\day11_00_session下,
文件后缀名是ser.当重新启动的时候,此文件对象会自动又被读入内存继续服务。
八.session销毁时机
1.服务器关闭
2.session对象调用invalidate()
3.session默认失效时间 30min
此处可以修改默认时间,也可以在web.xml中重新配置,覆盖默认的。