Session

  • 什么是Session

  上一篇中,cookie被容器作为响应发送给并浏览器被其保存,归根到底cookie是保存在客户端浏览器中随以后的请求一同发送的数据,只要每次客户端有这样一些flag“会话”就得以继续;cookie对象不仅有name-value属性还可以有sid(简写)属性,也是由服务器响应后被浏览器保存在客户端,随后当客户在请求该域时sid被浏览器自动填写进首部中,但是与上一篇中不同,cookie中携带的不再时服务器从客户获取并发回的value-name数据,而是sid,这里有这样一种倾向:即name-value保存一些可以暴露的用户信息,比如用户偏好,而sid保存的服务器中对应的session对象的id,仅仅是id,这里就要讲到session了,session被容器创建后应该是作为全局变量的保存的,即容器中的组件都可以访问该“数据结构”,只要req去获取session,容器就根据客户请求中的sid返回匹配的session对象,然后session中保存artribute就可以被程序员得到。但是容器第一次给客户端

  cookie时和上一篇的方式不同,只要程序员req.getsession"(),容器便创建s对象,并填充进cookie对象随后发送给客户端,客户端浏览器保存该携带sid的cookie。  

  注意:把session当作是全局变量,容器有一套自己的管理机制,因此作为和servlet一样级别的组件可以在部署文件中被配置。

  结构目录:

  • LoginServlet.java
package 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;
import util.OutputSessionInfo;
//第一次访问,假想为登陆页面;如果用户登陆后再次登陆,且服务器端session还没有失效,则获取sesionid及用户信息直接填表单
public class LoginServlet extends HttpServlet{
    private static final long serialVersionUID = -154176561953216931L;
    
    public void doGet(HttpServletRequest req,HttpServletResponse res) throws IOException {
        res.setContentType("text/html;charset=gb2312");
        HttpSession session = req.getSession();//session是全局的吧?调用获取sesion时,应用创建sesion对象全局保存?那么每一次获得否会发送吗?
        String user = (String) session.getAttribute("user");
//        String user =null;
        PrintWriter out = res.getWriter();
        out.println("<html>");
        out.println("<meta http-equiv=\"param\" content=\"no-cache\">");
        out.println("<head><title>登陆页面</title></head>");
        out.println("<body>");
        
        OutputSessionInfo.printSessionInfo(out, session);//调用工具
        
        out.println("<p>");
        out.println("<form method=post action=loginchk>");
        
        out.println("<table>");
            out.println("<tr>");
            out.println("<td>请输入用户 名</td>");
            if(null==user) {
                out.println("<td><input type=text name=user></td>");
            }else {
                out.println("<td><input type=text name=user value="+user+"></td>");
            }
            out.println("</tr>");
            
            out.println("<tr>");
            out.println("<td>请输入密码</td>");
            out.println("<td><input type=password name=password></td>");
            out.println("</tr>");
            
            out.println("<tr>");
            out.println("<td><input type=reset value=重填></td>");
            out.println("<td><input type=submit value=提交></td>");
            out.println("</tr>");
            
            out.println("</table>");
            
            out.println("</form>");
            out.println("<body>");
            out.println("<html>");
            out.close();
    }
    public void doPost(HttpServletRequest req,HttpServletResponse res) 
            throws ServletException,IOException{//传递给get
            doGet(req,res);
    }
}
View Code

  该程序会发送一个登陆页面给浏览器,填写表单后被交给验证程序。

  • LoginChkServlet.java
package servlet;

import java.io.IOException;

