javaweb学习————session

目录

1 session的概念

2 session和cookie的区别

3  session的实现

4 浏览器禁用cookie后session的处理机制

5 session对象的创建和销毁机制

5.1 session对象的创建时机

5.2 session对象的销毁时机

6 利用session防止表单重复提交


1 session的概念

在计算机中,尤其是在网络应用中,称为“会话控制”。Session对象存储特定用户会话所需的属性及配置信息。这样,当用户在应用程序的Web页之间跳转时,存储在Session对象中的变量将不会丢失,而是在整个用户会话中一直存在下去。当用户请求来自应用程序的 Web页时,如果该用户还没有会话,则Web服务器将自动创建一个 Session对象。当会话过期或被放弃后,服务器将终止该会话。Session 对象最常见的一个用法就是存储用户的首选项。例如,如果用户指明不喜欢查看图形,就可以将该信息存储在Session对象中。

在WEB开发中,服务器可以为每个用户浏览器创建一个会话对象(session对象),注意:一个浏览器独占一个session对象(默认情况下)。因此,在需要保存用户数据时,服务器程序可以把用户数据写到用户浏览器独占的session中,当用户使用浏览器访问其它程序时,其它程序可以从用户的session中取出该用户的数据,为用户服务。

2 session和cookie的区别

  • cookie存于客户端,session对象由服务端创建
  • cookie是把用户的数据写到浏览器上
  • session将用户的数据在浏览器上独占给用户自己

3  session的实现

服务端在创建了session之后,会将sessionid以cookie的形式存于浏览器,只要不关闭浏览器,再访问服务端时sessionid都会存在,就会使用服务端内存中与之对应的session为之服务。

package cn.session.study;

import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

/**
 * Servlet implementation class SessionDemo01
 */
@WebServlet("/SessionDemo01")
public class SessionDemo01 extends HttpServlet {
	private static final long serialVersionUID = 1L;
       
    /**
     * @see HttpServlet#HttpServlet()
     */
    public SessionDemo01() {
        super();
        // TODO Auto-generated constructor stub
    }

	/**
	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
	 */
	protected 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,sessionid是:"+sessionId);
		}
		
	}

	/**
	 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
		doGet(request, response);
	}

}

4 浏览器禁用cookie后session的处理机制

response.encodeRedirectURL(java.lang.String url)   用于对sendRedirect方法后的url地址进行重写。

response.encodeURL(java.lang.String url)    用于对表单action和超链接的url地址进行重写。

IndexServlet.java

package cn.session.study;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.Map;
import java.util.Set;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import cn.session.study.domain.Book;

/**
 * Servlet implementation class IndexServlet
 */
@WebServlet("/IndexServlet")
public class IndexServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;
       
    /**
     * @see HttpServlet#HttpServlet()
     */
    public IndexServlet() {
        super();
        // TODO Auto-generated constructor stub
    }

	/**
	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		
		response.setCharacterEncoding("utf-8");
		response.setContentType("text/html;charset=utf-8");
		PrintWriter out = response.getWriter();
		//创建session
		HttpSession  session = request.getSession();
		//获取sessionid
		String sessionID = session.getId();
		//判断session是不是新建的
		if(session.isNew()) {
			response.getWriter().print("session创建成功,sessionid是:"+sessionID);
		}else {
			response.getWriter().print("服务器已经纯在session,sessionid是:"+sessionID);
		}
		out.write("本网站有如下图书:
"); Set> set = DB.getAll().entrySet(); for (Map.Entry entry : set) { Book book = entry.getValue(); String url = request.getContextPath()+"/BuyServlet?id="+book.getId(); response.encodeURL(url);//用于对表单action和超链接的url地址进行重写 url = response.encodeURL(url);//将超链接的url地址进行重写 out.println(book.getName()+"购买
"); } } /** * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response) */ protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // TODO Auto-generated method stub doGet(request, response); } }

Book.java

package cn.session.study.domain;

public class Book {

	private String id;
	private String name;

	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;
	}
	
	
}

DB.java

package cn.session.study;
/**
 * 
 * @author Administrator
 *
 */

import java.util.LinkedHashMap;
import java.util.Map;

import cn.session.study.domain.Book;

public class DB {

	private static Map map = new LinkedHashMap();
	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 getAll() {
		return map;
	}
}

BuyServlet.java

package cn.session.study;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import cn.session.study.domain.Book;

/**
 * Servlet implementation class BuyServlet
 */
@WebServlet("/BuyServlet")
public class BuyServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;
       
    /**
     * @see HttpServlet#HttpServlet()
     */
    public BuyServlet() {
        super();
        // TODO Auto-generated constructor stub
    }

	/**
	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
	 */
	protected 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 list = (List) session.getAttribute("list");//得到用户用于保存所有书的容器
		if(list==null) {
			list = new ArrayList();
			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);
	}

	/**
	 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
		doGet(request, response);
	}

}

ListCarServlet.java

package cn.session.study;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.List;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import cn.session.study.domain.Book;

/**
 * Servlet implementation class ListCartServlet
 */
@WebServlet("/ListCartServlet")
public class ListCartServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;
       
    /**
     * @see HttpServlet#HttpServlet()
     */
    public ListCartServlet() {
        super();
        // TODO Auto-generated constructor stub
    }

	/**
	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		
		response.setContentType("text/html;charset=utf-8");
		PrintWriter writer = response.getWriter();
		HttpSession session = request.getSession();
		List list = (List) session.getAttribute("list");
		if (list==null||list.size()==0) {
			writer.write("对不起您没有购买任何商品!!");
			
		}
		writer.write("您买过如下商品:
"); for (Book book : list) { writer.write(book.getName()+"
"); } } /** * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response) */ protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // TODO Auto-generated method stub doGet(request, response); } }

