JSP(3)—Cookie和Session

  1. HTTP是一个无状态的协议,web服务器无法分辨出那些请求是同一个浏览器发出的,浏览器每一次请求都是孤立的
    即使HTTP1.1支持持续链接,但当用户有一段时间没有请求时,连接也会关闭。
    如何实现网上的购物车:某个用户从网站登陆页面登陆后,在进入到购物页面购物时,负责处理购物请求的服务器程序必须知
    道处理上一次请求的程序所得到的用户信息。
    作为web浏览器必须能够采用一种机制,来唯一标识一个用户,同时记录该用户的状态。
  2. 会话和会话状态
    web应用中的会话是指一个客户端浏览器与web服务器之间连续发生的一系列请求和响应过程。
    web应用的会话状态是指web服务器与浏览器在会话过程中产生的状态信息,借助会话状态web服务器能够把属于同一会话
    中的一系列的请求和响应过程关联起来。
  3. 实现有状态的会话
    web服务器端程序要能够从大量的请求消息中区分那些请求消息属于同一个会话,即可以识别同一个浏览器的访问请求
    这需要浏览器对其发出的每个请求消息都进行标识:属于同一个会话中的请求消息都附带同样的标识号,而属于不同会话的请
    求消息总是附带不同的标识号,这个标识号称之为会话ID(SessionID)
    在Servlet规范中有两种机制完成会话跟踪:
    ——Cookie
    ——Session
  4. Cookie:
    1).概念:cookie机制采用的是在客户端保持HTTP状态信息的方案,Cookie是浏览器在访问web服务器的某个资源时,由
    web服务器在HTTP响应消息头中附带传送给浏览器的一个小文本文件。
    2).一旦web浏览器保存了某个cookie,那么它在以后每次访问该web服务器时,都会在HTTP请求消息头中将这个Cookie回传给web服务器。
    3).底层原理:web服务器通过在HTTP响应消息中增加Set—Cookie响应头字段,将Cookie信息发送给浏览器,
    浏览器则通过HTTP请求消息中增加Cookie请求头字段将Cookie回传给web服务器。
    一个Cookie只能标识一种信息,它至少含有一个表示该信息的名称(NAME)和设置值(VALUE)
    一个web站点可以给一个web浏览器发送多个Cookie,一个web浏览器也可以存储多个web站点提供的Cookie。
    浏览器一般允许存放300个Cookie,每个站点可以存放20个Cookie每个Cookie大小限制为4KB

    4).获取Cookie时,初始有一个Cookie:JSESSIONID,它是有Tomcat服务器产生的传到浏览器中,首次访问book.jsp页面传到
    浏览器存到集合中,再次访问时又有新的Cookie存到集合中,该Cookie会存到集合中的第一位,以此每次获取到Cookie都会放到集合
    第一位上。

  5. Cookie相关API
    ServletAPI中提供了一个javax.servlet.http.Cookie类来封装Cookie信息,他包含生成Cookie的信息
    和提取Cookie信息的各个属性的方法。
    ——向客户端写入Cookie
    1).创建对象
    构造方法:public Cookie(String name, String value)

    2).设置Cookie的最大时效,值为负表不存储,值为0表立即删除,值为正表示该Cookie的存储时间
    setMaxAge()和getMaxAge()方法

    3).设置Cookie的作用范围:可以作用当前目录和当前目录的子目录,但不能作用到当前目录的上一级目录
    setPath(request.getContextPath())和getPath()方法

    4).调用request的一个方法把Cookie传给客户端
    HttpServletRequest接口中定义了一个addCookie方法,它用于发送给浏览器的HTTP请求响应消息中增加一个Set-Cookie
    响应头字段(服务器)
    HttpServletRequest接口中定义了一个getCookie方法,它用于从HTTP请求消息Cookie请求头字段中读取所有的Cookie项
    (浏览器)
    getName()和getValue()方法
    setValue()

从浏览器获取Cookie

Cookie[] cookies = request.getCookies();
    if(cookies != null && cookies.length > 0){
        for(Cookie cookie : cookies){
            String cookieName = cookie.getName();
            String cookieValue = cookie.getValue();
            if(cookieName.startsWith("ATGUIGU_BOOK_")){
                out.println(cookieValue);
                out.print("<br>");
            }
        }
    }

6 . Cookie的发送
①创建Cookie对象
②设置最大的时效
③将Cookie放入到HTTP响应头
如果创建一个Cookie,并将它发送到浏览器,默认情况下它是一个会话级别的cookie,存储在浏览器内存中,用户推出浏览器之后
被删除。若希望浏览器将该Cookie存储在磁盘上,则需要使用maxAge(),并给出一个以秒为单位的时间,将最大时效设置为0,表示让
浏览器删除Cookie。
发送Cookie则需要使用HttpServletResponse的addCookie方法,将cookie插入到一个Set-Cookie HTTP响应报头
中,由于这个方法并不修改任何之前指定的Set-Cookie报头中,而是创建新的报头,因此将这个方法称之为addCookie,而非SetCookie

