版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
第九章使用会话追踪
2011年5月30日
本节课的内容:
⑥什么是客户会话
⑥会话的工作机制
⑥维护会话的几种方式
⑥跟踪客户会话
♦,使用H11pSession对象维护会话信息
⑥监视会话对象
2011年5月30日2
工、什么是会话
典型的在线商店的情况:
用户刚刚在一个页面中挑选到一种商品,添加到购物车
中,在下一个商品页面中又挑选到一种添加到购物车中。
注意到这两次选择是在不同的HTTP连接中发生的。而用
户希望两次挑选的商品在同一个购物车中一起交付,而不是
每选一件商品都要交付一次。这就需要一种机制来唯一的标
识用户,以便跟踪客户在站点中的行为。
会话:
这种在多次HTTP连接间维护用户与同一用户发出的不同
请求之间关联的情况称为维护一个会话(session)。
2011年5月30日3
2、会话的特征
合会话能够把用户与同一用户发出的不同请求之间关联
起来。不同用户的会话应当是相互独立的。
合会话一旦建立就应当一直存在,直到用户空闲时间超
过了某一个时间界限,容器才应当释放该会话资源。
⑥在会话的存活期间,用户可能给服务器发送了很多请
求,该用户的这些请求信息都可以存储在会话中。
2011年5月30日4
3、会话的工作机制
网上购物商店的购物车
商店当用户选择“YES”确认购买时,服务
的
、器会将会话对象中的商品信息保存到
购
用户输入个人信用信息登物数据库中,并联系网上银行和邮局向
录到网上商店用户发货。
用户浏览产品页,察看商品
介绍,并点产“力口人”珀就在服务器,该商品的相关信息
商品信息在一次HTI保存在用户的会话对象中
传递到服务器
f7<issword:
心h版川程序
q当用户离开网上商店前,被
询问是否购买。
2011年5月30日5
⑥在上述的网上商店中,用户的会话信息保存在服务器端,用
户与服务器之间必须提供一种机制,标识某一用户与他在服务
器端用户状态之间的对应关系。这种机制必须保证:
■允许用户在不同页面(如:S㊀工vl㊀t)间浏览而不会丢失
“购物车”
-必须避免不同用户的“购物车”混淆。用户不会允许自
己为别的用户付款。
今不幸的是通常情况下W㊀b服务器不会自动跟踪用户操作轨迹。
捕获并存储用户轨迹是W㊀b应用开发人员的工作。
2011年5月30日6
4、维护会话的方式…・URL重写
>客户第一次访问网站时,将会话信息添加到由服务器发出
的每一个响应的URL中。
爹当用户再次访问网站时,URL中会把这个会话信息作为用
户请求参数返回服务器端,服务器根据返回的会话信息来标
识该客户,维护整个会话的信息持续性。
卷常见的URL重写格式
为了保持URL的简洁,通常这个嵌在URL中的会话信息
是一个由服务器器成的代表客户的唯一性的工D号,在URL的
表现形式上,它通常是作为URL查询参数的形式出现的,如:
http://.../ch09/huihua.jsp?sessionid=678
2011年5月30日7
#Session.jsp
#Tom.jsp
#■Jerry.jsp
2011年5月30日8
今URL重写技术的优点:
■用户是匿名的;
-在Web服务器实现上得到普遍的支持;
卷URL重写技术的缺点:
■由于会话信息作为查询参数在URL上是可见的,因
此会话存在一定的安全隐患;
■需要对所有动态生成的URL进行重写,代码比较繁
琐;
■只能用于动态产生的文档如Servlet和JSP页面,而
不能用于HTML文档;
■重写的URL不能长期有效
2011年5月30日9
5、隐藏窗体技术
⑥隐藏窗体技术原理
HTML表单允许把一些字段信息隐藏起来,而在浏览器上不
被显示出来。例如:
<INPUTTYPE="H1DDEN"Name's㊀ssion"Value
⑥使用隐藏窗体技术实现会话管理
这种方式的工作机制为:在用户第一次请求时,服务器在
为客户准备的页面上添加一个或多个隐藏表单,把一些要隐藏的
信息如标识该客户的工D号存储在那里。当客户提交该表单时,
这些信息会作为查询参数返回服务器,服务器可以利坦、
HttpS㊀rvl㊀tR㊀qu㊀st对象的g㊀'tParam㊀t㊀r()方法读取出来c
这样就达到了在服务器端维护会话信息持续的作用。
2011年5月30日10
⑥可以这样认为,同重写URL技术相比,
隐藏窗体技术在表单参数中传递会话信息,
而重写URL技术是在GET参数中传递会话
信息。除了这点,二者并无根本区别。
2011年5月30日11
卷上面我们分别说明了如何使用URL重写、cooki㊀和
隐藏表单这三种方式来跟踪用户会话。不管采用何种方
式,都应实现以下步骤:
1、服务器必须为每个会话产生一个唯一的工D号
2、在服务器和客户浏览器之间传递这个工D号以维持会
话
3、服务器端根据工D号维护相关客户的会话信息
2011年5月30日12
6、使用内建的Session对象
#'Servlet2.3规范定义了^^HttpSession^
口,允许S㊀rvl㊀t容器针对每一个用户建立一个
HTTP会话(即HttpS㊀ssion对象),每个HTTP会
话将会自动派减予一个唯一的会话编号(session
ID),而无需程序员编程实现。
*HttpS㊀ssion对象提供了和S㊀rvl㊀tCont㊀xt对
象相似的一组会话属性的方法,这样就可以很容易
地在服务器端存放用户会话状态。
2011年5月30日13
2011年5月30日14
会话与请求的关系
会话和请求之间的关系
会话维护的就是同一用户的一组请求序列之间的关联性。
mJI.、士-4^-fr-t人、-r.>口•、,AlY在一定A的J关系。换言之,
这些请求属于一个会话,因为它们是同一个用户发茬金港号哈
往同一个服务器应用程序(HeUoworld)的,即使冷浦沙/:义叱白田
它们是发往不同的Servlet的。当用户在Helloworld9判断该请求所属的
下不同的Servlet间浏览时,服务器可以用会话对象,
跟踪与用户有关的状态。r
http://www.MyW/HelloworLServlet
Id/Servlet2
这些请求属于另一个会话,代表不同的用户。
hI/Servlet3
这时请求可以与上面的请求同时发生而不会被
Servlet混淆。Servlet
/HeUoworld
Web应用
http://www.MyW/Helloworld7Servlet2'
http://www.MyW/Helloworld/Servlet3
http://www.MyW/HelloworlA/Servletl
http://www.MyW/HelloworldAServlet4
2011年5月30日客户端215
会话与请求的关系
获取与请求关联的会话对象
Ht■tpS㊀rvl㊀■tR㊀qu㊀st对象提供了g㊀tS㊀ssion方法,
通过这个方法,S㊀rvl㊀t就可以获得与当前请泰关联的会话对象的
引用。该方法为重载的方法,有两个版本:
■publicHttpSessiongetSession();
案故与当朝德求相去联的含话,如果当前请求还没有一个相关联
的会话,就创建一个并返回。
■publicHttpSessiongetSession(boolbCreate);
扳回与当前请求相关联的会t面寸象。如果没有,且参数cr㊀at㊀的
值为tru㊀,贝。创建异地向一个新的会话。如果cr㊀at㊀的值为
false,且请求没有相关联的会话对象,将返回null。
可以利用这点判断用户最直为第一次迈问朝点二如果一、、、
g㊀tS㊀ssion(false)返回null,则表不用尸是第一次访问站点,
如果返回非null则表示用户不是第一次访问站点。
2011年5月30日16
会话与请求的关系
获取与请求关联的会话对彳总是返回一个会话。但是我们不知道该会
、-r*DiVLr-kt,JL/_、--LD-1—
获得会话ID并保存到字符串中。该串将类似于:
.32FE24119D28C30866C9EF4BEA40EF4E
判断会话是新建的还是旧的。
if(s.isNew()){
out.printin("<p>新的会话工D="+sid+”</p>");
}
else{
out.printin("<p>欢迎回
来,<br>User:”+sid+”</p>");
}
2011年5月30日17
会话与请求的关系
会话工D
•s㊀rvl㊀t容器在创建每一个新的HTTP会话对象时,都会赋予一
个新的工D号。
⑥s㊀工vl㊀t容器保证它在W㊀b应用范围内是唯一的。
⑥会话工D是实际包含在Http请求/响应报文中的会话数据。
♦这个工D号可以通过HttpS㊀ssion对象的g㊀t工d()获得。例如:
HttpS㊀ssicms㊀ssion=raqu㊀st.g㊀tS㊀ssion();
Strings㊀ssion工d=s㊀ssion.g㊀t工d();
2011年5月30日18
会话与请求的关系
HttpS㊀ssion工作原理
1.当用户第一次发出请求时,S㊀工vl㊀t容器会建立一个HttpSassion
对象,并自动分配一■个W㊀b应用范围内唯一的Sassion工D与之对应。
这个Session工D也会随着HTTP响应内容传递给用户端浏览器。传递
的方式默认情况下为cooki㊀,如果用户端浏览器关闭了cookie功能,
就会使用URL重写技术传递给用户浏览器。
2.在用户发出的后续请求中,请求信息中会包含S㊀工v㊀It容器传递给它
的SessionIDoS㊀rvl㊀t容器就会根据传回的S㊀ssion工D将原来
建立的HttpS㊀ssion对象将请求与HttpS㊀工vl㊀tR㊀qu㊀st对象关联
起来。所以,对于同一个用户,调用g㊀tS㊀ssion()方法返[1]的将是
同一个HttpS㊀ssion对象。
2011年5月30日19
HttpSession对象的属性
与ServletContexI^^象类似,我们可以给HttpSession
对象绑定属性。
■S㊀工vl㊀tCont㊀xt对象的属性的作用域是W㊀b应用程序,
在这个应用程序下的所有S㊀zl㊀t都共享这些属性;
-绑定到HttpSessicm对象上的属性只在一次会话周期内有
效,且只有在属于该会话的HttpR㊀quest对象中才可以访
问这些属性。换句话说,会话属件就是特定用户的专用数据,
同时访问W㊀b应用的其他用户无法访问这些属性。
2011年5月30日20
HttpSession接口方法一访问属性
HttpSession接口使用以下方法管理绑定到会话的属
性
voids㊀tAttribut㊀(Stringnam㊀,Obj㊀ctvalue)
Objectg㊀tAttribut㊀(Stringnam㊀)
void工㊀mov㊀Att工ibute(Stringnam㊀)
«除伽的蹄颉叫楸槌u附麒的噬掘频碘豳鼬蒯辎周一
的堪聊雎制朝哪»例僦葡皴崎侬蹴蜘说ne雇的可姒肥邰播
阖楂时族弼曲对袈蜃豳对魔殿甜象将由vlaue指定的对象置换掉。
HttpSessionsession=request.getSession(true);
幽镇§幽)n(true);
Nttp^^km1s€S8senHrgqti^tti^tfte^hxii0iiMt)^);
session.setAttribute(naccountn,acct);
2011年5月38^sion.setAttribute(naccount6t,newInteger(lOO));21
HttpSession接口方法一访问属性
用false参数获取现有会话对象。若没有,则创建一
个新的会话,并将visitCount对象绑定到该会话名
publicvoiddoGet(HttpServletRe为“visitCount”的属性。
HttpServletResponseresponse)注意绑定到会话属性的对象类型只能为Object类型。
即可以是null、int、double、boolean以外的类型。
注意在本例中newInteger(visitCount))的用法
intvLsitCount;
HttpSessionsession=request.getSession(false);
if(session==null){若存在会话,则从该会话提取名为“visitCount”
vLsitCount=l;的绑定对象。更新其值后,重新绑定到会话。
session=request.getSessi
session.setAttribute("y,new
Integer(visitCount));
}else{
visitCount=((Integer)session.getAttribute("visitCount")).intVal
ue();
visitCount++;
session.setAttribute(HvisitCount",new
22
HttpSession接口方法一终止会话
如果要终止某个HTTP会话,可以使用下面的几种方式
publicvoidinvalidat㊀()方法
publicvoids㊀tMax工nactiv㊀工nt㊀rval(intinterval)
方法
在web.xm1中配置会话的生存时间
般嗣逮因嗨徽也飒谢帅像㈱翔教I加峨璇的逾神饰6绑姥国性,
寮金函蒯n-gfl咖gakStaiSExesfitiiHt鼎1翁ut例期;素指定,单位为分钟:
HttpSessionse^sion=request.getSession(true);
^猷恻0n(true);
T<sessiaii-tim£ouf>yO</session-timeouf>
sessionanvanaafeQ;
碣湍瓢跪缆躁金比,沿本Web应用程序的间隔超过了10分钟,容器
初倒.赖含嫡鬼碰氤出劭底懒嫩赧1EI置的晒第璇坤食麻游
2011年5月3曲篦携提责问阀陶超迤的弱会解§将肺擞会时之中。23
对于网上商店这样的应用,可能希望对“商店”中当前
的客人总数进行监控。根据前面所学内容,我们知道应该利用会话
来实现该功能。
在本节中,我们将学习利用HttpS㊀ssionList㊀n㊀r侦
听器,轻松实现一个计数器,以跟踪并向用户显示本网站的在线人
数。
监视会话对象
2011年5月30日24
镣施陵惭对象
4加稻
会话侦听器是用来监听会话事件的监听器类。同其他Web侦听
监器类似,会话侦听器由用户编写并注册到web应用中。当容器检测
视到某个会话有事件发生时,容器将激活监听器对象并激发对应的事
件方法。
会主要有两类会话侦听器:
话
对⑥会话生命周期侦听器
象同S㊀rv㊀tCont㊀xtList㊀n㊀r类似,这类侦听器主要负责会话生
命周期事件的监听,如会话的生成、结束、激活等。在S㊀rv工㊀t规
范中,可以通过实现接口HttpSessionListener和
HttpSessionActivationListener来实现侦听。
参会话属性侦听器、…
同S㊀rv㊀tCont㊀xtAt•tribut㊀List㊀n㊀r类似,这类侦听器负责
处理绑定到会话的属性的更改事件,如绑定、删除、修改等。这类
侦听器应实现HttpSessionAttributeListener或
HttpSessionBindingListener接口。
2011年5月30日25
、会话生命周期事件
4加稻
会话的生命周期是由S㊀rvl㊀t容器管理的。在会话生
监
年周容官合有今于当去器方现某个杳话的次态发生变温时(如生成、鼠
视我们需要做的是实现监弓化、激活、销毁),容器会将一个SessionEvent对象
会作为参数调用注册的监听器。
话
HttpSessionEvent
对生成会话HttpSessionListener
象
可以添加:替换、
删除型话精华HttpSessionActivationEvent
钝化会话)-----------------------------1HttpSessionActivationListener
HttpSessionActivationEvent
激活会话HttpSessionActvationListener
可以添力、替换、
.除"话属)
HttpSessionEvent
r销毁会话)
HttpSessionListener
2011年5月一、---------->
HttpSessionListener侦听器
4
OS
监
视对于本节要完成的任务,我们利用会话的生命周期事件来实现当前
会在线人数的统计工作。
话当一个用户登录网站时,容器将创建一个会话,这时可以将在线人
对数计数器加1;当田口超时、洋铛时一裒瞿"为;玄仝在牛的一在线
当容器生成一个新会话时会通知HttpSessionListener侦听器
象人数计数器减
调用本方法。容器向该方法传递的参数是HttpSessionEvent
当容器创建或
对当某个会话超时或者调用了invalidate。方法都会引起会话的
侦听器。Httj侦销毁。在会话销毁之前,容器会通知HttpSessionListener
在这两个方法pi侦听器并调用本方法。
同样,容器向该方法传递的参数是HttpSessionEvent对象,
侦听器可通过其getSessionO方法引用发生事件的会话对象。
publicvoids㊀㊀ssionEsee!
publicvoids㊀ssicmD㊀stroy㊀d(HttpS㊀ssimt
sc㊀)
2011年5月30日
HttpSessionListener侦听器
4
OS
监
视注意事项:
会
话1.当实现HttpSessionListener侦听器时,必须同附
对s㊀ssionCr㊀at㊀、s㊀ssionD㊀st工oy㊀d的实现。当仅仅需要
象侦听一个事件时,另一个事件方法可用空方法体,但必须实现;
2.通过从参数得到的HttpS㊀ssionEv㊀nt引用,在
s㊀ssionCr㊀at㊀方法和s㊀ssionD㊀stroy㊀d方法内可以获得
发生事件的会话的引用。除此之外,HttpSessionEvent
参数并不提供其他信息;
3.与S㊀rvl㊀tCont㊀xtList㊀n㊀r类似,这两个方法可能会遇到
多线程同步问题。
2011年5月30日28
publicclassOnlineCounterListenerimplementsServletContextListener,HttpSessionListener{
publicvoidcontext工nitialized(S㊀rvl㊀tCont㊀xtEv㊀ntsee)
(
S㊀工vl㊀tContext
cont㊀xt=sc㊀.g㊀tS㊀rvl㊀tConTaxT;
工nt㊀garcountc当容器每次进入一个新的会话时,从该会话检索出所
context.s㊀tAt'属的Web应用上下文,然后将其"counter”属性的值
}加1。注意"counter”属性是一个整型的、在整个Web
入】.44nd应用运行期间维护的量。
publicvoidcontextDestroi一、=-一一一一一一一一
S㊀rvl㊀tCont㊀xt
conLexL=t>ce.geLServle);
context.r㊀mev㊀㊀r”);
当容器每次删除一个会话时,说明有用户正在离开当
publicvoidsessionCreatec前Web应用。从会话检索出所属Web应用上下文,然
HttpSassions㊀ssion=s(后将其“counter”属性的值减1,重新存入Web应用上
下文。
S㊀rvl㊀tCont㊀xtcont㊀x-▼▼V<J/.LA/|J~|~/、p'11J,\JA411J''JJL_t
工nt㊀gar9S^rvletContext属性,这样就能保证计数器
counter=(Integer)context.对象能够让所有的用户访问。
count㊀r=n㊀wInteger(count㊀工.cntValu㊀()+1);
cont㊀xt.s㊀tAtt工ibut㊀("count㊀r”,counter);
publicvoidsessionDestroyed(HttpS㊀ssionEv㊀ntse){
HttpSassions㊀ssion=s㊀.g㊀tS㊀ssion();
S㊀工vl㊀tCont㊀xtcont㊀xt=sassion.g㊀tS㊀工vl㊀tCont㊀xt();
count㊀工=(工nt㊀ger)cont㊀xt.g㊀tAttribute("counter");
HttpSessionListener侦听器
4om箱
°本例中的几个问题说明:
监i.四个方法的作用必须分清楚:、
contextInitial!zed负责在Web上下文中建立"counter”属性并设置初值;
视sessionCreated负责在新会话出现时将“counter”属性值增、加
sessionDestroyed负责在会话结束时将"counter”属性值减少
会contextDestroyed负责在Web应用结束前释放上下文属性所苫资源。
话
2.编写好事件侦听器后,还要注册到Web.xml中才会生效。其中:
对〈session-config〉
<session-timeout>l</session-timeout>---
象会话失效时间长度
</session-config>
<listener><listener-class>
com.mycompany.servlet.OnlineCounterListener事件类的
全名
〈/listener-class〉</listener>
3.在Web应用中的某个Servlet中,可以随时查询计数
context=this.getServletContext();
request.getSession(true);//若还未进入会i舌贝(J仓U建—1^。
out.printin("<p>Online:n+context.getAttribute("counter")+
n</p>");
out.printin(</body></html>n);
2011年5月赳用《9$就$1。1111注01^「只能监听整个对象的生命周期,无法监听会话属理M添加、
朋||K仝书才?4^万1.U勺不用1支止匕d三自.才市由Hh■HnGaQQ-icn△十上rTHiihaT.iQhanar
二会话属性侦听器
4加稻
当容器发现向某个会话的属性发生变化时,将向
、、.nrtBv1r-nJ」.▼一.*.«
监
问侦听费是满足以下条件的Java类:合对属性的
视
添•实现HttpSessionAttributeListener或HttpSessionBindingListener接口
会,注册到了Web.XML卜的<listener><listener-class>节中
在侦听器中的事件方法
话取发生事件的会话和属事件发生时,一个HttpSessionBindingEvent对
一般情况下,我们通过象作为消息参数发送到侦听器。侦听器可以:
对
器而不是HttpSessionBii通过该参数获得会话、属性名等信息。
象生成或被治;:巾
HttpSessionBindingEvent
添加属性
HttpSessionBindingEvent
替换属性)------------------------------■HttpSessionAttributeListener
一.“=>…\HttpSessionBindingEvent
删除属性1________________________I
2011年5月30E钝化或隼毁会话
HttpSessionAttributeListener侦听器
领
监
HttpSessionAttributeListener4fe口共定义了三个方法:
普
话■publicvoid
attributeAdded(HttpSessionBindingEventse)
对
当使用HttpSession对象的setAttribute()方法添力口——
象个新的会话属性时,容器会调用侦听器的这个方法。
■publicvoid
attributeRemoved(HttpSessionBindingEventse)
当通过HttpS㊀ssion对象的removeAttribute()方法删
除一个会话属性时,容器会调用侦听器的这个方法。
■publicvoid
2011年5月30日attributeReplaced(HttpSessionBindingEventse)
HnTTIIC11*4^:不___■1____/%F丰*.
HttpSessionAttributeListener侦听器
4
OS
监
视HttpSessionBindingEvent^象
会
话
对当会话属性发生变更时,通知_
象HttpS㊀ssionAttribut㊀List㊀n㊀工侦听器的事件为
HttpS㊀ssionBindingEv㊀nt对象。
HttpS㊀ssionBindingEv㊀nt类继承自HttpS㊀ssionEv㊀nt类,
除了继承的g㊀tS㊀ssion()方法,
HttpS㊀ssionBindingEv㊀nt类还定义了两个方法:
■StringgetName()
返回绑定到会话对象或解除绑定的属性的名称。
■ObjectgetValue()
返回添加、替换或要删除的会话属性。
2011年5月30日33
publicclassSessionAttributeHandlerimplementsHttpSessionAttributeListener{
publicvoidattributeAdded(HttpSessionBinclingEventse){
HttpSessionsession=se.getSession();
ServletContextcontext=session.getServletContext();
context.log("Anattributenamed"+se.getName()+“!!
+s㊀.g㊀tValu㊀()+“add㊀d");
}
当向会话中绑定新属性时,容器调用该方法。参数se
publicvoidattributeRemoved(1说明了发生事件的会话对象以及新添加的属性。
HttpSessionsession=se.g(在本例中,我们从se获取会话,然后获取Web上下文
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 家长安全培训会新闻课件
- 2026年法律咨询服务保证书合同
- 2026年模特形象授权合同
- 2026年大件运输分包合同
- 2026年体育馆比赛区域空调服务合同协议
- 2026年远程教育工作者合同
- 2026年汽车传感器维修配件合同
- 2026年汽车租赁公司合作合同协议
- 2026年品牌推广代理合同
- 2026年广告物料运输合同协议
- 国家开放大学电大本科《流通概论》复习题库
- 2025-2026学年统编版二年级语文上册期末质量检测卷(含答案)
- 2025年学法减分试题及答案
- 2025年德州乐陵市市属国有企业公开招聘工作人员(6人)参考笔试题库及答案解析
- 邢台课件教学课件
- 医防融合视角下家庭医生签约慢病管理策略
- 2025年新能源市场开发年度总结与战略展望
- 中职历史期末考试及答案
- 从指南看慢性乙型病毒性肝炎的防治策略
- 江苏省扬州市江都区2025-2026学年八年级第一学期第二次月考语文答案
- 2026年辽宁装备制造职业技术学院单招职业技能测试题库带答案详解
评论
0/150
提交评论