javaweb学习————session_第1张图片

javaweb学习————session_第2张图片

5 session对象的创建和销毁机制

5.1 session对象的创建时机

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

//使用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,sessionid是:"+sessionId);
}

5.2 session对象的销毁时机

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



  JavaWeb_Study
  
    index.html
    index.htm
    index.jsp
    default.html
    default.htm
    default.jsp
  
  
  
  
    15
  
  

6 利用session防止表单重复提交

具体实现:在服务端生成一个唯一的随机标识号,专业术语称为token(令牌),同时在当前用户的session域中保存这个token,然后将token发送到form表单中,在form表单中使用隐藏域来存储这个token,表单提交的时候连同这个token一起提交到服务端,,然后在服务端判断客户端提交上来的token与服务端生成的token是否一致,如果不一致,那就是重复提交了。此时服务端就可以处理重复提交的表单。如果相同则处理表单提交,处理完后清除当前用户的session域中的标识号。

以下情况,服务器程序将拒绝处理用户的表单请求:

1. 存储session域中的token(令牌)与表单提交的token(令牌)不同、

2. 当前用户的session中不存在token(令牌)。

3. 用户提交的表单数据中没有token。

具体的范例:

1. 创建FormServlet,用于生成token(令牌)和跳转到fom.jsp

package cn.session.study;

import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * Servlet implementation class FormServlet
 */
@WebServlet("/FormServlet")
public class FormServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;
       
    /**
     * @see HttpServlet#HttpServlet()
     */
    public FormServlet() {
        super();
        // TODO Auto-generated constructor stub
    }

	/**
	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		String token = TokenProcessor.getInstance().makeToken();//创建token
		System.out.println("在FormServlet中生成token:"+token);
		request.getSession().setAttribute("token", token);
		request.getRequestDispatcher("/form.jsp").forward(request, response);//跳转到form.jsp页面
	}

	/**
	 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
		doGet(request, response);
	}

}

2. 在form.jsp中使用隐藏域来存储token(令牌)

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>




Form表单重复提交



	
<%--使用隐藏域存储生成的token --%> <%-- "> --%> <%--使用EL表达式取出存储在session中的token --%> 用户名:

3. DoFormServlet处理表单提交

package cn.session.study;

import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * Servlet implementation class DoFormServlet
 */
@WebServlet("/DoFormServlet")
public class DoFormServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;
       
    /**
     * @see HttpServlet#HttpServlet()
     */
    public DoFormServlet() {
        super();
        // TODO Auto-generated constructor stub
    }

	/**
	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		/*
		//客户端是以UTF-8编码传输数据到服务端的,所以设置服务端以UTF-8的编码进行接收,否则对于中文数据就会乱码
		request.setCharacterEncoding("utf-8");
		String userName = request.getParameter("username");
		try {
			//让当前的线程睡眠3秒钟,模拟网络延迟而导致表单重复提交的现象
			Thread.sleep(3*1000);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		System.out.println("向数据库中插入数据:"+userName);
		*/
		
		boolean b = isRepeatSubmit(request);//判断用户是否重复提交
		if(b==true) {
			System.out.println("请不要重复提交");
			return;
		}
		request.getSession().removeAttribute("token");//移除session中的token
		System.out.println("处理用户提交请求!");
	}

	/**
	 * 判断客户端提交上来的令牌和服务器端生成的令牌是否一致
	 * @param request
	 * @return	true  用户重复提交了表单
	 * 			false 用户没有重复提交表单
	 */
	private boolean isRepeatSubmit(HttpServletRequest request) {
		
		String client_token = request.getParameter("token");
		//1.如果用户提交的表单数据中没有token,,则用户是重复提交
		if(client_token==null) {
			return true;
		}
		//取出存储在session中token
		String server_token = (String) request.getSession().getAttribute("token");
		
		//2.如果当前用户的session中不存在token,则用户重复提交
		if (server_token==null) {
			return true;
		}
		//3.存储在session中的token与表单提交的token不同,则用户重复提交了表单
		if (!client_token.equals(server_token)) {
			return true;
		}
		return false;
	}

	/**
	 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
		doGet(request, response);
	}

}

生成token的工具类TokenProccessor

package cn.session.study;

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Random;

import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;

public class TokenProcessor {

	/*
	 * 单例设计模式(保证累的对象在内存中只有一个)
	 * 1.把类的构造函数私有
	 * 2.自己创建一个类的对象
	 * 3.对外提供一个公共的方法,返回类的对象
	 */
	
	private TokenProcessor() {}
	
	private static final TokenProcessor instance = new TokenProcessor();
	
	/**
	 * 返回类的对象
	 * @return
	 */
	public static TokenProcessor getInstance() {
		return instance;
	}
	
	/**
	 * 生成token
	 * @return
	 */
	public String makeToken() {
		String token = (System.currentTimeMillis()+new Random().nextInt(999999999))+"";
		
		try {
			MessageDigest md = MessageDigest.getInstance("md5");
			byte[] md5 = md.digest(token.getBytes());
			//base64编码--任意二进制编码明文字符   
			BASE64Encoder encoder = new BASE64Encoder();
			return encoder.encode(md5);
		} catch (NoSuchAlgorithmException e) {
			throw new RuntimeException(e);
		}
	}
}

 

你可能感兴趣的:(JavaWeb)