day11续—状态管理

来源:互联网 发布:mac视频下载工具 编辑:程序博客网 时间:2024/06/05 05:46
状态管理

为什么需要状态管理:

Web应用程序使用HTTP协议作为传输数据的标准协议,而HTTP协议是无状态协议,即一次请求对应一次响应,响应结束后连接即断开,同一个用户的不同请求对于服务器端来讲并不会认为这两个请求由什么关联性,并不会以此区分不同的客户端。但实际情况中还是需要服务器端能够区分不同的客户端以及记录与客户端相关的一些数据,所以状态管理能够做到不同客户端的身份识别。

什么是状态管理:
将客户端与服务器之间多次交互当做一个整体来看待,并且将多次交互中涉及的数据保存下来,提供给后续的交互进行数据的管理即状态管理。
这里的状态指的是当前的数据,管理指的是在这个多次交互的过程中对数据的存储、修改、删除。
生活中很多与状态管理类似的案例。如洗车卡记录洗车次数就是很典型的状态管理。洗车卡可以是一张记录简单次数的标示,车主每次携带卡片洗车后由商家修改,车主即可带走这张记录数据的卡片,商家不会保存任何数据,客户自己负责携带需要维护的数据。还有一种处理方式就是商家只给客户一个卡号,每次客户来洗车时自己不会记录洗车次数,只要报上卡号,商家就会从系统中找到与卡号对应的数据,修改后仍然是商家保存,客户带走的只是一个卡号这个标示。
以上两种模式都能实现洗车次数的记录,也就是数据的管理,只是各有利弊,程序中的状态管理与这个案例都采用了同样的处理原理。

状态管理两种常见模式:
一、Cookie
如果将数据存储在客户端,每次向服务器端发请求时都将存在客户端的数据随着请求发送到服务器端,修改后在发回到客户端保存的这种模式叫做Cookie。

二、Session
如果将数据存储在服务器端,并且为这组数据标示一个编号,只将编号发回给客户端。当客户端想服务器发送请求时只需要将这个编号发过来,服务器端按照这个编号找到对应的数据进行管理的这种模式叫做Session。

Cookie
一小段文本信息随着请求和响应,在客户端和服务器端之间来回传递。根据设定的时间来决定该段文本在客户端保存时长的这种工作模式叫做Cookie。最初服务器将信息发给客户端时是通过响应数据的Set-Cookie头信息来完成的。


如果客户端像服务器端AddServlet发送请求,遇到创建Cookie的代码时,那么一小段文本信息就会随着response响应中的头信息被传递会客户端。如图中Set-Cookie:uname=xxx就是从服务器端传递会客户端的文本信息。当文本信息到达客户端以后,会被保存在客户端的内存或硬盘上,存在内存中会随着内存的释放而消失,存在硬盘上则会保存更长的时间。
一旦客户端存有服务器发回的文本信息,那么当浏览器再次向服务器的发起请求时,如请求FindeServlet这个组件,那么存储的文本信息会随着请求数据包的消息头以Cookie::uname=xxx这样的形式将文本信息发送到服务器端。只要Cookie的生命周期没有结束,那么不管是存在内存还是硬盘上的信息都会在客户端向服务器端发出请求时自动的随着消息头发送过去。

如何创建Cookie

Servlet API提供了javax.servlet.http.Cookie这种类型来解释Cookie。其中存储的文本以name-value对的形式进行区分,所以创建Cookie时指定name-value对即可。这个name-value最终是以Set-Cookie这种消息头的形式跟随相应数据包到达客户端,所以要想将数据添加到消息头中需要使用response对象提供的方法。

创建Cookie的代码如下所示:
Cookie  c = new Cookie(String name,String value);
response.addCookie( c );

如何查询cookie:

当客户端向服务器发出请求时,服务器端可以尝试着从请求数据包的消息头中获取是否携带了Cookie信息。实现这一功能的代码如下:
Cookie[] =request.getCookies();

由于客户端是可以存放多个Cookie的,所以request提供的获取Cookie的方法的返回值是Cookie数组,如果想进一步获取某一个Cookie信息可以通过遍历数组,分别使用相应的getXXX方法来获取每一个Cookie的name和value。

如何修改Cookie:

所谓Cookie的修改,本质是获取到要变更值的Cookie,通过setValue方法将新的数据存入到cookie中,然后由response响应对象发回到客户端,对原有旧值覆盖后即实现了修改。



其中response.addCookie(c)是非常重要的语句,如果没有这一行代码,那么就算是使用setValue方法修改了Cookie的值,但是不发回到客户端的话,也不会实现数值的改变。所以只要见到response.addCookie这行代码,即服务器端发回了带有Set-Cookie消息头的信息。

Cookie的生存时间:

