1.1 举例 : 在线用户 我们做一个新手级的在线用户列表, 原理是这样 : 1. 用户登录, 并把登录使用的用户名保存到 session 中, 通过 session 中 是否存在用户名判断用户是否已登录 session 可以在整个会话过程中保存用户信息, 不必每次刷新页面都重新 登录 2. 用户登录后, 将用户名添加到 application 中的在线用户列表 用 户注销时, 讲用户名从 application 中的在线列表删除
只要服务器还在运行着,application 就会保存所有登录用户的信息, 所 有用户都可以看到这个在线用户列表 看如下的例子 : 1. 进入登录页面, 登陆一个用户 Index.jsp 2. 登录成功既看到已登录的用户名, 和当前的在线用户列表 Result.jsp 3. 再登录一个用户. 4. 然后就可以看到在线用户列表增加了, 可以看到里面包含上次登录的用户 和当前登录的用户
这时, 如果第一个用户刷新页面, 也会看到在线用户列表中变成两个人
5. 现在任何一个用户点击注销, 将返回登录页面 另一个用户刷新页面会发 现在线用户列表减少了 让我们从登录页面 index.jsp 开始, 复习一下目前学到的知识 index.jsp 中显示的是用户登录表单, 为了显示 index.jsp 中包含的中文, 需要加上 @ page contenttype="text/html; charset=utf-8", 这里使用的文件编码是默认的 utf-8 index.jsp <form action="login.jsp" method="post"> 用户名 :<input type="text" name="username" /> <br /> <input type="submit" value=" 登录 " /> </form> 在这个 form 里我们可以输入一个 username 的值, 提交的 url 是 login.jsp, 使用 post 方法是为了更简单的解决中文问题 在填写了用户名之后, 点击登录 按钮, 将数据提交到 login.jsp login.jsp 中进行的是对用户名的操作, 包括获得请求中的用户名, 将用户名添 加到 session 和在线用户列表中
Login.jsp @ page import="java.util.*" request.setcharacterencoding("utf-8"); // 取得登录的用户名 String username = request.getparameter("username"); // 把用户名保存进 session session.setattribute("username", username); // 把用户名放入在线列表 List onlineuserlist = (List) application.getattribute("onlineuserlist"); // 第一次使用前, 需要初始化 if (onlineuserlist == null) { onlineuserlist = new ArrayList(); application.setattribute("onlineuserlist", onlineuserlist); } onlineuserlist.add(username); // 成功 response.sendredirect("result.jsp"); 中文编码设置和获得请求参数都已经熟识了 在获得在线用户列表时, 先获得 application 中的 onlineuserlist, 强制转换成 List 类型 如果 onlineuserlist 并不存在, 我们还需要先对它做初始化, 并添加到 application 里 这时有一个小技巧, 因为 onlineuserlist 已经放在 application 中了, 将 username 添加进去后, 不必再使用 setattribute() 也可以达到修改在下用户列表的效果 因为此处用到的 List 和 ArrayList 都是定义在 java.util 包内的工具类, 如果不希望写成全类名 java.util.list, java.util.arraylist 的形式, 就需要使用 @ page import="java.util.*" 做声明, 当然也可以写成 @ page import="java.util.list,java.util.arraylist", 具体情况就任君选择了
登录成功后, 使用 redirect 的方式跳转到 result.jsp 页面,result.jsp 页面中显示的是当前登录用户和在线用户列表的信息 Result.jsp @ page contenttype="text/html; charset=utf-8" import="java.util.*" <html> <head> </head> <body> <h3> 您好 :${username} [<a href="logout.jsp"> 注销 </a>]</h3> List onlineuserlist = (List) application.getattribute("onlineuserlist"); for (int i = 0; i < onlineuserlist.size(); i++) { String onlineusername = (String) onlineuserlist.get(i); <tr> <td>=onlineusername</td> </tr> } </body> </html> 先看一下页面中使用的 jsp 指令 (directive), @ page contenttype="text/html; charset=utf-8" import="java.util.*", 为了处理中文和使用 import, 可以把这两部分写在一起 显示当前登陆名时, 使用了 el 表达式 : <h3> 您好 :${username} [<a href="logout.jsp"> 注销 </a>]</h3>
显示在线用户列表的时候使用了循环 : List onlineuserlist = (List) application.getattribute("onlineuserlist"); for (int i = 0; i < onlineuserlist.size(); i++) { String onlineusername = (String) onlineuserlist.get(i); <tr> <td>=onlineusername</td> </tr> } 这里的循环体可能会令人感到费解, 其实它与下面的写法是等价的 : List onlineuserlist = (List)application.getAttribute("onlineUserList"); for (int i = 0; i < onlineuserlist.size(); i++) { String onlineusername = (String) onlineuserlist.get(i); out.println("<tr>"); out.println("<td>" + onlineusername +"</td>"); out.println("</tr>"); } 只需要理解代码的含义就可以了, 从 application 里获得 onlineuserlist, 然 后循环输出所有的用户名 application 是公用的, 所以可以看到每个登录的用 户 点击注销的时候, 会跳转到 logout.jsp, 这里负责用户注销和从在线用户列表
去除已登录用户 Logout.jsp @ page import="java.util.*" // 取得登录的用户名 String username = (String) session.getattribute("username"); // 销毁 session session.invalidate(); // 从在线列表中删除用户名 List onlineuserlist = (List)application.getAttribute("onlineUserList" ); onlineuserlist.remove(username); // 成功 response.sendredirect("index.jsp");
这次我们从 session 中获得登录名, 因为请求中没有包含任何数据 session.invalidate() 这个方法给我们提供了一条销毁 session 的捷径, 不需要一条一条删除 session 中的数据,invalidate() 会直接销毁 session,session 里边所有的数据也就消失了 在线用户列表的操作很直观, 从 application 中获得 onlineuserlist, 然后 remove(username) 就可以从中去除当前登录用户 最后使用 redirect 跳转到 index.jsp 这个登录页面 整个应用的流程也就结束了 整个应用的功能很单纯, 之所以把它叫做 新手级, 是因为它只能用于演示 等待用户去点击注销才去操作在线用户列表存在着问题, 实际使用中, 用户很可能因为个人或网络原因没有进行注销就退出系统, 这样会导致用户列表不能删除, 就这样一直增长下去
解决这个问题的方法超出了目前掌握的知识, 我们将在后面的章节进行介绍 ***