Servlet 监听器接口详解(Listener) 您所在的位置:网站首页 监听有什么作用 Servlet 监听器接口详解(Listener)

Servlet 监听器接口详解(Listener)

2024-03-03 20:54| 来源: 网络整理| 查看: 265

目录

1、什么是监听器,监听器有什么作用?

2、Servlet 中有哪些监听器?

3、如何使用Servlet自带的监听器接口?

4、如何自定义一个监听器的实现?

5、监听器的实例在tomcat中是如何创建和注册的?源码展示

6、同类型的监听器,如何保障监听器的执行顺序?

1、什么是监听器,监听器有什么作用?

        监听器 Listener 是一个实现特定接口的程序,它基于观察者模式实现,可以在程序运行时对事件进行监控和响应。使用监听器可以使程序更加灵活和可扩展,具有以下几点优点:

分离关注点:将事件处理逻辑和业务逻辑分离,使程序更加模块化和易于维护。降低耦合性:将事件的产生和处理解耦,使程序更加灵活和可扩展。提高可重用性:监听器可以重复使用,减少代码冗余。提高程序响应速度:当事件发生时,监听器可以立即响应,提高程序响应速度。提高程序的可靠性:监听器可以对程序中可能发生的异常进行处理,提高程序的健壮性和可靠性。

        // 本质来说只是一种代码的设计模式,既然是设计模式,无非就是解耦合,提高程序可拓展性之类的云云。

2、Servlet 中有哪些监听器?

        Servlet 中的监听器主要用于监听 ServletContext、HttpSession 和 ServletRequest 等对象的生命周期和属性的变化,这些监听器可以用来处理 Web 应用程序中的各种事件,例如初始化、销毁、属性变化等。

在 Servlet 中,常见的监听器包括以下三种:

ServletContextListener:用于监听 ServletContext 对象的生命周期和属性变化。当 ServletContext 对象被创建或销毁时,或者 ServletContext 对象的属性发生变化时,ServletContextListener 可以捕获这些事件并进行处理。HttpSessionListener:用于监听 HttpSession 对象的生命周期和属性变化。当 HttpSession 对象被创建或销毁时,或者 HttpSession 对象的属性发生变化时,HttpSessionListener 可以捕获这些事件并进行处理。ServletRequestListener:用于监听 HttpServletRequest 对象的生命周期和属性变化。当 HttpServletRequest 对象被创建或销毁时,或者 HttpServletRequest 对象的属性发生变化时,ServletRequestListener 可以捕获这些事件并进行处理。 3、如何使用Servlet自带的监听器接口?

        使用监听器通常需要以下几个步骤:// 总结起来就是:实现监听器接口并注册

实现监听器接口:根据需要,选择要使用的监听器类型,并实现相应的接口,例如实现 HttpSessionListener 接口来监听 HttpSession 对象的创建和销毁事件。注册监听器:在 web.xml 文件中配置监听器,并将其注册到相应的组件中,例如在 web.xml 文件中配置 HttpSessionListener 监听器。// 也可以使用注解进行配置

        以下是使用注解方式配置一个监听器的示例:

        首先实现监听器接口,MyHttpSessionListener 实现了 HttpSessionListener 接口来监听 HttpSession 对象的创建和销毁事件。然后,使用 @WebListener 注解标注该监听器类:

import javax.servlet.annotation.WebListener; import javax.servlet.http.HttpSessionEvent; import javax.servlet.http.HttpSessionListener; @WebListener public class MyHttpSessionListener implements HttpSessionListener { @Override public void sessionCreated(HttpSessionEvent se) { System.out.println("Session Created: " + se.getSession().getId()); } @Override public void sessionDestroyed(HttpSessionEvent se) { System.out.println("Session Destroyed: " + se.getSession().getId()); } } 4、如何自定义一个监听器的实现?

        自定义一个监听器,可以按照以下步骤进行:

        (1)定义监听器接口:根据需要,首先定义一个监听器接口,并在其中定义相应的事件方法。例如,定义一个名为 MyListener 的监听器接口,其中包含一个名为 handleEvent 的方法用于处理事件。

public interface MyListener { void handleEvent(MyEvent event); }

        (2)实现事件对象:定义一个事件对象 MyEvent,用于封装事件相关的信息。