默认情况下,Cookie会被浏览器保存在内存中,此时Cookie的生命周期由浏览器决定,只要不关闭浏览器Cookie就会一直存在。
如果希望关闭浏览器后Cookie仍存在,则可以通过设置过期时间使得Cookie存在硬盘上得以保存更长的时间。
设置Cookie的过期时间使用如下代码:
void setMaxAge(int seconds);
该方法是Cookie提供的实例方法。参数seconds的单位为秒。


seconds > 0 :代表Cookie保存在硬盘上的时长
seconds = 0 : 代表Cookie的生命时长为现在,而这一刻稍纵即逝,所以马上Cookie就等同于过了生存时间,所以会被立即删除。这也是删除Cookie的实现方式。
seconds < 0 :缺省值,浏览器 会将Cookie保存在内存中。

Cookie编码解码:

Cookie作为在网络传输的一段字符串文本,只能保存合法的ASCII字符,如果要保存中文需要将中文变成合法的ASCII字符,即编码。
Cookie c = 
new Cookie("city",URLEncoder.encode("北京","utf-8"));

服务器读取客户端经过编码之后的信息时,要想能够正确显示需要将信息解码后才能输出。使用URLDecoder的decode()方法即可。
URLDecoder.decode(c.getValue(),"utf-8")

Cookie的路径:

客户端存储Cookie之后,并不是针对同一个应用访问任何资源时都自动发送Cookie到服务器端,而是会进行路径的判断。只有符合路径规范的请求才会发送Cookie到服务器端。
客户端会在接受Cookie时会为该Cookie记录一个默认路径,这个路径记录的是添加这个Cookie的Web组件的路径。
当客户端向 http://localhost:8080/test/file/addCookie.jsp发送请求时创建了cookie,那么该cookie的路径就是 /test/file.

此时:
访问的是 /test/file/a.jsp 或者 /test/file/b/c.jsp时,都会发送Cookie
访问的是 /test/d.jsp,则浏览器不会发送Cookie

Session
浏览器第一次访问服务器时,服务器会为该客户端分配一块对象空间,并且使用不同的SID来进行标识,该标识SID会随着响应发回到客户端,且被保存在内存中。当同一个客户端再次发送请求时,标识也会被同时发送到服务器端,而服务器判断要使用哪一个Session对象内的数据时,就会根据客户端发来的这个SID来进行查找。


如何获得Session:
获得session有两种情况。
请求中没有SID,则需要创建。
请求中包含一个SID,则根据SID去找对应的对象,但也可能找不到。

不管哪种情况都依赖于请求中的这个唯一标识,虽然对于编程人员来讲不需要去查看这个基本不会重复、编号很长的标识,但要想获取到与客户端关联的这个session对象一定要基于请求,所以在Request类型的API中包含获取到session对象的方法:
HttpSession s = request.getSession(boolean flag);
HttpSession s = request.getSession( );
flag = true是默认值。表示先从请求中找找看是否有SID,没有会创建新Session对象,有SID会查找与编号对应的对象,找到匹配的对象则放回,找不到SID对应的对象时则会创建新Session对象。所以,填写true就一定会得到一个Session对象。
flag = false:不存在SID以及按照SID找不到Session对象时都会返回null,只有根据SID找到对应的对象时会返回具体的Session对象。所以,填写false只会返回已经存在并且与SID匹配上了的Session对象。

如何使用Session:
Session作为服务器端为各客户端保存交互数据的一种方式,采用name-value对的形式来区分每一组数据。向Session添加数据绑定的代码如下:
void session.setAttribute(String name,Object obj);

获取绑定数据或移除绑定数据的代码如下:
void session.getAttribute(String name);
void session.removeAttribute(String name);

Session对象可以保存更复杂的对象类型数据了,不像Cookie只能保存字符串。

void  invalidate()删除session对象,不再进行管理。

Session超时:


Session会以对象的形式占用服务器端的内存,过多的以及长期的消耗内存会降低服务器端的运行效率,所以Session对象存在于内存中时会有默认的时间限制,一旦Session对象存在的时间超过了这个缺省的时间限制则认为是Session超时,Session会失效,不能再继续访问。
Web服务器缺省的超时时间设置一般是30分钟。
有两种方式可以修改Session的缺省时间限制,编程式和声明式。

void  setMaxInactiveInterval(int seconds)

<session-config>
   <session-timeout>30</session-timeout>
</session-config>

Session优缺点:
Session对象的数据由于保存在服务器端,并不在网络中进行传输,所以安全一些,并且能够保存的数据类型更丰富,同时Session也能够保存更多的数据,Cookie只能保存大约4kb的字符串。

Session的安全性是以牺牲服务器资源为代价的,如果用户量过大,会严重影响服务器的性能。

 浏览器禁用Cookie的后果
Session对象的查找依靠的是SID,而这个ID保存在客户端时是以Cookie的形式保存的。一旦浏览器禁用Cookie,那么SID无法保存,Session对象将不再能使用。

















2 0
原创粉丝点击