HeadFirst Jsp 06 (会话管理)

时间:2023-03-09 08:27:47
HeadFirst Jsp 06 (会话管理)

现在我们希望能够跨多个请求保留客户特定的状态. 现在, 模型中的业务只是检查请求中的参数, 并返回一个响应(建议), 应用中没有谁记得在当前请求之前与这个客户之间发生过什么.

与一个客户的整个会话期间, HttpSession对象会持久存储, 对于会话期间客户做的所有请求, 从中得到的所有信息都可以用HttpSession对象保存.

HeadFirst Jsp 06 (会话管理)

HeadFirst Jsp 06 (会话管理)

HeadFirst Jsp 06 (会话管理)

HeadFirst Jsp 06 (会话管理)

HeadFirst Jsp 06 (会话管理)

这里有个问题, 容器怎么知道客户是谁 ?

不能通过ip地址作为客户的唯一标识, 因为在外界看来, 如果局域网里的客户通过一个路由器连接到Internet, 那么所有客户都显示为路由器的ip地址, 但是他们是不同的客户, 如果这时候是网上购物, 那么大家就都放在同一个购物车里了.

所以, 客户需要一个唯一的会话ID, 道理很简单, 对客户的第一个请求, 容器会生成一个唯一的会话ID, 并通过响应把它返回给客户, 客户再以后的每一个请求中发回这个会话ID, 容器看到ID后, 会找到匹配的会话, 并把这个会话与请求关联. 看来这个ID就代表了一个session, 这个ID 就叫做 session ID, 会话ID.

客户和容器如何交换会话ID信息 ?

客户和容器之间通过 cookie 交换会话ID

容器几乎会做所有COOKIE工作

你确实必须告诉容器你想创建或使用一个会话, 但是除此之外, 生成会话ID, 创建新的cookie对象, 把会话ID放到cookie中, 把cookie设置为响应的一部分等等工作都是由容器负责, 对于后续的请求, 容器会从请求中的cookie得到会话ID, 这个会话ID与一个现有的会话匹配, 并把会话与当前请求关联.

在响应中发送一个会话cookie, HttpSession session = request.getSession();

HeadFirst Jsp 06 (会话管理)

判断是否为新会话, 还是之前的会话

HttpSession session = request.getSession();

if (session.isNew()) {

out.println(“This is a new session.”);

} else {

out.println(“Welcome back!”);

}

就算是客户不接受cookie, 你也能完成会话, 但是必须稍微多做点工作...

当用户禁用cookie时, 即cookie 不能工作时,在请求调用getSession(), 容器就会尝试使用cookie, 如果没有启动cookie, 这说明客户部不会加入会话, 换句话说, 会话的isNew()方法总会返回true, 也就是说, 每次都是一个新会话.

URL重写: 一条后路

容器就会求助于url重写, 但是只有当你额外做了一些工作, 对响应中发送的所有URL完成了编码, 此时URL重写才奏效,  response.encodeURL(“/BeerTest.do”) 想这个URL增加额外的会话ID信息.

所谓的 URL重写, 只是在url 后边加上 session_id 的信息. URL + ; jsessionid=1234567

容器没有办法判断是COOKIE失效还是第一次新的会话没有从客户那得到会话ID的信息, 所以它会采取双保险, 不仅针对会话ID有一个”set-cookie”首部, 而且会向URL追加会话ID(假设使用了response.encodeURL())。

把请求重定向到另外一个URL, 但是还是想使用一个会话, response.encodeRedirectURL(“/BeerTest.do”)

容器怎么知道cookie不能正常工作呢? 容器什么时候决定使用 URL重写 ?

当容器看到一个对 getSession()的调用, 而且容器从客户的请求没有得到会话ID, 它就知道必须尝试与客户建立一个新的会话. 此时, 容器并不知道cookie是否工作, 所以向客户返回第一个响应时, 它会同事尝试cookie和URL重写这两种做法.

为什么不先试试cookie, 得不到返回时再下一个响应中完成 URL重写 ?

容器没有从客户得到会话ID, 容器并不能判断这是一个新的会话还是cookie不能使用. 所以会采用双保险.

URL重写是自动的, 但是只有当你对URL完成了编码时它才奏效, 必须通过响应对象的一个方法(可以是 encodeURL()或encodeRedirectURL())来运行所有URL, 其他的所有事情都是由容器来做.

会话内容会保存在服务器中, 占用服务器内存空间, 那么如何删除会话呢?

这个删除时有讲究的, 不能session断开连接了就删除了, 因为有可能客户等一下来请求了, 所以, 我们的目的是, 如果客户在"太长"时间内还没有来请求, 那我们就删除 session对象. 那么这个时间多久算"太长"呢?

HeadFirst Jsp 06 (会话管理)

HeadFirst Jsp 06 (会话管理)

HeadFirst Jsp 06 (会话管理)

HttpSession 有哪些方法

HeadFirst Jsp 06 (会话管理)

HeadFirst Jsp 06 (会话管理)

HeadFirst Jsp 06 (会话管理)

HeadFirst Jsp 06 (会话管理)

cookie 还有其他作用么 ?

cookie 实际上就是客户和服务器之间交换的一小段数据(一个名/值 String对)

cookie 的一大妙处是, 用户不必介入, cookie 交换式自动的. 默认的, cookie与会话的寿命一样长, 但是你也可以让cookie活的更长一些.

-- 发送 cookie

Cookie cookie = new Cookie(“username”, name);

cookie.setMaxAge(30*60); // 设置cookie在客户端存活多久, 30*60秒=30分

response.addCookie(cookie);

-- 从客户端 得到cookie

Cookie[] cookies = request.getCookies();

for (int i=0; i<cookies.length; i++) {

Cookie cookie = cookies[i];

if (cookie.getName().equals(“username”)) {

String userName = cookie.getValue();

out.println(“Hello ” + userName);

break;

}

}