• 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始创建,设置时间到期后销毁。应用中考虑具体情况创造性使用即可,这里只记录其本质内容。

  • 相关阅读:
    Struts2升级注意事项
    使用HttpClient获取网页源码
    The method getJspApplicationContext(ServletContext) is undefined for the type JspFactory解决方案
    IBatis常见错误集锦
    JPush极光推送Java服务器端API
    JS去空trim
    Jquery常用操作
    适配器模式(Adapter)
    常见数据库设计(3)——历史数据问题之多记录变更
    VS2008 工具箱都是textbox(报表设计时)
  • 原文地址:https://www.cnblogs.com/10000miles/p/9274071.html
Copyright © 2020-2023  润新知