7 . 会话Cookie和持久化Cookie
如果不设置过期时间,则表示这个Cookie的生命周期为浏览器会话期间,只要关闭浏览器窗口,cookie就消失了,这种生命周期为浏览器
会话期的cookie为会话cookie,会话cookie一般不保存在硬盘上而是保存在内存里。
如果设置了过期时间,浏览器会把cookie保存到硬盘上,关闭之后在打开浏览器,这些cookie依然有效直到超过设定的过期时间。
存储在硬盘上的cookie可以在不同浏览器进程之间共享,比如两个IE窗口,而对于保存在内存cookie,不同的浏览器有不同的处理方式。

8 . 案例:保存浏览过的书本信息
books.jsp中心显示十本书,点击浏览之后跳转到book.jsp页面,点击book.jsp页面中的return超链接,返回到books.jsp页面
在,books.jsp页面中显示浏览过的书本,超过五本之后,就依次删除最早浏览过的书,若查看看过的书,则把该书保存到最新的位置上,且历史记录
不能重复。
1.books.jsp:两件事,第一提交表单,第二获取服务端发送的Cookie,并把符合条件的Cookie显示出来
2.book.jsp:两件事,第一获取表单数据,创建Cookie把获取到的数据作为cookieName返回到books.jsp,第二、处理获得的
Cookie,把符合规则的Cookie存到 集合中去,不符合的Cookie删除,最后返回到boos.jsp页面中.

9 . Session
Session机制采用的是在服务器端保持HTTP状态信息的方案。
其本来的含义是指有始有终的一系列动作/消息,比如打电话是从拿起电话拨号到挂断电话这中间的一系列过程可以称之为一个Session。
在web开发环境中,又指一类用来在客户端与服务器端之间保持状态的解决方案,有时Session也用来指这种解决方案的存储结构。
服务器使用的是一种类似于散列表的结构,来保存信息。当程序需要为某个客户端的请求创建一个Session时,服务器首先检查这个客户端
请求里是否含有一个Session标识,即SessionID,若已经包含一个SessionID,则说明以前已经为此客户端创建过Session,服务器就
按照sessionId把这个session检索出来使用,(如果检索不到,可能会创建一个,这种情况可能会出现在服务器端已经删除了该用户对应的
session对象,但用户人为的在URL后面添加一个JSESSION的参数)。如果客户端请求不包含sessionId,则为此客户端创建一个session
并且产生一个与此session相关的sessionId,这个sessionId将在本次响应中返回给客户端浏览器保存。

10 . 保存SessionId的几种方式

①保存sessionid的方式可以采用Cookie,这样在交互过程中浏览器可以自动的按照规则把这个标识发送到服务器。但由于Cookie可以被浏览器禁用,必须有其他机制在浏览器禁用Cookie时仍然能够把session id传递回服务器。
②经常采用的一种技术叫做URL重写,就是把sessionid以参数形式附加在URL地址的后面,HttpServletresponse接口中定义了
两个用于完成URL重写的方法encodeURL()和encodeRedirect(),附加的方式有两种

一种作为UR了路径的附加信息
另一种是作为查询字符串附加在URL后面,网络在交互过程中始终保持状态,就必须在每个客户端可能请求的路径后面都包含这个sessionid具体代码:action=”<%=response.encodeUrl(“hello.jsp”) %>”即可完成即使禁止session,也可跟踪session

11.Session Cookie
①session通过sessionid来区分不同的客户,session以cookie或者URL重写为基础,默认使用Cookie来实现,系统会创建
一个名为JSESSIONID的输出cookie,这称之为session cookie。
②session cookie是存储到浏览器内存中,并不是写到硬盘上通常看不到JSESSIONID,但是当浏览器禁止cookie,web服务器
会采用URL重写的方式传递sessionid,此时可以在地址栏看到。
③session cookie针对某一次会话而言,会话结束,session cookie也随之消失,而persistent cookie只是存在于
客户端硬盘的一段文本。
④关闭浏览器,只会是浏览器端内存中的session cookie消失,但不会使保存在服务器端session对象消失,同样不会使保存到
硬盘上的持久化cookie消失。
⑤persistent cookie也就是我们常说的Cookie

12.HttpSession的生命周期
1).何时创建session对象

