HTTP协议是一种无状态的协议,WEB服务器本身不能识别出哪些请求都是完全孤立的。
作为WEB服务器,必须能够采用一种机制来唯一标识一个用户,同时记录该用户的状态。
什么是状态管理
状态指的是数据,管理指的是多次交互时对数据的修改。
状态管理的两种常用模式:
①客户端状态管理技术
将状态保存在客户端,代表性的是cookie技术。
②服务端状态管理技术
将状态保存在服务端,代表性的是session技术。
Cookie机制
cookie机制采用的是在客户端保持HTTP协议状态信息的方案。
web服务器通过在HTTP响应信息中增加set-Cookie响应头字段将Cookie信息发送给浏览器,浏览器则通过在HTTP请求消息中增加Cookie请求字段将Cookie回传给服务器。
一个Cookie只能标识一种信息,它至少含有一个标识该信息的名称(name)和设置值(value)。
JSP Cookie 处理需要对中文进行编码与解码,方法如下:
String str = java.net.URLEncoder.encode("中文","UTF-8"); //编码 String str = java.net.URLDecoder.decode("编码后的字符串","UTF-8"); // 解码
使用JSP设置Cookie
使用JSP设置Cookie包含三个步骤:
①创建一个Cookie对象:调用Cookie的构造函数,使用一个Cookie名称和值做参数,它们都是字符串。
Cookie cookie = new Cookie("key","value");
②设置有效期:调用setMaxAge()函数表明Cookie在多长时间(以秒为单位)内有效。
cookie.setMaxAge(60*60*24); //将有效期设置为24小时
③将Cookie发送至HTTP响应头中:调用response.addCookie()函数来向HTTP响应头中添加cookie。
response.addCookie(cookie);
实例演示
以下是一个简单的 HTML 表单通过GET方法将客户端数据提交到 main.jsp 文件中,并设置 cookie:
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>菜鸟教程(runoob.com)</title> </head> <body> <form action="main.jsp" method=GET> 站点名: <input type="text" name="name"> <br /> 网址: <input type="text" name="url" /> <input type="submit" value="提交" /> </form> </body> </html>
main.jsp文件代码如下所示:
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@ page import="java.net.*" %> <% // 编码,解决中文乱码 String str = URLEncoder.encode(request.getParameter("name"),"utf-8"); // 设置 name 和 url cookie Cookie name = new Cookie("name", str); Cookie url = new Cookie("url", request.getParameter("url")); // 设置cookie过期时间为24小时。 name.setMaxAge(60*60*24); url.setMaxAge(60*60*24); // 在响应头部添加cookie response.addCookie( name ); response.addCookie( url ); %> <html> <head> <title>设置 Cookie</title> </head> <body> <h1>设置 Cookie</h1> <ul> <li><p><b>网站名:</b> <%= request.getParameter("name")%> </p></li> <li><p><b>网址:</b> <%= request.getParameter("url")%> </p></li> </ul> </body> </html>
使用JSP读取Cookie
想要读取cookie,您就需要调用request.getCookies()方法来获得一个javax.servlet.http.Cookie对象的数组,然后遍历这个数组,使用getName()方法和getValue()方法来获取每一个cookie的名称和值。
让我们来读取上个例子中的cookie, 以下为 cookie.jsp 文件代码:
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@ page import="java.net.*" %> <!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>获取 Cookie</title> </head> <body> <% Cookie cookie = null; Cookie[] cookies = null; // 获取cookies的数据,是一个数组 cookies = request.getCookies(); if( cookies != null ){ out.println("<h2> 查找 Cookie 名与值</h2>"); for (int i = 0; i < cookies.length; i++){ cookie = cookies[i]; out.print("参数名 : " + cookie.getName()); out.print("<br>"); out.print("参数值: " + URLDecoder.decode(cookie.getValue(), "utf-8") +" <br>"); out.print("------------------------------------<br>"); } }else{ out.println("<h2>没有发现 Cookie</h2>"); } %> </body> </html>
Session机制
Session机制采用的是在服务器端保持HTTP状态信息的方案,服务器采用一种类似于散列表的结构来保存信息。
实现原理:
当程序需要为每一个客户端的请求创建一个Session时,服务器首先检查这个客户端的请求里是否包含了一个SessionId,包含则说明以前已经为此客户创建过Session,服务器就按照SID把这个Session检索出来使用。 如果客户请求不包含SID,则为此客户创建一个Session并且生成一个与此Session相关联的SID,这个SID将在本次响应中返回给客户端保存。
保存sessionId的几种方式
保存sessionId的方式可以采用Cookie,这样在交互过程中浏览器可以自动的按照规则把这个标识发送给服务器。 由于Cookie可以被人为禁止,必须有其他机制以便在Cookie被禁用时仍然能够把sessionId传递回服务器,经常采用的一种技术叫做URL重写,就是把sessionId附加在URL路径的后面。
session cookie
Session通过sessionId来区分不同客户,Session是以Cookie或URL重写为基础的,默认使用Cookie来实现,系统会重建一个名为JSESSIONID的输出Cookie,这称为session cookie,以区别于persistent cookie(也就是我们通常所说的Cookie),session cookie是存储于浏览器内存中的,并不是写到硬盘上的,通常看不到JSESSIONID,但是当把浏览器的Cookie禁止后,web服务器会采用URL重写的方式传给sessionId,这时可以在地址栏看到。
HttpSession的生命周期
① 什么时候创建HttpSession对象
对于Servlet而言:若Servlet是客户端访问的第一个web应用的资源,则只有调用了request.getSession()或request.getSession(true);才会创建Session对象。
② 什么时候销毁HttpSession对象
session.invalidate:使当前的session对象立即失效。
服务器卸载了当前Web应用。
超出HttpSession的过期时间。
获取Session
① request.getSession()方法
在JSP页面中有一个Session的隐式对象,这个隐式对象实际上就是通过request.getSession()这个方法获得的,所以总是可以获得Session对象的。
② request.getSession(true)方法(默认)
查询请求中是否有关联的JSESSIONID,如果有则返回对应的session对象,没有则生成一个新的Session对象。这个方法一定可以获得一个Session对象。
③ request.getSession(false)方法
如果有则同上,如果没有则返回null。
本着节省服务器内存的原则:
向Session中存储登录信息时:request.getSession().setAttribute();
向Session中获取登录信息时:request.getSession(false).setAttribute();
下表列出了session对象的一些重要方法:
S.N. | 方法 & 描述 |
---|---|
1 | public Object getAttribute(String name)
返回session对象中与指定名称绑定的对象,如果不存在则返回null |
2 | public Enumeration getAttributeNames()
返回session对象中所有的对象名称 |
3 | public long getCreationTime()
返回session对象被创建的时间, 以毫秒为单位,从1970年1月1号凌晨开始算起 |
4 | public String getId()
返回session对象的ID |
5 | public long getLastAccessedTime()
返回客户端最后访问的时间,以毫秒为单位,从1970年1月1号凌晨开始算起 |
6 | public int getMaxInactiveInterval()
返回最大时间间隔,以秒为单位,servlet 容器将会在这段时间内保持会话打开 |
7 | public void invalidate()
将session无效化,解绑任何与该session绑定的对象 |
8 | public boolean isNew()
返回是否为一个新的客户端,或者客户端是否拒绝加入session |
9 | public void removeAttribute(String name)
移除session中指定名称的对象 |
10 | public void setAttribute(String name, Object value)
使用指定的名称和值来产生一个对象并绑定到session中 |
11 | public void setMaxInactiveInterval(int interval)
用来指定时间,以秒为单位,servlet容器将会在这段时间内保持会话有效 |
Session超时
Web服务器会将空闲时间过长的Session对象删除掉,以节省服务器内存空间。Web服务器缺省的超时时间限制一般是30分钟。
① 可以通过web.xml文件设置修改时间限制
<session-config> <session-timeout>15</session-timeout> </session-config>
② 也可通过编程的方式来修改
void setMaxInactiveInerval(int interval)
用来指定时间,以秒为单位,Servlet容器将会在这段时间内保持会话有效。
URL重写
所谓URL重写也就是说想要在哪个页面获取Session,URL就写哪个JSP
sessionId是通过Cookie传递给浏览器,但如果浏览器的Cookie被禁止就会出现问题,最好的解决办法就是重写URL。
①如果是链接地址(href)或表单提交(action),使用response.encodeURL(String url)生成重写后的URL。
②如果是重定向,使用response.encodeRedirectURL(String url)生成重写后的URL。