一、session简介
Session是服务端技术,服务器在运行时可以为每个用户的浏览器创建一个其独享的session对象,由于session为用户浏览器独享,所以用户在访问浏览器的web资源时,可以把各自的数据放在各自的session中,当用户再去访问服务器中的其他web资源时,其他web资源再从用户各自的session中取出数据为用户服务。
二、session实现原理
服务器创建session后,会把session的id号,以cookie的形式回写给客户端,只要客户端的浏览器不管,再去访问服务器时都会带着session的Id,服务器发现哭护短带着session id过来,就会使用内存中与之对应的session为之服务。
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 SessionDemo01 extends HttpServlet{
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setCharacterEncoding("utf-8");
response.setHeader("content-type", "text/html;charset=utf-8");
PrintWriter pw = response.getWriter();
HttpSession session = request.getSession();
session.setAttribute("data", "韩信");
String sessionId = session.getId();
if(session.isNew()){
pw.print("session创建成功,sessionId是:"+sessionId);
}else{
pw.print("服务器已经存在该session,sessionID是:"+session);
}
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doGet(request, response);
}
}
点击刷新按钮,再次请求服务器,此时就可以看到浏览器再请求服务器时,会把存储到cookie中的session的Id一起传递到服务器端了。
三、Session对象的创建和销毁时机
1.创建
在程序中第一次调用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);
}
session对象默认30分钟没有使用,则服务器会自动销毁session,在web.xml文件中可以手工配置session的失效时间。
index.jsp
15
当需要在程序中手动设置Session失效时,可以手工调用session.invalidate方法,摧毁session。
1 HttpSession session = request.getSession(); 2 //手工调用session.invalidate方法,摧毁session 3 session.invalidate();
四、利用session防止表单重复提交
具体的做法:在服务器端生成一个唯一的随机标识号,专业术语称为Token(令牌),同时在当前用户的Session域中保存这个Token。然后将Token发送到客户端的Form表单中,在Form表单中使用隐藏域来存储这个Token,表单提交的时候连同这个Token一起提交到服务器端,然后在服务器端判断客户端提交上来的Token与服务器端生成的Token是否一致,如果不一致,那就是重复提交了,此时服务器端就可以不处理重复提交的表单。如果相同则处理表单提交,处理完后清除当前用户的Session域中存储的标识号。
Token生成类
import java.security.MessageDigest;
import java.util.Random;
import sun.misc.BASE64Encoder;
/**
* Token工具类,单例模式(保证内存中只有一个实例对象)
*
* @author hanxin
*
*/
public class TokenUtil {
private static TokenUtil instance;
private TokenUtil(){
}
/*
* 返回实例对象,如果没有对象就新建一个对象
*/
public static TokenUtil getInstance(){
if(instance==null){
instance = new TokenUtil();
}
return instance;
}
/*
* 生成token
*/
public String getToken(){
String token =String.valueOf(System.currentTimeMillis()+new Random().nextInt(999999999));
//数据指纹 128位长 16个字节 md5
try{
MessageDigest md = MessageDigest.getInstance("md5");
byte[] md5 = md.digest(token.getBytes());
//base64编码--任意二进制编码明文字符
BASE64Encoder encoder = new BASE64Encoder();
return encoder.encode(md5);
}catch(Exception e){
e.printStackTrace();
}
return null;
}
}
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 SessionDemo02 extends HttpServlet{
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String token = TokenUtil.getInstance().getToken();//创建令牌
request.getSession().setAttribute("token", token);//保存到session中
request.getRequestDispatcher("/form.jsp").forward(request, response);//跳转到form.jsp中
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doGet(request, response);
}
}
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
form表单
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 SessionDemo03 extends HttpServlet{
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String token_client = request.getParameter("token");
//1、如果用户提交的表单数据中没有token,则用户是重复提交了表单
if(token_client==null){
return;
}
String token_server = (String)request.getSession().getAttribute("token");
//2、如果当前用户的Session中不存在Token(令牌),则用户是重复提交了表单
if(token_server==null){
return;
}
//3、存储在Session中的Token(令牌)与表单提交的Token(令牌)不同,则用户是重复提交了表单
if(!token_client.equals(token_server)){
return;
}
request.getSession().removeAttribute("token");//移除session中的token
System.out.println("处理用户提交请求!!");
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doGet(request, response);
}
}