该用户从未签到
|
状态管理
+ v* a: m! R! r# ^5 A% r 1)什么是状态管理+ L0 }9 l4 w; L2 I- ?+ P( V! z
将客户端(一般是浏览器)与服务器之间的多次
% b$ `6 _ A1 x, ? 交互当作一个整体来看待,即将多次操作所涉及的
% C5 v( Y* k3 h! G2 S 数据记录下来。3 x e7 k% f/ i- |
2)怎样进行状态管理
; x% v d5 q+ k( n* | 第一种方式,在客户端管理用户的状态
6 k4 j1 {; I8 N) k6 r (cookie)。
% w( H: Q% j. h+ d5 _ 第二种方式,在服务器端管理用户的状态1 x) J- c% C( B0 h/ X
(session)。9 e' i* {. H% F. q1 J4 b6 e
3)cookie
% _5 a& F! ]6 v: w% Z a,什么是cookie?
) w" B2 @1 n3 }% e 浏览器在访问服务器时,服务器将一些数据. P. k# B6 v8 s9 h
以set-cookie消息头的形式发送给浏览器。浏览3 p& E( R; p$ O2 y' t3 h
器会将这些数据保存起来。当浏览器再次访问
9 \3 _: F2 e2 y6 o& k 服务器时,会将这些数据以cookie消息头的形式
5 y2 c- J5 @, V# _ c$ J" A3 I$ |5 b 发送给服务器。通过这种方式,可以管理用户的
3 R& ?; ~. {% a% [ 状态。
; {; W! d% g, e' L; ^7 m b,怎样创建cookie?' _; P% P, X1 {, u8 o
Cookie cookie = new Cookie(String name,, O" J/ l) }, R" X3 Q7 v
String value);
" _/ s- u. e) S/ N* j response.addCookie(cookie);1 o8 G+ s) F3 r
c,查询cookie
% h& a9 } ]7 D' y //如果没有cookie,则返回null。
& l: \9 t D) l. k- ] Cookie[] cookies = request.getCookies();
' K8 h; Z& N" Z8 ^( ]; b& I String name = cookie.getName();: N, D# @4 {# k6 K, d8 i5 w" ]
String value = cookie.getValue();% k1 ^. Z" n( ^ X! u' V
d,cookie保存时的编码问题3 I. g7 i6 L( W' n* R8 M1 y
cookie的值只能是ascii字符,如果是中文,
! ]& c" B% H7 s+ b 需要将中文转换成ascii字符形式。
! y* c s) ?. v# z- j; p4 C- ] 可以使用URLEncoder.encode()方法和 E, Q! N9 [- Y5 w+ w9 w, p% Z- u6 N* e
URLDecoder.decode()方法来进行这种转换。
9 T9 |( X0 }& j( ~! } e,cookie的保存时间
& h# V# \* B+ U1 H6 [$ j$ A cookie.setMaxAge(int seconds);& v3 F7 D' i! \6 S H% r! B* l# p7 x
seconds > 0:浏览器会将cookie以文件的方式6 p! M5 B- W! ~: I1 d/ J
保存在硬盘上。在超过指定的时间以后,会删除3 p, k/ S4 J# L9 s
该文件。) |8 p: p6 _- a- |
seconds < 0:默认值,浏览器会将cookie保存2 C( f( h' B& K/ v% H- p# u* u
在内存里面。只有当浏览器关闭之后,才会删除。2 h2 `8 z- i7 ?% G0 r: M
seconds = 0:删除。8 l" _! q8 c) w* P
f,删除cookie
; E3 N( H5 D8 \( c2 a& q 比如要删除一个name为"username"的cookie。
0 X/ i. T2 B% e. q Cookie c = new Cookie("username","");0 n, g4 A1 ^$ B7 Q- p, b% l
c.setMaxAge(0);) H# W9 n5 j$ ^: T9 d
response.addCookie(c);. e2 c/ _! Q: T; R
g,cookie的路径问题% O% @+ [7 d9 T% G1 ]
浏览器在向服务器上的某个地址发送请求时,
B, e1 g' {) j" A( s7 \' R8 S 会先比较cookie的路径与向访问的路径(地址)是& r( O: h8 l8 W ~1 k! F+ v! }) _
否匹配。只有匹配的cookie,才会发送。6 y; Q: V+ w; d3 U- k
cookie的路径可以通过' R5 j. g9 N4 @
cookie.setPath(String path)方法来设置。8 ]* G! h, G1 ~+ R4 O) t& U
如果没有设置,则有一个缺省的路径,缺省的
; C; T/ p0 s) {7 c% M8 v: F 路径是生成该cookie的组件的路径。
5 j# ^" V d" Y, o6 G, y* K0 q 比如: /appname/addCookie保存了一个cookie,5 Z: h' [$ b1 _7 h) F- [7 z S
则该cookie的路径就是/appname/addCookie。! o. y* {8 u3 y: O
5 ~' W+ c% U5 }+ b& y 规则:
2 m6 _! x+ B. I+ A6 ~ E cookie的路径必须是要访问的路径的上层目录
- D& J! G' L3 I& S 或者是与要访问的路径相等,浏览器才会
0 k9 V! a) F" `& E2 B 将cookie发送给服务器。8 [2 F* B3 h3 U( Z8 |+ S6 v. N
$ s3 H% j8 {& s$ E& j& A 一般可以设置setPath("/appname"),表示访问
% N; @2 z0 ~$ \2 D. \/ y 该应用下的所有地址,均会发送cookie。, j' S5 G4 w# r' U) P5 P x
h,cookie的限制
( K5 J% K6 x* r cookie可以禁止( C1 A# J) ?3 Q. w' `2 K# t
cookie的大小有限制(4k左右)
$ S% b- m$ \4 j cookie的数量也有限制(浏览器大约能保存300个) ; K# z! m" U( k6 h
cookie的值只能是字符串,要考虑编码问题。, V( q6 H- A7 D2 Q
cookie不安全5 R6 A0 w' u. G. {4 c
练习:) {: H; w$ b# H# G5 H
写一个Add_FindCookieServlet,该servlet先查询- ~# K( ?* @) s9 J; D' t( z; u- F5 o
有没有一个名叫name的cookie,如果有,则显示8 l# U$ q0 ~) H8 w X; j6 m
该cookie的值,如果没有,则创建该cookie(
; u- a# ]! y" b cookie的名字:name,cookie的值:zs)。
: I8 o, W) E2 b* q' ~9 Z w9 ]# a" s4 f& q
) z; a& T2 ?6 b5 q/ T _ 4)session , O& q/ v1 i5 P
a,什么是session?
# m6 E. i) z7 p) @* v { 浏览器访问服务器时,服务器会创建一个session
3 E( Z( j( u4 y @! ^( K 对象(该对象有一个唯一的id, 一般称为sessionId)( g% `2 c: H8 { }6 V8 \
。服务器在缺省情况下,会将sessionId以cookie
" g9 u. A0 T* [& M, v0 {% } 机制发送给浏览器。当浏览器再次访问服务器时,; t! S. P7 w' J$ d6 E
会将sessionId发送给服务器。服务器依据sessionId
5 S f2 I: Q/ g( p# ? Y0 X# e5 M 就可以找到对应的session对象。通过这种方式,- e- Q7 i& R/ P& f$ X" s, ~
就可以管理用户的状态。7 _0 Q b# V/ d8 e; E. [
b,如何获得session对象
- e9 `! {$ ?8 e! l4 E 方式一:
8 W+ O0 |* {: v HttpSession session = ! Z" j' M$ M3 ?. N' t1 v" C
request.getSession(boolean flag);8 }/ Q& i; C+ q% F1 B
当flag = true:) e+ ]! K8 t; {: Z; g
服务器会先查看请求中是否包含sessionId,
' Q4 }' ?' A9 V 如果没有,则创建一个session对象。8 ~& b6 h0 U/ a" l) Q; v( D
如果有,则依据sessionId去查找对应的
$ G' q6 |9 w- t0 ^+ O session对象,如果找到,则返回。
& k9 o; R. e" y I: B8 m 如果找不到,则创建一个新的session对象。, y. j6 N) P4 k6 Z, o" F
当flag = false:
6 ?" O Q5 s- {8 D2 N 服务器会先查看请求中是否包含sessionId,( z* A- T9 o j3 D' ~7 ]3 q
如果没有,返回null。
4 d4 ]/ R& R3 S# g# w* V0 e 如果有,则依据sessionId去查找对应的
' s' I4 I$ p+ B- `$ S9 I! ~ session对象,如果找到,则返回。
5 f# q9 ~/ V$ C; K+ i7 I 如果找不到,返回null。, J7 N3 c8 ~; m/ I8 ^
方式二:
V% o7 E- D9 A4 W' I) R2 S HttpSession session = % f/ H1 c1 F) Q: `3 O1 Z- r
request.getSession();
! _. E# T& P0 H) _ 与request.getSession(true)等价。9 b9 K& G7 h3 K2 D1 @" c
c,HttpSession接口提供的一些方法
* t' O' K& r% N. x //获得sessionId。: d k3 v2 q, V* m
String session.getId();9 {$ M# e4 d- F6 G' K8 b3 B; R
//绑订数据% P8 u! E$ W- n1 H
session.setAttribute(
1 Q+ L3 V3 [/ f6 A8 ~5 s) ] String name,Object obj);
8 i Q) S! d$ N' v //obj最好实现Serializable接口(服务器; r' C* S- H0 I0 V1 E5 M
在对session进行持久化操作时,比如钝化# ^2 d) Y* `2 Q# @1 Y$ k6 W
、激活,会使用序列化协议)。
7 b8 z3 Z" Z H& r" V, H Object session.getAttribute(String name);" y" ?, t9 `) c# g6 E
//如果name对应的值不存在,返回null。1 _$ F, _; ?5 ]2 F
session.removeAttribute(String name);
8 q# r8 t) y% A8 I" R9 Z; W1 d( E d,session超时 U% V: f9 P! ?* B: t6 C/ `: u
服务器会将超过指定时间的session对象6 \$ y: x" x. ?4 N
删除(在指定的时间内,该session对象没有! s. W, Y/ k' e& o
使用)。5 m( E2 l6 q) d; W/ J" g
方式一:
) x, @' l) Y0 o/ [! L/ o session.setMaxInactiveInterval(
! O+ y+ A: R: f0 x int seconds);
1 z1 Z% j4 V1 X0 g" n; Q 方式二:" `& g) ~% l7 k) R: ?2 t
服务器有一个缺省的超时限制,可以( O% A. C: U' h. g2 a) m3 P
通过相应的配置文件来重新设置。/ H m1 ~$ h" D# _
比如可以修改tomcat的web.xml(
+ H* j' f8 B8 j f' p1 O6 A t tomcat_home/conf下面)。- ?. c' e$ x- F
<session-config>5 m( Z! Q6 C3 m. C1 @
<session-timeout>30</session-timeout>
9 `& c: V* Y$ N+ u+ ?, ] </session-config>+ u d: L9 p4 h
另外,也可以只修改某个应用的web.xml。
( K$ d9 N* c/ x Q2 o: E. q e,删除session
" O# P' }+ I0 R2 P, U- m; i3 L session.invalidate();
4 A- h1 [$ J6 j, h- u+ r* n% L, B4 r + ]3 a9 x/ u+ |0 B' z6 w
案例:, C7 a3 B: }8 \. O
session验证
4 M7 p2 b8 J% S1 J4 } step1 在登录成功之后,在session上绑订一些数据。
: u$ O& T: ?8 i+ C4 Z0 D& T8 J G; s' H 比如:. L1 @& L3 G9 Z" {5 a
session.setAttribute("user",user);
: e* c8 E% i. Q! |4 J3 n9 I step2 在访问需要保护的页面或者资源时,执行2 @3 }( u3 _' k) G
Object obj = session.getAttribute("user");! F( `3 b+ ]+ \/ o/ D( [$ ]7 F
如果obj为null,说明没有登录,一般重定向到5 V& m6 i& P; J% r0 ^5 a! y6 D
登录页面。, U+ e3 w, @, c
* p4 a3 l6 t5 ~1 O& S' M: B- h2 W: T8 L
|
|