配置在web.xml里就自动挂在一起了啊.就像一个事件侦听一样啊.
解决方案 »
- jquery的问题
- jfreechart的chartpanel生成Image对象的问题
- 大家、
- java netbeans中创建桌面应用程序的问题
- 请教前辈一道JAVA的问题!
- 通过JdbcOdbcDriver操作informax、Sql Server、Oracle有什么区别吗?
- 为何JTable中有addColumn方法,而没有addRow方法?
- 那位知道java的小例子 请提供些好例子的下载的地方。
- 急,关于函数调用的问题
- 这个能实现吗
- setIcon后按鈕上的圖片沒變,請指教!
- 怎样在同一Frame里建立像网页那种可以左右拉动的多个Frame?有没有StatusBar类,怎样添加状态栏?
private 是不是应该设成 public?
/**这是管理user信息的类文件名为onLineUser.java欢迎访问javajia家(http://www.javajia.com),由yuking制作。2001.1.1
*/import javax.servlet.http.*;
import javax.servlet.*;
import java.util.*; public class onLineUser implements HttpSessionBindingListener {
public onLineUser(){
} private Vector users=new Vector();
public int getCount(){
users.trimToSize();
return users.capacity();
}
public boolean existUser(String userName){
users.trimToSize();
boolean existUser=false;
for (int i=0;i<users.capacity();i++ )
{
if (userName.equals((String)users.get(i)))
{
existUser=true;
break;
}
}
return existUser;
} public boolean deleteUser(String userName) {
users.trimToSize();
if(existUser(userName)){
int currUserIndex=-1;
for(int i=0;i<users.capacity();i++){
if(userName.equals((String)users.get(i))){
currUserIndex=i;
break;
}
}
if (currUserIndex!=-1){
users.remove(currUserIndex);
users.trimToSize();
return true;
}
}
return false;
} public Vector getOnLineUser()
{
return users;
}
public void valueBound(HttpSessionBindingEvent e) {
users.trimToSize();
if(!existUser(e.getName())){
users.add(e.getName());
System.out.print(e.getName()+"\t 登入到系统\t"+(new Date()));
System.out.println(" 在线用户数为:"+getCount());
}else
System.out.println(e.getName()+"已经存在");
} public void valueUnbound(HttpSessionBindingEvent e) {
users.trimToSize();
String userName=e.getName();
deleteUser(userName);
System.out.print(userName+"\t 退出系统\t"+(new Date()));
System.out.println(" 在线用户数为:"+getCount());
}
} /////////////////////////////////////////////////////////////////////////////
<%
/**这是显示在线用户的jsp文件文件名为onLineUser.jsp欢迎访问javajia家(http://www.javajia.com),由yuking制作。2001.1.1
*/
%>
<%@ page contentType="text/html;charset=gb2312" %>
<%@ page import="onLineUser,java.util.*" %>
<jsp:useBean id="onlineuser" class="onLineUser" scope="application"/>
<html>
<head>
<title>搞定JSP在线人数</title>
</head>
<body>
<center>
<p><h1>登陆成功,欢迎您访问Java家!</h1></p>
</center>
<% session = request.getSession(false); %>
<%
String username=request.getParameter("username");
if (onlineuser.existUser(username)){
out.println("用户<font color=red>"+username+"</font>已经登陆!");
}else{
session.setMaxInactiveInterval(50); //Sesion有效时长,以秒为单位
session.setAttribute(username,onlineuser);
out.println("欢迎新用户:<font color=red>"+username+"</font>登陆到系统!");
}
out.println("<br>当前在线用户人数:<font color=red>"+onlineuser.getCount()+"</font><br>");
Vector vt=onlineuser.getOnLineUser();
Enumeration e = vt.elements();
out.println("在线用户列表");
out.println("<table border=1>");
out.println("<tr><td>用户名</td></tr>");
while(e.hasMoreElements()){
out.println("<tr><td>");
out.println((String)e.nextElement()+"<br>");
out.println("</td></tr>");
}
out.println("</table>");
%>
<center>
<p>yuking制作</p>
<p> </p>
<%
out.println("<p><a href='logout.jsp?username="+username+"'>退出系统</a></p>");
%>
</center>
</body>
</html> ////////////////////////////////////////////////////////////////////////////////////
<%
/**这是用户退出的jsp文件文件名为logout.jsp欢迎访问javajia家(http://www.javajia.com),由yuking制作。2001.1.1
*/
%>
<%@ page contentType="text/html;charset=gb2312" %>
<%@ page import="onLineUser,java.util.*" %>
<jsp:useBean id="onlineuser" class="onLineUser" scope="application"/>
<html>
<head>
<title>搞定JSP在线人数</title>
</head>
<body>
<center>
<p><h1>登陆成功,欢迎您访问Java家!</h1></p>
</center>
<%
String username=request.getParameter("username");
if(onlineuser.deleteUser(username))
out.println(username+"已经退出系统!");
else
out.println(username+"没有登陆到系统!");
%>
<center>
<p>yuking制作</p>
<p> </p>
<p><a href="logout.jsp">退出系统</a></p>
</center>
</body>
</html>
分类:JSP/Servlet ( 版主:eguy, delphiasp )
来自:曹晓钢, 时间:2001-12-4 18:30:00, ID:763625 [显示:小字体 | 大字体]
JSP作为后起之秀能够在服务器编程环境中占据一定地位,是和它良好支持一系列业界标准
密切相关的。Session就是它提供的基础设施之一。作为一个程序员,你可以不介意具体在
客户端是如何实现,就方便的实现简单的基于session的用户管理。现在对于处理在线用户,有几种不同的处理方法。一种是叶面刷新由用户控制,服务器端控制一个超时时间比如30分钟,到了时间之后用户
没有动作就被踢出。这种方法的优点是,如果用户忘了退出,可以防止别人恶意操作。
缺点是,如果你在做一件很耗时间的事情,超过了这个时间限制,submit的时候可能要
再次面临登陆。如果原来的叶面又是强制失效的话,就有可能丢失你做的工作。在实现
的角度来看,这是最简单的,Server端默认实现的就是这样的模式。另一种方式是,站点采用框架结构,有一个Frame或者隐藏的iframe在不断刷新,这样你
永远不会被踢出,但是服务器端为了判断你是否在线,需要定一个发呆时间,如果超过
这个发呆时间你除了这个自动刷新的叶面外没有刷新其他叶面的话,就认为你已经不在
线了。采取这种方式的典型是xici.net。 他的优点是可以可以利用不断的刷新实现一些
类似server-push的功能,比如网友之间发送消息。不管哪一种模式,为了实现浏览当前所有的在线用户,还需要做一些额外的工作。
servlet API中没有得到Session列表的API。可以利用的是Listener. Servlet 2.2和2.3规范在这里略微有一些不一样。
2.2中HttpSessionBindingListener可以实现当一个HTTPSession中的Attribute变化的
时候通知你的类。而2.3中还引入了HttpSessionAttributeListener.鉴于我使用的环境
是Visual age for java 4和JRun server 3.1,他们还不直接支持Servlet 2.3的编程,
这里我用的是HttpSessionBindingListener.需要做的事情包括做一个新的类来实现HttpSessionBindingListener接口。这个接口有
两个方法:
public void valueBound(HttpSessionBindingEvent event),和
public void valueUnbound(HttpSessionBindingEvent event)。
当你执行Session.addAttribute(String,Object)的时候,如果你已经把一个实现了
HttpSessionBindingListener接口的类加入为Attribute,Session会通知你的类,调用
你的valueBound方法。相反,Session.removeAttribute方法对应的是valueUndound方法。[code]
public class HttpSessionBinding implements javax.servlet.http.HttpSessionBindingListener
{
ServletContext application = null; public HttpSessionBinding(ServletContext application)
{
super();
if (application ==null)
throw new IllegalArgumentException("Null application is not accept.");
this.application = application;
} public void valueBound(javax.servlet.http.HttpSessionBindingEvent e)
{
Vector activeSessions = (Vector) application.getAttribute("activeSessions");
if (activeSessions == null)
{
activeSessions = new Vector();
} JDBCUser sessionUser = (JDBCUser)e.getSession().getAttribute("user");
if (sessionUser != null)
{
activeSessions.add(e.getSession());
}
application.setAttribute("activeSessions",activeSessions);
} public void valueUnbound(javax.servlet.http.HttpSessionBindingEvent e)
{
JDBCUser sessionUser = (JDBCUser)e.getSession().getAttribute("user");
if (sessionUser == null)
{
Vector activeSessions = (Vector) application.getAttribute("activeSessions");
if (activeSessions != null)
{
activeSessions.remove(e.getSession().getId());
application.setAttribute("activeSessions",activeSessions);
}
}
}
}
[/code]假设其中的JDBCUser类是一个任意User类。
在执行用户登录时,把User类和HttpSessionBinding类都加入到Session中去。
这样,每次用户登录后,在application中的attribute "activeSessions"这个vector中
都会增加一条记录。
每当session超时,valueUnbound被触发,在这个vector中删去将要被超时的session.[code]
public void login()
throws ACLException,SQLException,IOException
{
/* get JDBC User Class */
if (user != null)
{
logout();
}
{
// if session time out, or user didn't login, save the target url temporary. JDBCUserFactory uf = new JDBCUserFactory(); if ( (this.request.getParameter("userID")==null)
|| (this.request.getParameter("password")==null) )
{
throw new ACLException("Please input a valid userName and password.");
}
JDBCUser user =
(JDBCUser) uf.UserLogin(
this.request.getParameter("userID"),
this.request.getParameter("password") );
user.touchLoginTime();
this.session.setAttribute("user",user);
this.session.setAttribute("BindingNotify",new HttpSessionBinding(application));
}
}[/code]
Login的时候,把User和这个BindingNotofy目的的类都加入到session中去。logout的时候,就要主动在activeSessions这个vector中删去这个session.
[code]
public void logout()
throws SQLException,ACLException
{
if (this.user == null
&& this.session.getAttribute("user")==null)
{
return;
} Vector activeSessions = (Vector) this.application.getAttribute("activeSessions");
if (activeSessions != null)
{
activeSessions.remove(this.session);
application.setAttribute("activeSessions",activeSessions);
} java.util.Enumeration e = this.session.getAttributeNames(); while (e.hasMoreElements())
{
String s = (String)e.nextElement();
this.session.removeAttribute(s);
}
this.user.touchLogoutTime();
this.user = null;
}
[/code]这两个函数位于一个HttpSessionManager类中.这个类引用了jsp里面的application全局
对象。
这个类的其他代码和本文无关且相当长,我就不贴出来了。下面来看看jsp里面怎么用。
假设一个登录用的表单被提交到doLogin.jsp, 表单中包含UserName和password域。节选部分片段:
[code]
<%
HttpSessionManager hsm = new HttpSessionManager(application,request,response);
try
{
hsm.login();
}
catch ( UserNotFoundException e)
{
response.sendRedirect("InsufficientPrivilege.jsp?detail=User%20does%20not%20exist.");
return;
}
catch ( InvalidPasswordException e2)
{
response.sendRedirect("InsufficientPrivilege.jsp?detail=Invalid%20Password");
return;
}
catch ( Exception e3)
{
%> Error:<%=e3.toString() %><br>
Press <a href="login.jsp">Here</a> to relogin.
<% return;
}
response.sendRedirect("index.jsp");
%>
[/code]再来看看现在我们怎么得到一个当前在线的用户列表。
[code]
<body bgcolor="#FFFFFF">
<table cellspacing="0" cellpadding="0" width="100%"> <tr >
<td style="width:24px">SessionId
</td>
<td style="width:80px" >User
</td>
<td style="width:80px" >Login Time
</td>
<td style="width:80px" >Last access Time
</td>
</tr>
<%
Vector activeSessions = (Vector) application.getAttribute("activeSessions");
if (activeSessions == null)
{
activeSessions = new Vector();
application.setAttribute("activeSessions",activeSessions);
}
Iterator it = activeSessions.iterator();
while (it.hasNext())
{
HttpSession sess = (HttpSession)it.next();
JDBCUser sessionUser = (JDBCUser)sess.getAttribute("user");
String userId = (sessionUser!=null)?sessionUser.getUserID():"None";
%>
<tr>
<td nowrap=''><%= sess.getId() %></td>
<td nowrap=''><%= userId %></td>
<td nowrap=''>
<%= BeaconDate.getInstance( new java.util.Date(sess.getCreationTime())).getDateTimeString()%></td>
<td class="<%= stl %>3" nowrap=''>
<%= BeaconDate.getInstance( new java.util.Date(sess.getLastAccessedTime())).getDateTimeString()%></td>
</tr>
<%
}
%>
</table>
</body>
[/code]以上的代码从application中取出activeSessions,并且显示出具体的时间。其中
BeaconDate类假设为格式化时间的类。这样,我们得到了一个察看在线用户的列表的框架。至于在线用户列表分页等功能,
与本文无关,不予讨论。
这是一个非刷新模型的例子,依赖于session的超时机制。我的同事sonymusic指出很
多时候由于各个厂商思想的不同,这有可能是不可信赖的。考虑到这种需求,需要在
每个叶面刷新的时候都判断当前用户距离上次使用的时间是否超过某一个预定时间值。
这实质上就是自己实现session超时。
如果需要实现刷新模型,就必须使用这种每个叶面进行刷新判断的方法。曹晓钢
2001年12月3日
本文版权属于南京丰柏信息技术有限公司。保留一切权力。
(若不保留此版权信息,请勿转载)