HttpSession

session在不同环境下的不同含义

  session,中文经常翻译为会话.

  session在Web开发环境下的语义又有了新的扩展,它的含义是指一类用来在客户端与服务器端之间保持状态的解决方案。有时候Session也用来指这种解决方案的存储结构。

Session机制

  session机制采用的是在服务器端保持 HTTP 状态信息的方案

  服务器使用一种类似于散列表的结构(也可能就是使用散列表)来保存信息。

  当程序需要为某个客户端的请求创建一个session时,服务器首先检查这个客户端的请求里是否包含了一个session标识(即sessionId),如果已经包含一个sessionId则说明以前已经为此客户创建过session,服务器就按照session id把这个session检索出来使用(如果检索不到,可能会新建一个,这种情况可能出现在服务端已经删除了该用户对应的session对象,但用户人为地在请求的URL后面附加上一个JSESSION的参数)。如果客户请求不包含sessionId,则为此客户创建一个session并且生成一个与此session相关联的sessionId,这个session id将在本次响应中返回给客户端保存。

保存session id的几种方式

  保存session id的方式可以采用cookie,这样在交互过程中浏览器可以自动的按照规则把这个标识发送给服务器。

  由于cookie可以被人为的禁用,必须有其它的机制以便在cookie被禁用时仍然能够把session id传递回服务器,经常采用的一种技术叫做URL重写,就是把session id附加在URL路径的后面,附加的方式也有两种,一种是作为URL路径的附加信息,另一种是作为查询字符串附加在URL后面。网络在整个交互过程中始终保持状态,就必须在每个客户端可能请求的路径后面都包含这个session id。

Session cookie

  session通过SessionID来区分不同的客户, session是以cookie或URL重写为基础的,默认使用cookie来实现,系统会创造一个名为JSESSIONID的输出cookie,这称之为session cookie,以区别persistent cookies(也就是我们通常所说的cookie),session cookie是存储于浏览器内存中的,并不是写到硬盘上的,通常看不到JSESSIONID,但是当把浏览器的cookie禁止后,web服务器会采用URL重写的方式传递Sessionid,这时地址栏看到.

HttpSession 的生命周期:

  1). 什么时候创建 HttpSession 对象

  ①. 对于 JSP: 是否浏览器访问服务端的任何一个 JSP, 服务器都会立即创建一个 HttpSession 对象呢?不一定

    > 若当前的 JSP 是客户端访问的当前 WEB 应用的第一个资源,且 JSP 的 page 指定的 session 属性值为 false, 则服务器就不会为 JSP 创建一个 HttpSession 对象;

    > 若当前 JSP 不是客户端访问的当前 WEB 应用的第一个资源,且其他页面已经创建一个 HttpSession 对象,则服务器也不会为当前 JSP 页面创建一个 HttpSession 对象,而回会把和当前会话关联的那个 HttpSession 对象返回给当前的 JSP 页面.

  ②. 对于 Serlvet: 若 Serlvet 是客户端访问的第一个 WEB 应用的资源, 则只有调用了 request.getSession() 或 request.getSession(true) 才会创建 HttpSession 对象

  2). page 指令的 session=“false“  到底表示什么意思?

    > 当前 JSP 页面禁用 session 隐含变量!但可以使用其他的显式的 HttpSession 对象

  3). 在 Serlvet 中如何获取 HttpSession 对象

    > request.getSession(boolean create):

      create 为 false, 若没有和当前 JSP 页面关联的 HttpSession 对象, 则返回 null; 若有, 则返回 true   

      create 为 true, 一定返回一个 HttpSession 对象. 若没有和当前 JSP 页面关联的 HttpSession 对象, 则服务器创建一个新的HttpSession 对象返回, 若有, 直接返回关联的.

    > request.getSession(): 等同于 request.getSession(true)

  4). 什么时候销毁 HttpSession 对象:

    ①. 直接调用 HttpSession 的 invalidate() 方法: 该方法使 HttpSession 失效

    ②. 服务器卸载了当前 WEB 应用.

    ③. 超出 HttpSession 的过期时间.

      > 设置 HttpSession 的过期时间: session.setMaxInactiveInterval(5); 单位为秒

      > 在 web.xml 文件中设置 HttpSession 的过期时间: 单位为 分钟.
               <session-config>
                <session-timeout>30</session-timeout>
           </session-config>

    ④. 关闭浏览器只会使存储在客户端浏览器内存中的session cookie失效,不会使服务器端的session对象失效。

 HttpSession接口中的方法
getId方法
getCreationTime方法
getLastAccessedTime方法
setMaxInactiveInterval方法
getMaxInactiveInterval方法
isNew方法
   //如果客户端请求消息中返回了一个与Servlet程序当前获得的HttpSession对象的会话标识号相同的会话标识号,则认为这个HttpSession对象不是新建的。
invalidate方法
getServletContext方法
setAttribute方法
getAttribute方法
removeAttribute方法
getAttributeNames方法
 HttpServletRequest接口中的Session方法
getSession方法 
public HttpSession getSession(boolean create)
public HttpSession getSession()
isRequestedSessionIdValid方法 
isRequestedSessionIdFromCookie方法 
isRequestedSessionIdFromURL方法 

 