①对于JSP:浏览器访问服务器端的任何一个JSP,服务器是否都会立即创建一个HttpServlet对象呢?不一定。
对于JSP:若当前的JSP是客户端访问的当前web应用的第一个资源,且JSP的page指定的session属性值为false则服务器端不会为
JSP创建一个HttpSession对象,若当前JSP不是客户端访问的当前web应用的第一个资源,且其他页面创建过HttpSession对象,则当前JSP页面会返回一个
HttpSession对象,而不会创建一个新的Session对象
②对于Servlet:若Servlet是客户端访问的第一个web应用资源,则只有调用了request.getSession()或者request.getSession(true)
才会创建HttpSession对象.
实际上就是只有某个Servlet程序调用了HttpServletRequest.getSession或者HttpServletRequest.getSession(true)
这两个方法时session才会被创建。

2).在Servlet中如何获取HttpSession对象

getSession(boolean create):
参数为false,若没有和当前的JSP页面关连HttpSession对象,返回null,若有返回该session对象,
参数为true一定返回一个HttpSession对象,若没有和当前的JSP页面关连HttpSession对象,则服务器创建一个返回,
若有直接返回关联的session对象
getSession():等同于request.getSession(true)

3).page指令的session=“false”,表示当前JSP页面禁止使用session的隐含变量,但可以使用其他显式的HttpSession

4).什么时候销毁Session对象

直接调用HttpSession的invalidate方法,该方法使HttpSession失效
服务器卸载了当前web应用
超出HttpSession的过期时间

5).并不是关闭浏览器就销毁的session

13.HttpSession相关API
比较重要的:

①获取session对象:request.getSession和request.getSession(true)
②属性相关的:setAttribute(String, Object)getAttribute(String)removeAttribute(String)
③使HttpSession失效的:invalidate()
④设置和获取最大时效的:setMaxInactiveInterval(int)getMaxInactiveInterval()
getId()
isNew()
getAttributeNames()
getCreationTime()
getLastAccessedTime()
getServletContext()
getSessionContext()
getValue(String)
getValueNames()
putValue(String, Object)
removeValue(String)

总结:
page指令中的session属性为true/false,只针对session的隐含对象,并不包括显式的session对象
request.getSession(true):参数为true/false,针对显式的session对象

14.相对路径与绝对路径
①开发时建议使用绝对路径,写绝对路径肯定没有问题,但是使用相对路径时可能会出现问题
具体内容在Demo7_RelativePathAndAbsolutePath目录下的note.txt文件中

15.表单的重复提交
①调用RequestDispatcher.forward()方法,浏览器所保留的URL是先前表单提交的的URL,此时刷新浏览器将
再次提交用户先前输入的数据,造成重复提交。
若是使用HttpServletResponse.sendRedirct()方法将客户端重定向到成功页面,将不会出现重复一条的问题。
②如何避免:
在表单中做一个标记,提交到Servlet时,检查标记是否与预定义的标记一致,若一致则受理请求,并销毁标记,
若没有标记或标记不一致,则直接提示”重复”
③解决方案:

1).使用隐藏域,但是隐藏域Servlet中验证之后没有办法销毁。该方案不行。
2).使用request.setAttribute()请求参数做标记,但是表单页面刷新后,request已经销毁,在提交
再提交表单是一个新的request,或者说请求token.jsp页面是一个请求,form表单提交是一个请求,这是两个请求,
所以,在Servlet中获取不到请求token.jsp页面的这个请求所设置是属性值。该方案不行。
3).使用session和隐藏域,session在页面上添加属性值,隐藏域提交参数,Servlet中获取到session
中的的属性值,在获取隐藏域提交的参数,互相比对成功之后删除session中的属性。该方案可以。
步骤:token.jsp页面根据PathServlet跳转到success.jsp或者重复提交之后跳转到warn.jsp
token.jsp中生成一随机数,该随机数分别存到隐藏域和session中。
PathServlet中分别取出隐藏域和session中的属性值,并判断比对是否正确,是则删除session中的
属性值,并跳转到success.jsp,否则跳转到warn.jsp提示重复提交并return。

16.验证码
其实现机制是与避免表单重复提交的机制是一样的

17.form提交请求到Servlet的方法

①在web.xml中配置Servlet
    例如:购物车案例
        form表单中:action="<%=request.getContextPath() %>/step1Servlet"
        web.xml配置:  
          <servlet>
            <display-name>step1Servlet</display-name>
            <servlet-name>step1Servlet</servlet-name>
            <servlet-class>com.shopCart.Servelt.Step1Servelt</servlet-class>
          </servlet>
          <servlet-mapping>
            <servlet-name>step1Servlet</servlet-name>
            <url-pattern>/step1Servlet</url-pattern>
          </servlet-mapping>
②在Servlet中使用注解的方式
    例如:避免重复提交案例
        form表单中:action="<%=request.getContextPath()%>/tokenServlet"
        Servlet中类名之上:@WebServlet("/tokenServlet")
注意:使用注解这种方式时,注解的值要与form表单中的值一致
原文地址:https://www.cnblogs.com/tengpengfei/p/10453981.html