1、java事件监听机制
* 1.java的事件监听机制涉及到三个组件:事件源、事件监听器、事件对象
* 2.当事件源上发生操作时,它将会调用事件监听器的一个方法,并在调用这个方法时,会传递事件对象过来。
* 3事件监听器由开发人员编写,开发人员在事件监听器中,通过事件对象可以拿到事件源,从而对事件源上的操作进行处理。
代码片段:
<span style="font-family:KaiTi_GB2312;font-size:14px;">//观察者设计模式(observer设计模式)
//事件源
class Person{
private PersonListener listener;
public void registerListener(PersonListener listener){
this.listener = listener;
}
public void run(){
if(listener!=null){
Even even = new Even(this);
this.listener.dorun(even);
}
System.out.println("runn!!");
}
public void eat(){
if(listener!=null){
Even e = new Even(this);
this.listener.doeat(e);
}
System.out.println("eat!!");
}
}
//事件监听器
interface PersonListener{
public void dorun(Even even);
public void doeat(Even even);
}
//事件对象(封装事件源)
class Even{
private Person person;
public Even() {
super();
}
public Even(Person person) {
super();
this.person = person;
}
public Person getPerson() {
return person;
}
public void setPerson(Person person) {
this.person = person;
}
}
public class Demo3 {
public static void main(String[] args) {
Person p = new Person();
p.registerListener(new MyListener1());
p.eat();
p.run();
}
}
class MyListener1 implements PersonListener{
public void doeat(Even even) {
System.out.println(even.getPerson()+"你天天吃,你就知道吃,你猪啊!!");
}
public void dorun(Even even) {
System.out.println(even.getPerson()+"你吃完就跑,有病!!");
}
}
</span><span style="font-family:KaiTi_GB2312;font-size:14px;">
</span>
在Servlet规范中定义了多种类型的监听器,它们用于监听的事件源分别为ServletContext, HttpSession 和ServletRequest 这三个域对象。
l
Servlet规范针对这三个对象上的操作,又把这多种类型的监听器划分为三种类型。
•监听三个域对象创建和销毁的事件监听器
•监听域对象中属性的增加和删除的事件监听器
•监听绑定到 HttpSession 域中的某个对象的状态的事件监听器。(查看API文档)
2.1--[编写Servlet监听器]
和编写其它事件监听器一样,编写servlet监听器也需要实现一个特定的接口,并针对相应动作覆盖接口中的相应方法。
和其它事件监听器略有不同的是,servlet监听器的注册不是直接注册在事件源上,而是由WEB容器负责注册,开发人员只需在web.xml文件中使用<listener>标签配置好监听器,web容器就会自动把监听器注册到事件源中。一个web.xml 文件中可以配置多个Servlet 事件监听器,web 服务器按照它们在web.xml 文件中的注册顺序来加载和注册这些Serlvet 事件监听器。
2.2--[监听三个域对象域对象创建和销毁]
监听servletContext域对象创建和销毁:
ServletContextListener 接口用于监听ServletContext 对象的创建和销毁事件。
当ServletContext 对象被创建时,激发contextInitialized (ServletContextEventsce)方法
当ServletContext 对象被销毁时,激发contextDestroyed(ServletContextEvent sce)方法。
•创建:服务器启动针对每一个web应用创建servletcontext
•销毁:服务器关闭前先关闭代表每一个web应用的servletContext
监听HttpSession域对象创建和销毁
HttpSessionListener接口用于监听HttpSession的创建和销毁
创建一个Session时,sessionCreated(HttpSessionEvent se) 方法将会被调用。
销毁一个Session时,sessionDestroyed (HttpSessionEvent se) 方法将会被调用。
•创建:用户每一次访问时,服务器创建session
•销毁:如果用户的session 30分钟没有使用,服务器就会销毁session,我们在web.xml里面也可以配置session失效时间
监听HttpRequest域对象创建和销毁
ServletRequestListener 接口用于监听ServletRequest 对象的创建和销毁。
Request 对象被创建时,监听器的requestInitialized方法将会被调用。
Request对象被销毁时,监听器的requestDestroyed方法将会被调用。
•创建:用户每一次访问,都会创建一个reqeust
•销毁:当前访问结束,request对象就会销毁
当ServletContext 对象被创建时,激发contextInitialized (ServletContextEventsce)方法
当ServletContext 对象被销毁时,激发contextDestroyed(ServletContextEvent sce)方法。
•创建:服务器启动针对每一个web应用创建servletcontext
•销毁:服务器关闭前先关闭代表每一个web应用的servletContext
监听HttpSession域对象创建和销毁
HttpSessionListener接口用于监听HttpSession的创建和销毁
创建一个Session时,sessionCreated(HttpSessionEvent se) 方法将会被调用。
销毁一个Session时,sessionDestroyed (HttpSessionEvent se) 方法将会被调用。
•创建:用户每一次访问时,服务器创建session
•销毁:如果用户的session 30分钟没有使用,服务器就会销毁session,我们在web.xml里面也可以配置session失效时间
监听HttpRequest域对象创建和销毁
ServletRequestListener 接口用于监听ServletRequest 对象的创建和销毁。
Request 对象被创建时,监听器的requestInitialized方法将会被调用。
Request对象被销毁时,监听器的requestDestroyed方法将会被调用。
•创建:用户每一次访问,都会创建一个reqeust
•销毁:当前访问结束,request对象就会销毁
2.3--[监听三个域对象属性变化]
Servlet规范定义了监听ServletContext, HttpSession,HttpServletRequest 这三个对象中的属性变更信息事件的监听器。
这三个监听器接口分别是ServletContextAttributeListener,HttpSessionAttributeListener ServletRequestAttributeListener
这三个接口中都定义了三个方法来处理被监听对象中的属性的增加,删除和替换的事件,同一个事件在这三个接口中对应的方法名称完全相同,只是接受的参数类型不同。attributeAdded方法,attributeRemoved方法,attributeReplaced方法。
2.4--[感知 Session绑定的事件监听器]
保存在Session 域中的对象可以有多种状态:绑定到 Session中;从 Session域中解除绑定;随 Session对象持久化到一个存储设备中;随 Session 对象从一个存储设备中恢复。Servlet 规范中定义了两个特殊的监听器接口来帮助 JavaBean 对象了解自己在 Session域中的这些状态:HttpSessionBindingListener接口和HttpSessionActivationListener接口,实现这两个接口的类不需要 web.xml文件中进行注册,因为他们事件源和监听器是同一对象。
HttpSessionBindingListener接口
实现了HttpSessionBindingListener接口的JavaBean 对象可以感知自己被绑定到Session 中和从Session 中删除的事件
当对象被绑定到HttpSession 对象中时,web 服务器调用该对象的 voidvalueBound(HttpSessionBindingEvent event)方法
当对象从HttpSession 对象中解除绑定时,web 服务器调用该对象的voidvalueUnbound(HttpSessionBindingEvent event)方法
HttpSessionActivationListener接口
实现了HttpSessionActivationListener接口的JavaBean 对象可以感知自己被活化和钝化的事件
当绑定到HttpSession 对象中的对象将要随HttpSession 对象被钝化之前,web 服务器调用如下方法sessionWillPassivate(HttpSessionBindingEventevent) 方法
当绑定到HttpSession 对象中的对象将要随HttpSession 对象被活化之后,web 服务器调用该对象的voidsessionDidActive(HttpSessionBindingEvent event)方法
3、简单应用之代码片段
3.1--[l统计当前在线人数]
<span style="font-size:14px;">public class CountNumListener implements HttpSessionListener {
public void sessionCreated(HttpSessionEvent se) {
ServletContext context = se.getSession().getServletContext();
Integer count = (Integer) context.getAttribute("count");
if(count==null){
count = 1;
context.setAttribute("count", count);
}else{
count++;
context.setAttribute("count", count);
}
}
public void sessionDestroyed(HttpSessionEvent se) {
ServletContext context = se.getSession().getServletContext();
Integer count = (Integer) context.getAttribute("count");
count--;
context.setAttribute("count", count);
}
}</span><span style="font-size:24px;font-weight: bold;">
</span>
3.2--[l自定义session扫描器]
<span style="font-size:14px;">public class SessionScanner implements HttpSessionListener,ServletContextListener {
//Collections这个集合工具类生成的集合是线程安全的。
private List<HttpSession> list = Collections.synchronizedList(new LinkedList<HttpSession>());
private Object lock = new Object();
public void contextInitialized(ServletContextEvent sce) {
Timer timer = new Timer();
timer.schedule(new MyTask(list,lock), 0, 30*1000);
}
public void sessionCreated(HttpSessionEvent se) {
HttpSession session = se.getSession();
System.out.println(session + "被创建了!!");
synchronized (lock) { //锁旗标
list.add(session);
}
}
public void sessionDestroyed(HttpSessionEvent se) {
System.out.println(se.getSession() + "被销毁了");
}
public void contextDestroyed(ServletContextEvent sce) {
// TODO Auto-generated method stub
}
}
class MyTask extends TimerTask{
private List list;
private Object lock;
public MyTask(List list,Object lock){
this.list = list;
this.lock = lock;
}
@Override
public void run() {
System.out.println("定时器执行!!");
synchronized (this.lock) {
ListIterator it = list.listIterator();
while(it.hasNext()){
HttpSession session = (HttpSession) it.next();
if((System.currentTimeMillis()-session.getLastAccessedTime())>30*1000){
session.invalidate();
//list.remove(session); //并发修改异常
it.remove();
}
}
}
}
}
/*class MyList{
Object arr[] = new Object[10];
public void add(Object obj){ //session
if(arr[0]==null){
arr[0] = obj;
}
}
}*/</span><span style="font-size:24px;font-weight: bold;">
</span>
3.3--[踢用户]
<span style="font-size:14px;">public class UserListener implements HttpSessionAttributeListener {
public void attributeAdded(HttpSessionBindingEvent se) {
Map map = (Map) se.getSession().getServletContext().getAttribute("map");
if(map==null){
map = new HashMap();
se.getSession().getServletContext().setAttribute("map", map);
}
Object object = se.getValue();
if(object instanceof User){
User user = (User) object;
map.put(user.getUsername(), se.getSession());
}
}
public void attributeRemoved(HttpSessionBindingEvent se) {
......
}
public void attributeReplaced(HttpSessionBindingEvent se) {
......
}
}
public class KickServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String username = request.getParameter("username");
username = new String(username.getBytes("iso8859-1"),"UTF-8");
Map map = (Map) this.getServletContext().getAttribute("map");
HttpSession session = (HttpSession) map.get(username);
if(session!=null){
session.invalidate();
map.remove(username);
}
response.sendRedirect("/kick/listuser.jsp");
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}</span><pre name="code" class="java">
public class LoginServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
request.setCharacterEncoding("UTF-8");
String username = request.getParameter("username");
String password = request.getParameter("password");
User user = new User();
user.setPassword(password);
user.setUsername(username);
request.getSession().setAttribute("user", user);
response.sendRedirect("/kick/index.jsp");
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}