利用URL重写实现Session跟踪

  Servlet规范中引入了一种补充的会话管理机制,它允许不支持Cookie的浏览器也可以与WEB服务器保持连续的会话。

  将会话标识号以参数形式附加在超链接的URL地址后面的技术称为URL重写。

  HttpServletResponse接口中定义了两个用于完成URL重写方法:
    encodeURL方法
    encodeRedirectURL方法

<a href="<%= response.encodeURL("login.jsp") %>">重新登录</a>

相对路径和绝对路径:

1). 为什么要解决相对路径的问题: 在有一个 Servlet 转发页面的情况下, 会导致相对路径的混乱.

a.jsp: <a href="ToBServlet">To B Page2</a>
ToBServlet: request.getRequestDispatcher("/dir/b.jsp").forward(request, response);

 注意, 此时点击 To B Page2 超链接后的浏览器的地址栏的值: http://localhost:8989/day_36/ToBServlet, 实际显示的是dir 路径下的 b.jsp

而 b.jsp 页面有一个超链接: <a href="c.jsp">TO C Page</a>. 默认情况下, c.jsp 应该和 b.jsp 在同一路径下. 此时点击超链接将在浏览器地址栏显示: http://localhost:8989/day_36/c.jsp. 但在根目录下并没有 c.jsp, 所以会出现路径混乱的问题.

2). 使用绝对路径会解决以上的问题:

绝对路径: 相对于当前 WEB 站点根目录的路径.

http://localhost:8989/day_36/c.jsp: http://localhost:8989/ 是 WEB 站点的根目录, /day_36 是 contextPath, /c.jsp 是相对于当前 WEB 应用的一个文件路径. 我们需要在当前 WEB 应用的任何的路径下都添加上 contextPath, 即可.

比如:

<a href="ToBServlet">To B Page2</a> 需改为: <a href="<%= request.getContextPath() %>/ToBServlet">To B Page2</a>
response.sendRedirect("a.jsp"); 需改为: response.sendRedirect(request.getContextPath() + "/a.jsp");
<form action="AddServlet"></form> 需改为: <form action="<%= request.getContextPath() %>/AddServlet"></form>

3). 在 JavaWEB 应用中 / 代表的是: 有时代表当前 WEB 应用的根目录, 有时代表的是站点的根目录.

/ 代表的是当前 WEB 应用的根路径: 若 / 所在的命令或方法需被 WEB 服务器解析, 而不是直接打给浏览器, 则 / 代表 WEB 应用的根路径. 此时编写绝对路径就不需要在添加 contextPath 了. 在 web.xml 文件中做 Serlvet 映射路径时,  在请求转发: request.getRequestDispatcher("/dir/b.jsp").forward(request, response);

/ 代表的是站点的根目录: 若 / 直接交由浏览器解析, / 代表的就是站点的根路径, 此时必须加上 contextPath
<form action="/AddServlet"></form>
response.sendRedirect("/a.jsp");

4). 如何获取 contextPath:

  ServletContext: getContextPath()
  HttpServletRequest: getContextPath()

避免表单的重复提交

1). 重复提交的情况:

  ①. 在表单提交到一个 Servlet, 而 Servlet 又通过请求转发的方式响应一个 JSP(HTML) 页面, 此时地址栏还保留着 Serlvet 的那个路径, 在响应页面点击 "刷新"

  ②. 在响应页面没有到达时重复点击 "提交按钮".

  ③. 点击 "返回", 再点击 "提交"

2). 不是重复提交的情况: 点击 "返回", "刷新" 原表单页面, 再 "提交"。

3). 如何避免表单的重复提交: 在表单中做一个标记, 提交到 Servlet 时, 检查标记是否存在且是否和预定义的标记一致, 若一致, 则受理请求,并销毁标记, 若不一致或没有标记, 则直接响应提示信息: "重复提交"

  ①. 仅提供一个隐藏域: <input type="hidden" name="token" value="atguigu"/>. 行不通: 没有方法清除固定的请求参数.

  ②. 把标记放在 request 中. 行不通, 因为表单页面刷新后, request 已经被销毁, 再提交表单是一个新的 request.

  ③. 把标记放在 session 中. 可以!

        > 在原表单页面, 生成一个随机值 token
        > 在原表单页面, 把 token 值放入 session 属性中
        > 在原表单页面, 把 token 值放入到 隐藏域 中.

        > 在目标的 Servlet 中: 获取 session 和 隐藏域 中的 token 值
        > 比较两个值是否一致: 若一致, 受理请求, 且把 session 域中的 token 属性清除
        > 若不一致, 则直接响应提示页面: "重复提交"

使用 HttpSession 实现验证码

1). 基本原理: 和表单重复提交一致:

     > 在原表单页面, 生成一个验证码的图片, 生成图片的同时, 需要把该图片中的字符串放入到 session 中.
       > 在原表单页面, 定义一个文本域, 用于输入验证码.

          > 在目标的 Servlet 中: 获取 session 和 表单域 中的 验证码的 值
          > 比较两个值是否一致: 若一致, 受理请求, 且把 session 域中的 验证码 属性清除
          > 若不一致, 则直接通过重定向的方式返回原表单页面, 并提示用户 "验证码错误"

转载于:https://www.cnblogs.com/linyueshan/p/5634429.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值