该用户从未签到
|
状态管理+ \9 {3 t, T# W" M% L
1)什么是状态管理4 v! _/ S" \% n
将客户端(一般是浏览器)与服务器之间的多次5 c2 H1 D! Z1 ?$ R) l7 { F( P+ l
交互当作一个整体来看待,即将多次操作所涉及的
8 H' z9 h8 v$ k- |6 G2 g& F 数据记录下来。
( f2 `. U8 v/ |3 U 2)怎样进行状态管理
8 v6 q- T$ @/ ]5 g/ D% m 第一种方式,在客户端管理用户的状态
l8 y! a# o G (cookie)。
2 L# G8 M% E- A3 @ 第二种方式,在服务器端管理用户的状态
$ S$ f* K5 R) Y1 y& C2 M* w2 E$ A (session)。
" t7 {/ Q" K9 |0 j 3)cookie* i0 V6 n7 Y: E6 G. G
a,什么是cookie?$ A C, J5 Z, Y: C" g
浏览器在访问服务器时,服务器将一些数据, V+ K, G( G% `: Q7 ?4 {! @+ ?- U
以set-cookie消息头的形式发送给浏览器。浏览
' z7 ~, ?3 V" S( H; Z+ \8 t& V: q 器会将这些数据保存起来。当浏览器再次访问
' C( r) k, m% w9 {2 _. \. \ 服务器时,会将这些数据以cookie消息头的形式* W2 a# o3 f3 O3 B8 N7 n. J3 J3 B
发送给服务器。通过这种方式,可以管理用户的
/ W0 k0 M$ J- O; y9 t( g8 B 状态。
1 L9 f( M) ~$ b- `: j4 _/ M0 H" g8 x b,怎样创建cookie?
# e( M0 B' \" e: T9 s9 u Cookie cookie = new Cookie(String name,
e+ i3 n& e$ m% s9 M String value);
2 z# q+ `$ E* p# w response.addCookie(cookie);
M1 O0 A- T6 e# f3 s* J c,查询cookie3 v1 z, u% Z8 n( x" k- W+ i
//如果没有cookie,则返回null。
; p& ?3 W2 q3 F- o9 p3 x# Q Cookie[] cookies = request.getCookies();
( m4 B& F1 G' X- ] String name = cookie.getName();0 r9 u0 O1 \( A2 K: f( n
String value = cookie.getValue();
1 r, M; F t5 Y% U) ^ d,cookie保存时的编码问题; H$ ]! q0 S" u$ E- A! j
cookie的值只能是ascii字符,如果是中文,
' {5 {3 R: x w( [ 需要将中文转换成ascii字符形式。
7 g$ K9 c$ z# h1 m1 a4 n8 { 可以使用URLEncoder.encode()方法和 F P/ i0 B% n- l5 R# O! v5 [8 Y
URLDecoder.decode()方法来进行这种转换。
. q* s/ `+ z$ ?3 w& M3 D e,cookie的保存时间
- Y' f2 b5 N/ ^" g; r! O+ Y" r cookie.setMaxAge(int seconds);
- t* |! z. U. C- @; M6 f7 y seconds > 0:浏览器会将cookie以文件的方式
4 `* N0 l9 K$ T& r2 i 保存在硬盘上。在超过指定的时间以后,会删除
% D5 ?. ^+ h- J+ o 该文件。8 z! q' n0 p. {8 z7 w; u
seconds < 0:默认值,浏览器会将cookie保存# `& f+ V: }: l1 [
在内存里面。只有当浏览器关闭之后,才会删除。
7 k2 f' X; z8 g7 p# \' a5 r seconds = 0:删除。' j9 E0 v3 u7 w: t; N
f,删除cookie6 }: D& U1 f8 p5 Z, d$ G! F
比如要删除一个name为"username"的cookie。
$ i1 g8 }- N, b7 a1 ^ Cookie c = new Cookie("username","");
+ o; v( h3 U# I" Q R- ?9 Y/ B c.setMaxAge(0);
; i- h- u1 Y' j2 a response.addCookie(c);
5 i* _2 o9 W2 ?6 P. ?. q g,cookie的路径问题
. G2 K0 I, w7 u! v: D1 Z6 J 浏览器在向服务器上的某个地址发送请求时,
9 p+ f$ T; z& d8 `0 t, u 会先比较cookie的路径与向访问的路径(地址)是
; u5 w& @! T9 \, _8 u 否匹配。只有匹配的cookie,才会发送。" y% R" D6 Y9 T9 H0 |$ H
cookie的路径可以通过
. Q* x, w" S- r& m7 z: |3 t cookie.setPath(String path)方法来设置。
' R: E' `, n$ o% J% y, ^# P 如果没有设置,则有一个缺省的路径,缺省的* I8 G2 P+ r# c, P- M. M: J
路径是生成该cookie的组件的路径。
* w! X( z" \; ]( z: s 比如: /appname/addCookie保存了一个cookie,
9 j, I& d& K0 l1 }+ I) R 则该cookie的路径就是/appname/addCookie。
+ B( W; E9 h# o2 B* @ # f1 B3 |% w+ I$ }0 y/ h
规则:
0 Y9 \/ t: l+ }- K! m cookie的路径必须是要访问的路径的上层目录, u+ D$ u5 Y2 S9 y0 b+ o0 ~" ]
或者是与要访问的路径相等,浏览器才会
0 ^8 I* E* v8 {) K2 D! [6 B 将cookie发送给服务器。; t1 R s; ~. B4 v% M+ ^% t2 x+ Z
3 G, S& L; [: w0 | 一般可以设置setPath("/appname"),表示访问
! l& ?: R5 q8 H 该应用下的所有地址,均会发送cookie。5 n1 ]2 G7 R7 r# T3 M, c
h,cookie的限制' @# Y! f6 ]' M( N0 m, _/ `! S
cookie可以禁止
9 y! n' \( R4 b: n3 o" ` cookie的大小有限制(4k左右)
9 f5 u3 Y+ C ~8 O7 c+ i* a cookie的数量也有限制(浏览器大约能保存300个) 9 R! [; N5 T) q X0 ]( `
cookie的值只能是字符串,要考虑编码问题。4 }. O# S, \& |7 H
cookie不安全, n0 Y1 S3 q4 T6 c3 Y( M" {
练习:
% E* g$ F3 _3 h, H1 \6 V$ | 写一个Add_FindCookieServlet,该servlet先查询- r0 _" u* F6 s: m% l0 |* U( i: {
有没有一个名叫name的cookie,如果有,则显示
1 O6 j9 F( O! ?" { 该cookie的值,如果没有,则创建该cookie(" ^0 e$ E O) A7 d+ J) i1 ~
cookie的名字:name,cookie的值:zs)。- r/ G# C# @5 M* k: P4 |
3 V( C; K) j# A
' f& J! a& p% F( B5 j: { 4)session
0 ]2 d( E) `( S# Z9 e a,什么是session? l' @/ ^- z4 A S1 E y
浏览器访问服务器时,服务器会创建一个session
2 |" F0 p4 F4 s 对象(该对象有一个唯一的id, 一般称为sessionId)
r( z+ S* v. H1 S 。服务器在缺省情况下,会将sessionId以cookie
* d2 U# l9 v- G+ A0 ? 机制发送给浏览器。当浏览器再次访问服务器时,. _6 T7 ]2 d$ X: u0 }0 ~! [
会将sessionId发送给服务器。服务器依据sessionId b9 i/ u9 u- T1 Q
就可以找到对应的session对象。通过这种方式,7 ?" q/ ? }. L& n/ R5 N& o
就可以管理用户的状态。
, _( j0 K6 Z8 Q/ H) a, z# d; m/ ^% Z; b b,如何获得session对象
. k8 o* ^0 R% o 方式一:
: p0 c3 ^( }+ X# | E HttpSession session = F2 H' e; Q, O
request.getSession(boolean flag);
% q' M9 P9 E, U# a3 \4 S7 G/ k 当flag = true:/ i9 X% M1 b8 j Z
服务器会先查看请求中是否包含sessionId,3 c# p2 L* R2 _( l
如果没有,则创建一个session对象。
7 n, m* m Q* k3 T; g3 J 如果有,则依据sessionId去查找对应的
! X" e# `" H4 `& t7 R3 c+ w) H session对象,如果找到,则返回。, B& L1 p; R3 D4 O
如果找不到,则创建一个新的session对象。% S1 |2 {) a' b' s' ]
当flag = false:3 ]* u+ b6 [6 q3 r
服务器会先查看请求中是否包含sessionId,, c/ c" c5 r. D4 c
如果没有,返回null。
$ G" u) D; E1 N/ x; p 如果有,则依据sessionId去查找对应的- @2 s' r; N; W# u* ~
session对象,如果找到,则返回。
* g6 s( j5 b. \% W' c% H 如果找不到,返回null。+ i% e8 z5 F t \! Y3 i' |; R; E
方式二:
* _) n, s5 \8 e% N9 |0 l HttpSession session = 6 g, G( o6 Q8 n6 A' j& \
request.getSession();; h) K4 @! P$ _/ o% M# i
与request.getSession(true)等价。 E3 P5 @+ p, J1 E
c,HttpSession接口提供的一些方法
% ]% {# ?0 I: @) l& Z //获得sessionId。
$ g" h- a! W3 z/ A/ `4 R String session.getId();9 a( e- |& c' x O: i3 B
//绑订数据
$ ]& m: J2 X: ?0 i session.setAttribute(
3 w) [2 X$ [+ l1 I String name,Object obj);
2 I* m5 u! Y) a //obj最好实现Serializable接口(服务器( E+ b" Q0 L* T1 g5 j* X' m
在对session进行持久化操作时,比如钝化
! Z6 k4 t# j3 A' `& J 、激活,会使用序列化协议)。) R6 A' N" ]4 }' g0 z% E; v
Object session.getAttribute(String name);
- e) }2 J; U* }& l7 B //如果name对应的值不存在,返回null。; Q2 b$ }/ i4 L5 F
session.removeAttribute(String name);. \5 a) c3 c3 r1 Y# {
d,session超时* I6 H! r2 e1 G, {
服务器会将超过指定时间的session对象
2 x, X7 R x# Y& U+ I, M2 m& X 删除(在指定的时间内,该session对象没有
) V, n+ @8 _ ~4 o 使用)。
9 p2 k8 W. O' _ 方式一:
8 `" q, D4 |' [+ y, a session.setMaxInactiveInterval(1 x6 R/ X# }; b$ r' {+ U
int seconds);
6 h: D+ B6 `$ [ 方式二:
" u4 e$ d* A: p3 z1 L. b0 M 服务器有一个缺省的超时限制,可以
2 e% \* [" Y3 ~# q 通过相应的配置文件来重新设置。
+ i, q9 y/ T: l' P7 v, a 比如可以修改tomcat的web.xml(
! H7 B& Z: m% P; g9 w; l& c tomcat_home/conf下面)。2 r% e, E( O( {0 Z
<session-config>5 O$ x+ d% M' T0 W
<session-timeout>30</session-timeout>5 n0 X- z% x+ T: k% k2 ]& D
</session-config>. M. S& Z, }* B3 f1 ]/ c7 N
另外,也可以只修改某个应用的web.xml。
3 y5 `/ P( }% u e,删除session% r6 E& k% y) w9 _# t, {1 w
session.invalidate();
/ F$ `8 V; X0 Z% _5 l, j% t 9 e8 s- B3 J$ J$ y
案例:
( J% j% J5 Q, `# B6 ` session验证
4 I+ {- z+ K2 A: x0 z0 O7 N step1 在登录成功之后,在session上绑订一些数据。) D5 v0 {; e- L) P% V n
比如: ~, v$ Q: g! i( I; K* P) d
session.setAttribute("user",user);
' g$ m* a0 X. X" W: f" P step2 在访问需要保护的页面或者资源时,执行; X$ j7 m: A. l) H! O' B
Object obj = session.getAttribute("user");* [$ I8 a, u1 |1 _# {2 _- K
如果obj为null,说明没有登录,一般重定向到
+ S; l; ?9 e" W; p* d 登录页面。* y' O: A1 T4 N
% f9 s/ x0 g E- q, O! u- y m; P
|
|