会话管理(二)---Session技术及其使用

来源:互联网 发布:如何网络招生 编辑:程序博客网 时间:2024/06/05 03:50

Session概述

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

Session 是一个域
作用范围:当前会话范围
生命周期:
当程序第一次调用到request.getSession()方法时说明客户端明确的需要用到session此时创建出对应客户端的Session对象.
当session超过30分钟(这个时间是可以在web.xml文件中进行修改的)没有人使用则认为session超时销毁这个session.
修改时间:在web.xml文件中<web-app>标签里添加:

<session-config>    <session-timeout>30</session-timeout> 以分钟为单位的值</session-config>

程序中明确的调用session.invalidate()方法可以立即杀死session.
当服务器被非正常关闭时,随着虚拟机的死亡而死亡.
如果服务器是正常关闭,还未超时的session会被以文件的形式保存在服务器的work目录下,这个过程叫做session的钝化(Sessions.ser).下次再正常启动服务器时,钝化着的session会被恢复到内存中,这个过程叫做session的活化.
作用:在会话范围内共享数据。

Session原理

request.getSession()方法会检查请求中有没有JSESSIONID cookie,如果有拿出他的值找到对应的session为他服务。
如果没有则检查请求的URL后有没有以参数的形式带着JSESSIONID过来,如果有则找到对应的Session为浏览器服务。
如果还找不到则认为这个浏览器没有对应的Session,创建一个Session然后再在响应中添加JSESSIONID cookie,值就是这个Session 的id。

默认情况下,JSESSIONID 的path为当前web应用的名称,并且没有设置过MaxAge,是一个会话级别的cookie。

这意味着一旦关闭浏览器再新开浏览器时,由于JSESSIONID丢失,会找不到之前的Session。
我们可以手动的发送JSESSIONID cookie,名字和path设置的和自动发送时一样,但是设置一下MaxAge,使浏览器除了在内存中保存JSESSIONID信息以外还在临时文件夹中以文件的形式保存,这样即使重开浏览器仍然可以使用之前的session。

session原理图

URL重写

如果浏览器禁用了Cookie,浏览器就没有办法JSESSIONID cookie,这样就用不了Session了.
我们可以使用URL重写的机制,在所有的超链接后都以参数的形式拼接JSESSIONID信息,从而在点击超链接时可以使用URL参数的方式带回JSESSIONID,从而使用Session
将URL进行重写拼接上JSESSIONID的过程就叫做URL重写

request.getSession() –在URL重写之前一定要先创建出Session,才能进行重写
response.encodeURL()— 一般的地址都用这个方法重写
response.encodeRedirectURL() — 如果地址是用来进行重定向的则使用这个方法

url重写的方法一旦发现浏览器带回了任意cookie信息,则认为客户端没有禁用cookie,就不会再进行重写操作

Session实例

利用session模拟简单的网站购物功能

购物图片

新建prodList.jsp文件,用来显示商品。代码如下:

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8" session="false"%><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"><html>  <head>  </head>  <body>    <%        request.getSession();        String url1 = request.getContextPath() + "/servlet/BuyServlet?prod=电视机";        String url2 = request.getContextPath() + "/servlet/BuyServlet?prod=冰箱";        String url3 = request.getContextPath() + "/servlet/PayServlet";        url1 = response.encodeURL(url1);        url2 = response.encodeURL(url2);        url3 = response.encodeURL(url3);    %>    <a href="<%=url1 %>">电视机</a>    <a href="<%=url2 %>">冰箱</a>    <a href="<%=url3 %>">结账</a>  </body></html>

BuyServlet,处理购买商品的逻辑:

package me.zipstream.session;import java.io.IOException;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 javax.servlet.http.HttpSession;public class BuyServlet extends HttpServlet {    public void doGet(HttpServletRequest request, HttpServletResponse response)            throws ServletException, IOException {        String prod = request.getParameter("prod");        prod = new String(prod.getBytes("iso8859-1"), "utf-8");        HttpSession session = request.getSession();        Cookie jc = new Cookie("JSESSIONID", session.getId());        jc.setPath(request.getContextPath());        jc.setMaxAge(1800);//30minutes        response.addCookie(jc);        session.setAttribute("prod", prod);    }    public void doPost(HttpServletRequest request, HttpServletResponse response)            throws ServletException, IOException {        doGet(request, response);    }}

PayServlet,显示购买后的逻辑:

package me.zipstream.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;public class PayServlet extends HttpServlet {    public void doGet(HttpServletRequest request, HttpServletResponse response)            throws ServletException, IOException {        response.setContentType("text/html;charset=utf-8");        HttpSession session = request.getSession();        String prod = (String) session.getAttribute("prod");        response.getWriter().write("您购买的商品是:" + prod + ",售价5999元。");    }    public void doPost(HttpServletRequest request, HttpServletResponse response)            throws ServletException, IOException {        doGet(request, response);    }}

利用Session实现网站登录的案例

登录注销

新建index.jsp,模拟网站的首页:

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"><html>  <head>  </head>  <body>    <h1>我的网站</h1><hr>    <%         //获取Session中的登录状态        String user = (String) session.getAttribute("user");    %>    <%         if (user==null || "".equals(user)){    %>            欢迎光临!游客!            <a href="${pageContext.request.contextPath }/loginout/login.jsp">登录</a>            <a href="#">注册</a>    <%         } else{    %>            欢迎回来!<%=user %>            <a href="${pageContext.request.contextPath }/servlet/LogoutServlet">注销</a>    <%         }    %>  </body></html>

新建login.jsp,模拟登录页面:

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"><html>  <head>  </head>  <body>    <h1>我的网站</h1><hr>    <form action="${pageContext.request.contextPath }/servlet/LoginServlet" method="POST">        用户名:<input type="text" name="username" />        密码:<input type="password" name="password" />        <input type="submit" value="登录" />    </form>  </body></html>

新建UserDao类,模拟用户数据库:

package me.zipstream.session.loginout;import java.util.HashMap;import java.util.Map;public class UserDao {    private UserDao(){}    private static Map<String, String> map = new HashMap<String, String>();    static{        map.put("张三丰", "111");        map.put("张翠山", "222");        map.put("张无忌", "333");    }    public static boolean valiNamePsw(String username, String password){        return map.containsKey(username) && map.get(username).equals(password);    }}

新建LoginServlet,处理用户登录逻辑:

package me.zipstream.session.loginout;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 LoginServlet extends HttpServlet {    public void doGet(HttpServletRequest request, HttpServletResponse response)            throws ServletException, IOException {        request.setCharacterEncoding("utf-8");        response.setContentType("text/html;charset=utf-8");        //获取用户名和密码        String username = request.getParameter("username");        String password = request.getParameter("password");        //查询数据库检查用户名和密码        if (UserDao.valiNamePsw(username, password)){            //如果正确登录,则重定向到主页            request.getSession().setAttribute("user", username);            response.sendRedirect(request.getContextPath() + "/loginout/index.jsp");            return;        } else{            //如果错误,则提示            response.getWriter().write("用户名或密码不正确!");        }    }    public void doPost(HttpServletRequest request, HttpServletResponse response)            throws ServletException, IOException {        doGet(request, response);    }}

新建LogoutServlet,实现用户注销的逻辑:

package me.zipstream.session.loginout;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 LogoutServlet extends HttpServlet {    public void doGet(HttpServletRequest request, HttpServletResponse response)            throws ServletException, IOException {        //杀掉session        if (request.getSession(false)!=null                 && request.getSession().getAttribute("user")!=null){            request.getSession().invalidate();        }        //重定向到主页        response.sendRedirect(request.getContextPath() + "/loginout/index.jsp");    }    public void doPost(HttpServletRequest request, HttpServletResponse response)            throws ServletException, IOException {        doGet(request, response);    }}
0 0