public class MyEvent { private String message; public MyEvent(String message) { this.message = message; } public String getMessage() { return message; } }

        (3)实现监听器:实现 MyListener 接口,并在其中实现 handleEvent 方法,用于处理事件。

public class MyListenerImpl implements MyListener { @Override public void handleEvent(MyEvent event) { System.out.println("Received event message: " + event.getMessage()); } }

        (4)实现事件源:定义一个事件源对象 MyEventSource,并在其中添加注册、移除和触发监听器事件的方法。// 这一步很重要,把事件和监听器关联起来

import java.util.ArrayList; import java.util.List; public class MyEventSource { private List listeners = new ArrayList(); public void addListener(MyListener listener) { listeners.add(listener); } public void removeListener(MyListener listener) { listeners.remove(listener); } public void fireEvent(MyEvent event) { for (MyListener listener : listeners) { listener.handleEvent(event); } } }

        使用监听器:创建 MyEventSource 对象,并向其注册 MyListener 监听器,然后触发事件并处理监听器事件。

public class TestListener { public static void main(String[] args) { MyEventSource source = new MyEventSource(); MyListener listener = new MyListenerImpl(); source.addListener(listener); source.fireEvent(new MyEvent("Hello, world!")); } }

        在实现自定义监听器时,需要注意编写良好的代码结构和设计,以便扩展和维护。同时,应该根据实际需求选择合适的事件类型和监听器类型,并编写相应的处理逻辑,以实现所需的功能。

        // 整个过程看下来,感觉像不像就是设计模式?不用感觉,它就是!!!

5、监听器的实例在tomcat中是如何创建和注册的?源码展示

        @WebListener注解是由Java Servlet规范提供的,其具体实现由Servlet容器厂商完成。以下是Tomcat容器实现@WebListener注解的关键源码展示:// 监听器由Servlet容器创建

        首先,Tomcat容器会在启动时扫描应用程序中所有的类,通过解析注解信息来实例化监听器对象:

public void startInternal() throws LifecycleException { ... // Instantiate and initialize all listeners defined in our context for (ServletContextListener listener : context.findListeners()) { instanceSupport.addLifecycleListener(new LifecycleListener() { @Override public void lifecycleEvent(LifecycleEvent event) { if (event.getType().equals(Lifecycle.AFTER_START_EVENT)) { listener.contextInitialized(new ServletContextEvent(context)); } else if (event.getType().equals(Lifecycle.BEFORE_STOP_EVENT)) { listener.contextDestroyed(new ServletContextEvent(context)); } } }); } ... }

        在上述代码中,通过调用context.findListeners()方法获取所有标注了@WebListener注解的监听器类,然后通过反射机制实例化这些类,并将其注册到对应的事件源对象中。

public static List findListeners( ServletContext servletContext, ClassLoader classLoader) { List listeners = new ArrayList(); Set> classes = AnnotationProcessor.scanClasspath(classLoader, true, WebListener.class); listenerClasses.addAll(classes); for (Class clazz : listenerClasses) { WebListener ann = clazz.getAnnotation(WebListener.class); if (ann == null) { continue; } Class targetClass = clazz; while (targetClass != null) { if (isListenerClass(targetClass)) { break; } targetClass = targetClass.getSuperclass(); } if (targetClass == null) { targetClass = clazz; } try { listeners.add((ServletContextListener) targetClass.newInstance()); } catch (InstantiationException | IllegalAccessException e) { throw new IllegalStateException(e); } } return listeners; }

        在上述代码中,通过扫描应用程序中所有的类,并解析其中的@WebListener注解信息。如果找到了标注了该注解的类,容器会将该类转换成对应的监听器类型,并将其实例化。

        需要注意的是,不同的Servlet容器对@WebListener注解的实现逻辑可能会略有不同,但大体的原理和实现方法都是类似的。

6、同类型的监听器,如何保障监听器的执行顺序?

        使用@WebListener注解声明的监听器的执行顺序是不确定的,因为Servlet规范并没有明确规定使用注解声明的监听器的执行顺序。

        如果需要保证监听器的执行顺序,最好还是使用web.xml文件进行声明。在web.xml中声明的监听器顺序就是它们被执行的顺序。但是,在使用注解声明监听器时,也可以通过实现Ordered接口或使用@Order注解来指定监听器的执行顺序。



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有