import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
//第二次访问,客户端携带sessionid发送请求;理解为登陆程序,判断用户的合法性保证会话中保存的是合法的用户信息,合法则给客户端设置sessionId,携带用户信息,最后跳转到合理的页面
public class LoginChkServlet extends HttpServlet{
    private static final long serialVersionUID = 7607414497209254926L;

    
    public void doGet(HttpServletRequest req,HttpServletResponse res) throws IOException {
        req.setCharacterEncoding("gb2312");
        String name = req.getParameter("user");
        String pwd = req.getParameter("password");//获取请求参数
        if(null==name || null==pwd || name.equals("") || pwd.equals("")) {
            res.sendRedirect("login");//重定向到登陆页面
            return;
        }else {//重定向时,请求对象更新,但是会携带sessionid请求头部
            HttpSession session = req.getSession();//从全局变量中去获取ssesion,请求对象自动根据请求头的seesionid去全局中找到该对应的对象,该对象保存了其他状态
            session.setAttribute("user", name);
            res.sendRedirect("greet");//值得注意的是:如果不是新创建的sesion,重定向是不回发送sesionid头部的,新的会话会发送;不只是重定向,转发也是一样!因为本质都是res/req
            return;
        }
        
    }
    
    public  void doPost(HttpServletRequest req,HttpServletResponse res)throws IOException {
        doGet(req,res);
    }
}
View Code

  表单为空则让用户重新登陆;非空则验证且容器创建session对象填充用户数据,并重定向到处理页面/程序(或假想为首页),可以查看浏览器控制台,set-cookie携带着sid被  作为响应首部的一部分发送给客户端,于是浏览器在内存中保存该数据,以后的请求中都会在请求首部中携带该sid。

  • GreetServlet.java
package servlet;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import util.OutputSessionInfo;

/**真正所要做的,其实就是从服务器set-sid后会话开始,让客户端持续地发送sid,结束只有两种情形:客户端丢失了sid,即关闭浏览器或页面(当客户端被开启新回话时,将导致旧会话在服务器丢失);
 *                                                                        服务端丢失s对象,即客户一定时间内没有进行会话(但是请求仍携带sid,服务器找不到s对象,将新创建s)。
 * 
 * 服务器获取请求首部中的sid并判断,这里获取sid时,如果客户操作时间太长导致服务端销毁s对象,则将导致服务器端找不到与请求头部sid匹配的s对象,重新登陆;
*                                       如果客户端强制清理了sid即不发送sid请求头,则组件获取到容器中新创建的s对象,s对象携带的属性肯定为null,需要去登陆重新建立会话;
*                                     
**/
//用户合法则会话已经完整,因为s对象已创建并发送给客户,属性已保存了s对象。下面是会话阶段,即让程序变得有状态!!
public class GreetServlet extends HttpServlet{
    public void doGet(HttpServletRequest req,HttpServletResponse res) throws IOException {
        HttpSession session = req.getSession();
        String user = (String) session.getAttribute("user");
        
        if(null==user) {
            res.sendRedirect("login");
        }else {
            res.setContentType("text/html;charset=gb2312");
            PrintWriter out=res.getWriter();
            out.println("<html><head><title>欢迎页面</title></head>");
            out.println("<body>");
            
            OutputSessionInfo.printSessionInfo(out, session);
            
            out.println("<p>");
            out.println("欢迎你,"+user+"</p>");
            out.println("<a href=login>重新登录</a>");
            out.println("<a href=logout>注销</a>");
            out.println("</body></html>");
            out.close();
        }
        
    }
    
    public  void doPost(HttpServletRequest req,HttpServletResponse res)throws IOException {
        
    }
}
View Code

  该程序会获取请求中的sid,如果服务端新创建session对象说明客户端丢失了携带sid的cookie或者服务端销毁了session对象,重新登陆;如果请求中有携带了sid的cookie,并  且容器中session持续有效,则展示输出session中的数据。

  • session的部署

 

总结:服务器根据sid可以从容器中众多的session找到对应的与客户sid匹配的session,session在被容器管理,由程序获取session始创建,设置时间到期后销毁。应用中考虑具体情况创造性使用即可,这里只记录其本质内容。

 

posted @ 2018-07-06 15:58  10000miles  阅读(236)  评论(0编辑  收藏  举报