|
马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有帐号?立即注册
x
对于一个大型项目,如果用java来作,可能需要9个月,并且可能需要翻阅10本以上的书,但如果用ruby来作,3个月,3本书就足够了,而.net也不过3,4本书足以,这就是区别。JSP作为后起之秀可以在服务器编程情况中占有必定位置,是和它优秀撑持一系列业界尺度亲切相干的。Session就是它供应的基本举措措施之一。作为一个程序员,你能够不介怀详细在客户端是怎样完成,就便利的完成复杂的基于session的用户办理。如今关于处置在线用户,有几种分歧的处置办法。
一种是页面革新由用户把持,服务器端把持一个超不时间好比30分钟,到了工夫以后用户没有举措就被踢出。这类办法的长处是,假如用户忘了加入,能够避免他人歹意操纵。弱点是,假如你在做一件很耗工夫的事变,凌驾了这个工夫限定,submit的时分大概要再次面对上岸。假如本来的叶面又是强迫生效的话,就有大概丧失你做的事情。在完成的角度来看,这是最复杂的,Server端默许完成的就是如许的形式。
另外一种体例是,站点接纳框架布局,有一个Frame大概埋没的iframe在不休革新,如许你永久不会被踢出,可是服务器端为了判别你是不是在线,必要定一个发愣工夫,假如凌驾这个发愣工夫你除这个主动革新的页面外没有革新其他页面的话,就以为你已不在线了。接纳这类体例的典范是xici.net。他的长处是能够能够使用不休的革新完成一些相似server-push的功效,好比网友之间发送动静。
不论哪种形式,为了完成扫瞄以后一切的在线用户,还必要做一些分外的事情。servletAPI中没有失掉Session列表的API。
能够使用的是Listener.Servlet2.2和2.3标准在这里稍微有一些纷歧样。2.2中HttpSessionBindingListener能够完成当一个HTTPSession中的Attribute变更的时分关照你的类。而2.3中还引进了HttpSessionAttributeListener.鉴于我利用的情况是Visualageforjava4和JRunserver3.1,他们还不间接撑持Servlet2.3的编程,这里我用的是HttpSessionBindingListener.
必要做的事变包含做一个新的类来完成HttpSessionBindingListener接口。这个接口有两个办法:
publicvoidvalueBound(HttpSessionBindingEventevent)
publicvoidvalueUnbound(HttpSessionBindingEventevent)
当你实行Session.addAttribute(String,Object)的时分,假如你已把一个完成了HttpSessionBindingListener接口的类到场为Attribute,Session会关照你的类,挪用你的valueBound办法。相反,Session.removeAttribute办法对应的是valueUndound办法。
publicclassHttpSessionBindingimplementsjavax.servlet.http.HttpSessionBindingListener
{
ServletContextapplication=null;
publicHttpSessionBinding(ServletContextapplication)
{
super();
if(application==null)
thrownewIllegalArgumentException("Nullapplicationisnotaccept.");
this.application=application;
}
publicvoidvalueBound(javax.servlet.http.HttpSessionBindingEvente)
{
VectoractiveSessions=(Vector)application.getAttribute("activeSessions");
if(activeSessions==null)
{
activeSessions=newVector();
}
JDBCUsersessionUser=(JDBCUser)e.getSession().getAttribute("user");
if(sessionUser!=null)
{
activeSessions.add(e.getSession());
}
application.setAttribute("activeSessions",activeSessions);
}
publicvoidvalueUnbound(javax.servlet.http.HttpSessionBindingEvente)
{
JDBCUsersessionUser=(JDBCUser)e.getSession().getAttribute("user");
if(sessionUser==null)
{
VectoractiveSessions=(Vector)application.getAttribute("activeSessions");
if(activeSessions!=null)
{
activeSessions.remove(e.getSession().getId());
application.setAttribute("activeSessions",activeSessions);
}
}
}
}
假定个中的JDBCUser类是一个恣意User类。在实行用户登录时,把User类和HttpSessionBinding类都到场到Session中往。
如许,每次用户登录后,在application中的attribute"activeSessions"这个vector中城市增添一笔记录。每当session超时,valueUnbound被触发,在这个vector中删往将要被超时的session.
publicvoidlogin()
throwsACLException,SQLException,IOException
{
/*getJDBCUserClass*/
if(user!=null)
{
logout();
}
{
//ifsessiontimeout,oruserdidntlogin,savethetargeturltemporary.
JDBCUserFactoryuf=newJDBCUserFactory();
if((this.request.getParameter("userID")==null)||(this.request.getParameter("password")==null))
{
thrownewACLException("PleaseinputavaliduserNameandpassword.");
}
JDBCUseruser=(JDBCUser)uf.UserLogin(
this.request.getParameter("userID"),
this.request.getParameter("password"));
user.touchLoginTime();
this.session.setAttribute("user",user);
this.session.setAttribute("BindingNotify",newHttpSessionBinding(application));
}
}
Login的时分,把User和这个BindingNotofy目标的类都到场到session中往。logout的时分,就要自动在activeSessions这个vector中删往这个session.
publicvoidlogout()
throwsSQLException,ACLException
{
if(this.user==null&&this.session.getAttribute("user")==null)
{
return;
}
VectoractiveSessions=(Vector)this.application.getAttribute("activeSessions");
if(activeSessions!=null)
{
activeSessions.remove(this.session);
application.setAttribute("activeSessions",activeSessions);
}
java.util.Enumeratione=this.session.getAttributeNames();
while(e.hasMoreElements())
{
Strings=(String)e.nextElement();
this.session.removeAttribute(s);
}
this.user.touchLogoutTime();
this.user=null;
}
这两个函数位于一个HttpSessionManager类中.这个类援用了jsp内里的application全局对象。这个类的其他代码和本文有关且相称长,我就不贴出来了。
上面来看看jsp内里怎样用。
假定一个登任命的表单被提交到doLogin.jsp,表单中包括UserName和password域。节选部分片断:
<%
HttpSessionManagerhsm=newHttpSessionManager(application,request,response);
try
{
hsm.login();
}
catch(UserNotFoundExceptione)
{
response.sendRedirect("InsufficientPrivilege.jsp?detail=User%20does%20not%20exist.");
return;
}
catch(InvalidPasswordExceptione2)
{
response.sendRedirect("InsufficientPrivilege.jsp?detail=Invalid%20Password");
return;
}
catch(Exceptione3)
{
%>Error:<%=e3.toString()%><br>
Press<ahref="login.jsp">Here</a>torelogin.
<%return;
}
response.sendRedirect("index.jsp");
%>
再来看看如今我们怎样失掉一个以后在线的用户列表。
<bodybgcolor="#FFFFFF">
<tablecellspacing="0"cellpadding="0"width="100%">
<tr>
<tdstyle="width:24px">SessionId
</td>
<tdstyle="width:80px">User
</td>
<tdstyle="width:80px">LoginTime
</td>
<tdstyle="width:80px">LastaccessTime
</td>
</tr>
<%
VectoractiveSessions=(Vector)application.getAttribute("activeSessions");
if(activeSessions==null)
{
activeSessions=newVector();
application.setAttribute("activeSessions",activeSessions);
}
Iteratorit=activeSessions.iterator();
while(it.hasNext())
{
HttpSessionsess=(HttpSession)it.next();
JDBCUsersessionUser=(JDBCUser)sess.getAttribute("user");
StringuserId=(sessionUser!=null)?sessionUser.getUserID():"None";
%>
<tr>
<tdnowrap=><%=sess.getId()%></td>
<tdnowrap=><%=userId%></td>
<tdnowrap=>
<%=BeaconDate.getInstance(newjava.util.Date(sess.getCreationTime())).getDateTimeString()%></td>
<tdclass="<%=stl%>3"nowrap=>
<%=BeaconDate.getInstance(newjava.util.Date(sess.getLastAccessedTime())).getDateTimeString()%></td>
</tr>
<%
}
%>
</table>
</body>
以上的代码从application中掏出activeSessions,而且显现出详细的工夫。个中BeaconDate类假定为格局化工夫的类。
如许,我们失掉了一个观察在线用户的列表的框架。至于在线用户列表分页等功效,与本文有关,不予会商。
这是一个非革新模子的例子,依附于session的超机会制。我的同事sonymusic指出良多时分因为各个厂商头脑的分歧,这有多是不成信任的。思索到这类需求,必要在每一个叶面革新的时分都判别以后用户间隔前次利用的工夫是不是凌驾某一个预准时间值。这本色上就是本人完成session超时。假如必要完成革新模子,就必需利用这类每一个叶面举行革新判别的办法。
微软什么都提供了。你可以试想一下,如果你是新手,你是希望你点一下按钮程序就能运行那,还是想自己一点一点的组织结构,然后打包发部,调错再打包...... |
|