【Java EE 学习 20】【使用过滤器实现登陆验证、权限认证】【观察者模式和监听器(使用监听器实现统计在线IP、登录IP 、踢人功能)】

2023-03-05,,

一、使用过滤器实现登录验证、权限认证

  1.创建5张表

/*使用过滤器实现权限过滤功能*/

/**创建数据库*/
DROP DATABASE day20;
CREATE DATABASE day20;
USE DAY20;
/*用户表*/
DROP TABLE IF EXISTS USER;
CREATE TABLE USER(
userid VARCHAR(32) ,
username VARCHAR(32),
userpassword VARCHAR(32),
CONSTRAINT pk_userid PRIMARY KEY (userid)
);
/*角色表*/
CREATE TABLE role(
roleid VARCHAR(32),
rolename VARCHAR(32),
roledes VARCHAR(120),/*角色分配的菜单????*/
CONSTRAINT pk_roleid PRIMARY KEY(roleid)
); /*创建菜单表*/
CREATE TABLE menu(
menuid VARCHAR(32),
menuname VARCHAR(32),
menuurl VARCHAR(32),
CONSTRAINT pk_menuid PRIMARY KEY (menuid)
); /*开始创建中间表*/ /*创建userrole中间表*/
CREATE TABLE userrole(
userid VARCHAR(32),
roleid VARCHAR(32),
CONSTRAINT pk_userrole PRIMARY KEY(userid,roleid),
CONSTRAINT fk_userid FOREIGN KEY(userid) REFERENCES USER(userid),
CONSTRAINT fk_roleid FOREIGN KEY(roleid) REFERENCES role(roleid)
); /*创建rolemenu中间表*/
CREATE TABLE rolemenu(
menuid VARCHAR(32),
roleid VARCHAR(32),
CONSTRAINT rm_pk PRIMARY KEY(menuid,roleid),
CONSTRAINT rm_fk1 FOREIGN KEY(menuid) REFERENCES menu(menuid),
CONSTRAINT rm_fk2 FOREIGN KEY(roleid) REFERENCES role(roleid)
)
INSERT INTO USER VALUES('U001','Jack','');
INSERT INTO USER VALUES('U002','张三','');
INSERT INTO USER VALUES('U003','Tom',''); INSERT INTO role VALUES('R001','管理员','');
INSERT INTO role VALUES('R002','教师',''); INSERT INTO userrole VALUES('U001','R001');
INSERT INTO userrole VALUES('U002','R002'); INSERT INTO menu VALUES('M001','系统管理','/sys.jsp');
INSERT INTO menu VALUES('M002','用户管理','/user.jsp');
INSERT INTO menu VALUES('M003','角色管理','/role.jsp'); INSERT INTO rolemenu VALUES('M001','R001');
INSERT INTO rolemenu VALUES('M002','R001');
INSERT INTO rolemenu VALUES('M003','R001');
INSERT INTO rolemenu VALUES('M003','R002');

创建5张表并初始化数据

  ER图:

  2.sql查询准备

    (1)查找所有用户对应的角色信息

SELECT u.username,r.rolename FROM USER u
INNER JOIN userrole ur ON u.userid=ur.userid
INNER JOIN role r ON r.roleid=ur.roleid;

    (2)查找所有角色对应的管理菜单

SELECT r.rolename,m.menuname FROM role r
INNER JOIN rolemenu rm ON r.roleid=rm.roleid
INNER JOIN menu m ON rm.menuid=m.menuid;

    (3)查找所有用户对应的管理菜单

SELECT u.username,m.menuname FROM USER u
INNER JOIN userrole ur ON u.userid=ur.userid
INNER JOIN role r ON ur.roleid=r.roleid
INNER JOIN rolemenu rm ON r.roleid=rm.roleid
INNER JOIN menu m ON rm.menuid=m.menuid;

    3.注意:在使用过滤器进行权限认证的时候最重要的是sql的写法,即最重要的是数据库查询部分

    4.过滤器

      (1)登陆验证过滤器:首先验证是否已经登陆,如果没有登录的话,首先需要登陆,在web.xml文件中配置的时候要放在所有认证过滤器的前面。

       示例代码:

import java.io.IOException;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; public class LoginFilter implements Filter { public void init(FilterConfig filterConfig) throws ServletException {
// TODO Auto-generated method stub } public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) request;
if(req.getSession().getAttribute("user")==null){
System.err.println("用户还没有登录");
HttpServletResponse resp = (HttpServletResponse) response;
resp.sendRedirect(req.getContextPath()+"/index.jsp?error=2");
}else{
chain.doFilter(req, response);
}
} public void destroy() {
// TODO Auto-generated method stub } }

登录验证过滤器

      (2)权限认证过滤器:如果用户已经登陆(登陆验证过滤器负责),而且想要访问权限不够的资源,比如教师想要进行系统管理,因为教师没有系统管理的权限,所以系统应当拦截该请求并警醒错误提示。

       示例代码:

package cn.itcast.filter;

import java.io.IOException;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest; import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.ScalarHandler; import cn.itcast.domain.User;
import cn.itcast.utils.DataSourceUtils; public class AuthFilter implements Filter { public void init(FilterConfig filterConfig) throws ServletException {
// TODO Auto-generated method stub } public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
//获取uri
HttpServletRequest req = (HttpServletRequest) request;
String uri = req.getRequestURI();//Http://localhost:8080/day20/jsps/role.jsp->day20/jsps/role.jsp
uri = uri.replace(req.getContextPath(), "");
//组成sql
String sql = "SELECT COUNT(1)"+
" FROM menus m INNER JOIN rolemenu rm ON m.id=rm.mid"+
" INNER JOIN roles r ON r.id=rm.rid"+
" INNER JOIN roleuser ru ON r.id=ru.rid"+
" WHERE ru.uid=? AND url=?";
//取到用户的id
User user = (User) req.getSession().getAttribute("user");
try{
QueryRunner run = new QueryRunner(DataSourceUtils.getDatasSource());
Object o = run.query(sql,new ScalarHandler(),user.getId(),uri);
int size = Integer.parseInt(o.toString());
if(size==0){
System.err.println("你没有权限....");
}else{
chain.doFilter(req, response);
} }catch(Exception e){ }
} public void destroy() {
// TODO Auto-generated method stub
} }

权限认证过滤器


二、观察者模式

  1.监听器存在三个对象

    (1)监听者:XxxxListener        

                        一般是一个接口

    (2)被监听者             

                        任意对象都能成为被监听者

    (3)监听到的事件:XxxxEvent

                        永远是一个具体类,用来放监听到的数据,永远都会有一个方法getSource,该方法返回被监听的对象

  2.观察者模式

    (1)java Web中的所有监听器使用的都是观察者模式

    (2)观察者模式模拟

      awt编程模拟:

public class MyFrame extends JFrame {
public MyFrame() {
JButton btn = new JButton("你好");
System.err.println("btn: is:"+btn.hashCode());
btn.addActionListener(new MyListener());
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//获取容器
Container con= getContentPane();
//设置布局
con.setLayout(new FlowLayout());
con.add(btn); setSize(300, 300);
setVisible(true);
}
public static void main(String[] args) {
new MyFrame();
}
//实现一个监听者
class MyListener implements ActionListener{
//监听方法
public void actionPerformed(ActionEvent e) {
System.err.println("我监听到了:"+e.getSource().hashCode());
}
}
}

JFrame按钮单击监听

    (3)观察者模式分析:自己模拟一个观察者模式

     模拟监听某人跑步的动作,一旦监听到被监听者有跑步的动作就要有通知告知被监听者跑步了!

package com.kdyzm.ObserverModel;
//测试观察者模式
public class Main {
public static void main(String args[])
{
Person p=new Person();
p.addPersonListener(new PersonListener(){
@Override
public void doListen(PersonEvent e) {
System.out.println("被监听到正在跑步!");
throw new RuntimeException("他正在跑步!!!");
}
});
p.run();
}
}
interface PersonListener
{
void doListen(PersonEvent e);
}
class PersonEvent
{
Person p=null;
public PersonEvent(Person p)
{
this.p=p;
}
public Person getSource()
{
return p;
}
} class Person
{
PersonListener listener=null;
public void addPersonListener(PersonListener listener)
{
//完成传递监听器的过程。
this.listener=listener;
}
public void run()
{
//被监听者只要有动作,监听器也跟着一起动
if(listener!=null)//如果不加监听器的话也要能够正常“跑步”
{
listener.doListen(new PersonEvent(this));
}
System.out.println("我正在跑步!");
}
}

观察者模式模拟代码

三、监听器

  1.java web中存在三个被监听对象

    (1)HttpServletRequest

    (2)HttpSession

    (3)ServletContext

  2.监听者

监听者

被监听者

监听到事件对象

HttpSessionActivationListener

HttpSession – 监听HttpSession活化和顿化。

HttpSessionEvent 

HttpSessionAttributeListener[W1]

HttpSession – 监听session的属性变化的。S.setAttributee();

HttpSessionBindingEvent 

HttpSessionBindingListener

HttpSession - 监听哪一个对象,绑定到了session上。S.setAtrri(name,User);

HttpSessionListener[W2]

HttpSesion – 监听sessioin创建销毁

HttpSessionEvent

ServletContextAttributeListener

ServletContext – 属性变化的

ServletContextListener

servletContext 创建销毁

ServletRequestListener - serlvetRequestAttibuteListner

Rrequest -创建销毁

 四、监听HttpServletRequest的创建和销毁

  1.一个基本的监听器实现

    第一步:实现一个接口ServletRequestListener,该接口提供了两个方法可以监控Request的创建和销毁。

Method Summary

 void

requestDestroyed(ServletRequestEvent sre)
          Receives
notification that a ServletRequest is about to go out of scope of the web
application.

 void

requestInitialized(ServletRequestEvent sre)
          Receives
notification that a ServletRequest is about to come into scope of the web
application.

  创建的类:

package com.kdyzm.listener;

import javax.servlet.ServletRequestEvent;
import javax.servlet.ServletRequestListener;
public class RequestListener implements ServletRequestListener { @Override
public void requestDestroyed(ServletRequestEvent sre) {
Object request=sre.getSource();
System.out.println(request+"被创建!");
} @Override
public void requestInitialized(ServletRequestEvent sre) {
Object request=sre.getSource();
System.out.println(request+"被销毁!");
}
}

实现了ServletRequestListener接口的类

  第二步:在web.xml文件中进行配置

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.0"
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"> <listener>
<listener-class>com.kdyzm.listener.RequestListener</listener-class>
</listener>
</web-app>

在web.xml文件中的配置

  第三步:通过浏览器向服务器发起请求,如请求默认的index.jsp页面,可以得到该请求对象被创建的时间和该请求对象被销毁的时间。

     说明:

       (1):配置一个Listener只要求提供类名就可以了。

       (2):在tomcat启动时,会自动的初始化这个监听器类。

       (3):tomcat创建的Listner,Serlvet,Filter都是单列的.

五、通过HttpSessionListener监视器实现记录在线人数的功能

  1.API

Method Summary

 void

sessionCreated(HttpSessionEvent se)
          Receives
notification that a session has been created.

 void

sessionDestroyed(HttpSessionEvent se)
          Receives
notification that a session is about to be invalidated.

  2.实现记录在线人数的功能,不仅显示人数,还要将所有在线的人ip地址输出出来,通过配置web.xml设置session的存活时间。

    具体小练习:https://github.com/kdyzm/day20_2

  小练习结果:

org.apache.catalina.session.StandardSessionFacade@19815db session被创建!
C35F7D7FE6B48813E79FD6DB2DC23386 退出!
org.apache.catalina.session.StandardSessionFacade@f6ae8f session被创建!
org.apache.catalina.session.StandardSessionFacade@10ecfa session被创建!
org.apache.catalina.session.StandardSessionFacade@ session被创建!
org.apache.catalina.session.StandardSessionFacade@d38409 session被创建!
org.apache.catalina.session.StandardSessionFacade@818d25 session被创建!
org.apache.catalina.session.StandardSessionFacade@1599f60 session被创建!
org.apache.catalina.session.StandardSessionFacade@ee7f4c session被创建!
E4FEA09EC547D15DEF3C4B13B1327985 退出!
org.apache.catalina.session.StandardSessionFacade@86aa0c session被创建!
21FE11469F2F5C2DECF8AB32F0F18B96 退出!
6BEB338728B16829FB39B693238ADDE3 退出!
F71C51D49A900B3B9C5819D467136970 退出!
CA402FF768C14972F6E3358B27E4DA2D 退出!
ACE87998C0EAA62B2C9332FFBC31EA60 退出!
53A1FFC5F2A80A1EFDD38172C0632CAA 退出!
C6BF0DF4E7042FBEBDC51192ABA3BD7F 退出!

浏览器显示示例:

六、使用HttpSessionAttributeListener监听HttpSession中的属性变化。

  1.API

Method Summary

 void

attributeAdded(HttpSessionBindingEvent event)
          Receives
notification that an attribute has been added to a session.

 void

attributeRemoved(HttpSessionBindingEvent event)
          Receives
notification that an attribute has been removed from a session.

 void

attributeReplaced(HttpSessionBindingEvent event)
          Receives
notification that an attribute has been replaced in a session.

  2.具体用法配置略(小练习七会用到该接口)。

七、小练习:

  要求:

    1.显示所有登陆人数

    2.登录人的ip、还要现实创建session的时间、最后访问的时间

    3.管理员:可以踢出某个用户

  1.项目源代码:https://github.com/kdyzm/day20_3

  2.核心类:

    (1)监听器1个(实现HttpSessionAttributeListener接口)

package com.kdyzm.listener;

import java.util.HashMap;
import java.util.Map; import javax.servlet.ServletContext;
import javax.servlet.http.HttpSession;
import javax.servlet.http.HttpSessionAttributeListener;
import javax.servlet.http.HttpSessionBindingEvent; public class SessionAttributeListener implements HttpSessionAttributeListener { @Override
public void attributeAdded(HttpSessionBindingEvent event) {
String attributename=event.getName();
if(attributename.equals("user"))
{
System.out.println(event.getName()+"新属性被添加!"+event.getValue());
String attributevalue=event.getValue().toString();
ServletContext sc=event.getSession().getServletContext();
Map<String,HttpSession>map=(Map<String, HttpSession>) sc.getAttribute("map");
if(map==null)
{
map=new HashMap<String,HttpSession>();
sc.setAttribute("map", map);
}
map.put(attributevalue, event.getSession());
}
} @Override
public void attributeRemoved(HttpSessionBindingEvent event) {
String name=event.getName();
System.out.println("有属性被移除!"+name+":"+event.getValue());
if(name.equals("user"))
{
ServletContext sc=event.getSession().getServletContext();
String value=event.getValue().toString();
Map<String,HttpSession> map=(Map<String, HttpSession>) sc.getAttribute("map");
map.remove(value);
}
} @Override
public void attributeReplaced(HttpSessionBindingEvent event) {
} }

SessionAttributeListener.java

    (2)过滤器两个(实现Filter接口)

      [1]登陆过滤器: 

package com.kdyzm.filter;

import java.io.IOException;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; public class LoginFilter implements Filter { @Override
public void destroy() {
} @Override
public void doFilter(ServletRequest req, ServletResponse resp,
FilterChain chain) throws IOException, ServletException {
HttpServletRequest request=(HttpServletRequest) req;
HttpServletResponse respose=(HttpServletResponse) resp;
if(request.getSession().getAttribute("user")==null)
{
System.out.println("用户还没有登录!");
respose.sendRedirect(request.getContextPath()+"/index.jsp");
}
else
{
chain.doFilter(request, resp);
}
} @Override
public void init(FilterConfig arg0) throws ServletException {
} }

LoginFilter.java

      [2]获取请求ip的过滤器

package com.kdyzm.filter;
//拦截请求并从请求信息中获取ip信息将信息保存到session中
import java.io.IOException; import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession; public class SessionSetIpFilter implements Filter { @Override
public void destroy() {
} @Override
public void doFilter(ServletRequest req, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
HttpServletRequest request=(HttpServletRequest) req;
if(request.getSession().getAttribute("ip")==null)
{
String ip=request.getRemoteAddr();
System.out.println("有新用户访问!ip="+ip);
HttpSession session=request.getSession();
session.setAttribute("ip", ip);
}
chain.doFilter(request, response);
}
@Override
public void init(FilterConfig arg0) throws ServletException {
} }

SessionSetIpFilter

    (3)Servlet2个:

      [1]将存放Map<String,HttpSession>对象转换成List<Map<String,String>>对象的转换Servlet

package com.kdyzm.servlet;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set; import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession; import com.kdyzm.utils.BaseServlet; public class ShowAll extends BaseServlet { @Override
public void defaultMethod(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
ServletContext sc=getServletContext();
Map<String,HttpSession>map=(Map<String, HttpSession>) sc.getAttribute("map");
List<Map<String,String>>list=new ArrayList<Map<String,String>>();
if(map!=null)
{
Set<Map.Entry<String, HttpSession>>set=map.entrySet();
Iterator <Map.Entry<String, HttpSession>> it=set.iterator();
while(it.hasNext())
{
Map.Entry<String, HttpSession>entry=it.next();
Map<String,String>hashMap=new HashMap<String,String>();
hashMap.put("name",entry.getValue().getAttribute("user").toString());
hashMap.put("ip",entry.getValue().getAttribute("ip").toString());
hashMap.put("createtime",new Date(entry.getValue().getCreationTime()).toString());
hashMap.put("lastaccesstime",new Date(entry.getValue().getLastAccessedTime()).toString());
list.add(hashMap);
}
}
request.setAttribute("userlist", list);
request.getRequestDispatcher("/showAll.jsp").forward(request, response);
} }

ShowAll.java

      [2]处理登陆和踢人请求的Servlet

package com.kdyzm.servlet;

import java.io.IOException;
import java.util.Map; import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession; import com.kdyzm.utils.BaseServlet; public class UserServlet extends BaseServlet {
//默认是登陆
@Override
public void defaultMethod(HttpServletRequest request,
HttpServletResponse response) throws IOException {
String name=request.getParameter("name");
String password=request.getParameter("password");
//暂时不验证
HttpSession session=request.getSession();
session.setAttribute("user", name);
response.sendRedirect(request.getContextPath()+"/index.jsp");
}
public void remove(HttpServletRequest request,HttpServletResponse response) throws IOException
{
String name=request.getParameter("name");
name=new String(name.getBytes("iso-8859-1"),"utf-8");
ServletContext sc=getServletContext();
Map<String,HttpSession>map=(Map<String, HttpSession>) sc.getAttribute("map");
HttpSession session=map.get(name);
session.removeAttribute("user");
response.sendRedirect(request.getContextPath()+"/showAll");
}
}

UserServlet.java

  3.配置文件web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.0"
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
<filter>
<filter-name>sessionSetIpFilter</filter-name>
<filter-class>com.kdyzm.filter.SessionSetIpFilter</filter-class>
</filter>
<filter>
<filter-name>loginFilter</filter-name>
<filter-class>com.kdyzm.filter.LoginFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>loginFilter</filter-name>
<url-pattern>/showAll.jsp</url-pattern>
<dispatcher>REQUEST</dispatcher>
<dispatcher>FORWARD</dispatcher>
</filter-mapping>
<filter-mapping>
<filter-name>sessionSetIpFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping> <servlet>
<servlet-name>UserServlet</servlet-name>
<servlet-class>com.kdyzm.servlet.UserServlet</servlet-class>
</servlet>
<servlet>
<servlet-name>ShowAll</servlet-name>
<servlet-class>com.kdyzm.servlet.ShowAll</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>UserServlet</servlet-name>
<url-pattern>/userServlet</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>ShowAll</servlet-name>
<url-pattern>/showAll</url-pattern>
</servlet-mapping> <listener>
<listener-class>com.kdyzm.listener.SessionAttributeListener</listener-class>
</listener> </web-app>

web.xml

  4.jsp文件

    (1)登陆JSP

<%@ page language="java" import="java.util.*" pageEncoding="utf-8"
contentType="text/html; charset=utf-8" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8">
<title>Insert title here!</title>
<style type="text/css">
table {
border: 1px solid black;
border-collapse: collapse;
margin: 0 auto;
}
td {
border: 1px solid black;
text-align: center;
padding: 3px;
}
</style>
</head>
<body>
<!-- 默认是登陆界面 -->
<c:choose>
<c:when test="${empty sessionScope.user}">
<form action="<c:url value='/userServlet'/>" method="post">
<table>
<tr>
<td>用户名:</td>
<td><input type="text" name="name"></td>
</tr>
<tr>
<td>密码:</td>
<td><input type="text" name="password"></td>
</tr>
<tr>
<td colspan="2"><input type="submit" value="登陆"></td>
</tr>
</table>
</form>
</c:when>
<c:otherwise>
${sessionScope.user}已登录!<br/>
<a href="<c:url value='/showAll'/>">查看登陆用户列表</a>
</c:otherwise>
</c:choose>
</body>
</html>

index.jsp

    (2)显示用户列表JSP

<%@ page language="java" import="java.util.*" pageEncoding="utf-8"
contentType="text/html; charset=utf-8" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8">
<title>Insert title here!</title>
<style type="text/css">
table {
border: 1px solid black;
border-collapse: collapse;
margin: 0 auto;
}
td {
border: 1px solid black;
text-align: center;
padding: 3px;
}
</style>
</head> <body>
这里是在线用户列表!
<table>
<tr>
<td>用户名</td>
<td>ip地址</td>
<td>首次访问时间</td>
<td>最后一次访问时间</td>
<td>踢人</td>
</tr>
<c:forEach items="${requestScope.userlist}" var="map">
<tr>
<td>${map.name}</td>
<td>${map.ip}</td>
<td>${map.createtime }</td>
<td>${map.lastaccesstime}</td>
<td><a href="<c:url value='/userServlet?cmd=remove&name=${map.name}'/>">踢人</a></td>
</tr>
</c:forEach>
</table>
</body>
</html>

showAll.jsp

  5.注意事项:

    (1)Map对象使用put(key,value)方法之后,可以在JSP页面中使用EL表达式${map对象.key)的方式将映射的值取出。

    (2)将IP放到session作用域中之后不能在监视器中直接将该ip拿出,拿到的一定是NULL。

    (3)使用登陆过滤器的时候一定要注意避免循环重定向错误

  6.出现的错误

    循环重定向错误

    

  7.小练习结果:

    (1)直接访问showAll.jsp,重定向到index.jsp页面

    

    (2)登陆之后,再次登陆

    

    (3)查看用户列表

 

    (4)在其它机器登陆之后

    (5)将其他机器上登陆的用户踢掉(不要踢我)

      【1】我的当前页面

  

      【2】其他机器不能继续访问该页面,重定向到登陆页面(刷新之后)

【Java EE 学习 20】【使用过滤器实现登陆验证、权限认证】【观察者模式和监听器(使用监听器实现统计在线IP、登录IP 、踢人功能)】的相关教程结束。

《【Java EE 学习 20】【使用过滤器实现登陆验证、权限认证】【观察者模式和监听器(使用监听器实现统计在线IP、登录IP 、踢人功能)】.doc》

下载本文的Word格式文档,以方便收藏与打印。