|
该用户从未签到
|
状态管理
- t4 i$ S7 k0 z' P7 U- l 1)什么是状态管理
1 V1 V1 }- @' J2 L% P 将客户端(一般是浏览器)与服务器之间的多次7 P+ V L% @, B
交互当作一个整体来看待,即将多次操作所涉及的
+ `$ o# j/ F, A 数据记录下来。
+ D' \( b$ G1 q2 j6 f% v; i6 b 2)怎样进行状态管理+ x0 z/ H) Q7 G7 |
第一种方式,在客户端管理用户的状态+ q. Z3 v K0 w$ z3 m2 Y: @7 g
(cookie)。
( A. G$ H- {) }4 G 第二种方式,在服务器端管理用户的状态; S+ r$ x: V# {) @3 `
(session)。
+ G2 p1 j# c& _; }7 `# k4 L8 b 3)cookie
, X" N. h3 G+ X5 s: Z a,什么是cookie?
" _+ o `* W6 F/ \0 v& s7 W$ _ 浏览器在访问服务器时,服务器将一些数据
3 ?3 Y$ t# I3 I5 R& _( t$ o 以set-cookie消息头的形式发送给浏览器。浏览
4 L' ^/ e5 }1 m" O' o 器会将这些数据保存起来。当浏览器再次访问2 p# D4 b7 P- n
服务器时,会将这些数据以cookie消息头的形式3 p" O1 V9 ] K
发送给服务器。通过这种方式,可以管理用户的
9 Y) E2 F8 j$ J5 Z3 A# Q* y6 N. q$ c 状态。; r. N# ?1 i$ c ]3 A4 M* u! h
b,怎样创建cookie?
! _ [7 y- m, N4 W* I) b7 K Cookie cookie = new Cookie(String name,
) ~+ o( ^* ?: x7 S. T8 F String value);
" X9 e1 l4 k2 y$ M: ?* Y& M p) Q response.addCookie(cookie);& Y. J. P6 c/ e6 ]
c,查询cookie7 H: v) l7 q) e% P) a7 h
//如果没有cookie,则返回null。6 H, H( B1 q0 d& E- E3 a- E+ b
Cookie[] cookies = request.getCookies();
/ t3 ~" H7 O. {. d6 H, Y String name = cookie.getName();4 n( O1 {& U. a; `& M$ o" K2 j
String value = cookie.getValue();0 b1 O/ ]: h4 r9 t& f
d,cookie保存时的编码问题+ v. J n. U6 _5 W
cookie的值只能是ascii字符,如果是中文, S# W" Q8 B. c7 N3 Z* u
需要将中文转换成ascii字符形式。: h8 C: x1 Q+ o) K; q
可以使用URLEncoder.encode()方法和0 O7 a0 V! h3 j; a- z3 Q w4 R
URLDecoder.decode()方法来进行这种转换。
* d( q/ `/ Q9 T C. m' J e,cookie的保存时间
" H6 y7 {# b/ t0 Z cookie.setMaxAge(int seconds);
6 t( \0 A0 u* j seconds > 0:浏览器会将cookie以文件的方式
; i: z6 I1 `; O 保存在硬盘上。在超过指定的时间以后,会删除
/ U; R" | o+ ^1 G! o7 B# Q7 w 该文件。
, q" q1 @: E( U5 l& e seconds < 0:默认值,浏览器会将cookie保存
& h/ t% }2 n( p# v 在内存里面。只有当浏览器关闭之后,才会删除。1 E) q' f1 o& j
seconds = 0:删除。
" C/ D" M" ~) d. ]. @ S f,删除cookie
, @) R( T( N, {: j# d5 \8 @% o. l 比如要删除一个name为"username"的cookie。
0 _6 ^/ L1 a& ?3 E Cookie c = new Cookie("username","");9 l6 Z* G. L. R. O5 G
c.setMaxAge(0);
" u X* e" |1 R! M- A response.addCookie(c);* a: N; L0 l8 _# Y N& {1 |
g,cookie的路径问题
}* b3 ~/ O; F/ \/ [ 浏览器在向服务器上的某个地址发送请求时,
0 ~- d8 j- \( \1 ^. R' S$ ? 会先比较cookie的路径与向访问的路径(地址)是
" H5 G% H; t7 `3 T0 w/ P! T 否匹配。只有匹配的cookie,才会发送。
7 a& k$ m: M6 z; \6 f, r. L( ` cookie的路径可以通过) M3 t; @1 p8 L4 a
cookie.setPath(String path)方法来设置。
2 C, R( q$ `0 | 如果没有设置,则有一个缺省的路径,缺省的
5 M5 [& [0 _+ t4 q2 s3 S 路径是生成该cookie的组件的路径。
4 D- e1 ^/ v) v 比如: /appname/addCookie保存了一个cookie,1 b0 ~4 K; H& y9 z7 e( |
则该cookie的路径就是/appname/addCookie。
9 b) S; E+ k6 A) M: W6 | : U/ W- M& B; Q# a
规则:
5 |( n: M6 o. h cookie的路径必须是要访问的路径的上层目录; W# v, }/ Z, L
或者是与要访问的路径相等,浏览器才会* C: Z0 A: [3 ?, ?8 {7 z* `( ^9 J
将cookie发送给服务器。
% [8 C3 { d+ U+ z . P# |3 x6 a* e- X4 k- R% D# i+ _1 {
一般可以设置setPath("/appname"),表示访问! A8 E/ E. h( u: i
该应用下的所有地址,均会发送cookie。: d, j7 L% V# t5 u, F
h,cookie的限制 r2 _( T# A& p8 h
cookie可以禁止
* a* X5 b# P0 Q6 R cookie的大小有限制(4k左右)
4 O$ [' P2 F% N) p9 r. f4 W9 m cookie的数量也有限制(浏览器大约能保存300个)
" d5 i) {' e& n/ z cookie的值只能是字符串,要考虑编码问题。8 X4 \( @; ?: K% X3 f9 c2 i
cookie不安全
/ ^3 R+ e. U- u& @! b 练习:8 P$ h( T4 _' n" L; q
写一个Add_FindCookieServlet,该servlet先查询" s3 z- n2 H# R6 E4 i5 R* y$ f
有没有一个名叫name的cookie,如果有,则显示
: l$ m+ r4 v. f9 J' c3 B 该cookie的值,如果没有,则创建该cookie(9 i- U) n9 X0 T: v9 ~7 i" d
cookie的名字:name,cookie的值:zs)。2 T$ Y2 N" G$ d
" u0 J$ ]6 M& a5 d4 y
: Z; y* N M% a; l. N& u0 T 4)session
! W# l8 K7 t# N) s6 i9 s5 n: a a,什么是session?/ \' v9 A3 Y8 z. C6 x) K
浏览器访问服务器时,服务器会创建一个session
1 S- I0 h$ a3 T" i$ q0 t3 t 对象(该对象有一个唯一的id, 一般称为sessionId)
8 t4 `5 q3 g! H B 。服务器在缺省情况下,会将sessionId以cookie! x: J- Z$ E" J t$ [ a
机制发送给浏览器。当浏览器再次访问服务器时,
2 Y9 N/ `# O8 r( U 会将sessionId发送给服务器。服务器依据sessionId
: B0 A3 L# D% S1 ] 就可以找到对应的session对象。通过这种方式,
, E% q0 d' W% g! b) a$ h7 K. i 就可以管理用户的状态。
# U1 D5 o: m( G8 P b,如何获得session对象3 i& u" w0 k: z; P# m( W
方式一:; a, g9 n# }9 D! C
HttpSession session =
. [% c9 ?3 v+ |% C) I7 h. x4 P request.getSession(boolean flag);7 N; q( E( n* n0 Y# P
当flag = true:( F: `, v1 E2 o; Z: o3 d0 }
服务器会先查看请求中是否包含sessionId,( j& ?1 x3 ]; n4 |& y% O: U
如果没有,则创建一个session对象。
_* P% O! g/ H" ~, } 如果有,则依据sessionId去查找对应的& p4 g# F8 z+ }) ]/ A1 N5 _- f* n
session对象,如果找到,则返回。* c! y0 I4 ^7 U- g5 c9 k
如果找不到,则创建一个新的session对象。; W1 }6 e4 \, H) u4 i
当flag = false:
8 I: M5 Q: t, ~: `/ ?+ N; u) n 服务器会先查看请求中是否包含sessionId,
- L8 Y& \2 F+ {, b5 y1 @: M 如果没有,返回null。
& Z8 G3 N5 Z5 w( a' j7 P' q 如果有,则依据sessionId去查找对应的1 T" Y+ p( H5 B% y
session对象,如果找到,则返回。
8 n! @5 q, x% v. m* v, y9 {9 D l- l 如果找不到,返回null。
6 W+ U$ L' g6 D3 Z% A* j8 e4 o 方式二:3 ?, O3 W4 S5 B S5 d
HttpSession session =
9 N+ k" i3 j8 y9 c! M request.getSession();
9 _7 u) k2 L. Q0 W: x: r$ W 与request.getSession(true)等价。
( z! g! a! O! d% {* h2 N8 D- v c,HttpSession接口提供的一些方法
! L% N4 x- P0 |. y& A3 y1 \! { //获得sessionId。
1 y$ Z9 W* i6 R+ z) W5 {0 x6 W6 C String session.getId();
e( B2 z0 W5 Q) o* ^7 } //绑订数据
3 ?, ^, Y3 n$ p$ d session.setAttribute(2 a8 H! I4 M! E) g% {
String name,Object obj);; o7 i0 M4 z4 X; n7 g' }+ v# E
//obj最好实现Serializable接口(服务器
9 D6 T) E' k6 N! ~# j4 G4 l, m 在对session进行持久化操作时,比如钝化
7 ?3 S' t# K; a/ C1 I( v; b$ V2 K 、激活,会使用序列化协议)。
, x3 P5 h7 `/ A( ^ Object session.getAttribute(String name);, p2 }. q$ u3 k. A* V- q5 e3 T
//如果name对应的值不存在,返回null。
& | f& V% e6 ?3 f7 M session.removeAttribute(String name);: M0 [# X5 ~4 G# O! f z
d,session超时$ K( ?0 E& @3 [2 c
服务器会将超过指定时间的session对象$ } v/ p$ i4 {" [" B0 t/ V. x2 V$ o
删除(在指定的时间内,该session对象没有
; ~+ N, o8 f- H6 L 使用)。, J& b) E, M! @' q# G
方式一:
, P" a; W. e- z+ u T5 d session.setMaxInactiveInterval(& E4 [9 x! E. N4 s/ o0 U
int seconds);
5 | v. V9 \: e* d J 方式二:% X; s. [4 h- _8 U) ~% o
服务器有一个缺省的超时限制,可以
* K0 o4 H0 W5 H4 z 通过相应的配置文件来重新设置。* |. M7 X' ^7 o1 v
比如可以修改tomcat的web.xml(
]: y/ _( u ]: h1 P4 l tomcat_home/conf下面)。' |$ o H; J! G
<session-config>
- X8 c8 K7 P* [, X" Q <session-timeout>30</session-timeout>- L1 k6 g7 _8 O+ K! D- E; p- a
</session-config>
( Q8 j: d, N+ F& G! q1 Z# \ 另外,也可以只修改某个应用的web.xml。8 a" ^% I) N# P5 B; q2 i
e,删除session; u, ~: Z) A9 J/ b8 c+ P1 v
session.invalidate();
; C7 x* N# U+ u1 n) A$ B% S- h ) {% N( P0 n0 \' _8 i9 D
案例:
6 Q3 W) |5 D( l" O0 B$ A session验证5 ?: k4 z- ~7 P
step1 在登录成功之后,在session上绑订一些数据。- p* l0 U# U( k! m6 s
比如:7 P) n2 e' M( j }8 z
session.setAttribute("user",user);
# v+ E( } Y% {% W1 y$ m8 D. [ step2 在访问需要保护的页面或者资源时,执行& Q" C4 } o$ E1 d: q
Object obj = session.getAttribute("user");) ^# [ S) J$ T. L8 d0 S6 L
如果obj为null,说明没有登录,一般重定向到
v- N1 P4 d! D5 @. ] 登录页面。: ?( _6 b3 k/ ?% p' p- K% A# c4 C
. h" K& l: V3 B) O+ ?8 p |
|