Servlet 监听器接口详解(Listener)

目录

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

2、Servlet 中有哪些监听器?

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

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

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

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


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

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

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

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

2、Servlet 中有哪些监听器?

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

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

  1. ServletContextListener:用于监听 ServletContext 对象的生命周期和属性变化。当 ServletContext 对象被创建或销毁时,或者 ServletContext 对象的属性发生变化时,ServletContextListener 可以捕获这些事件并进行处理。
  2. HttpSessionListener:用于监听 HttpSession 对象的生命周期和属性变化。当 HttpSession 对象被创建或销毁时,或者 HttpSession 对象的属性发生变化时,HttpSessionListener 可以捕获这些事件并进行处理。
  3. ServletRequestListener:用于监听 HttpServletRequest 对象的生命周期和属性变化。当 HttpServletRequest 对象被创建或销毁时,或者 HttpServletRequest 对象的属性发生变化时,ServletRequestListener 可以捕获这些事件并进行处理。

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

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

  1. 实现监听器接口:根据需要,选择要使用的监听器类型,并实现相应的接口,例如实现 HttpSessionListener 接口来监听 HttpSession 对象的创建和销毁事件。
  2. 注册监听器:在 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<MyListener> 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<ServletContextListener> findListeners(
        ServletContext servletContext, ClassLoader classLoader) {

    List<ServletContextListener> listeners = new ArrayList<>();

    Set<Class<?>> listenerClasses = new LinkedHashSet<>();
    Set<Class<?>> 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注解来指定监听器的执行顺序

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
Java中的监听器Listener)是一种广泛应用的设计模式,它用于处理程序中的事件。通过监听器,我们可以在事件发生时执行一些特定的操作。在Java中,我们可以使用内置的监听器API或自定义监听器实现此功能。 下面是Java中的常见监听器类型: 1. ActionListener:用于处理按钮、菜单等组件的动作事件。 2. WindowListener:用于处理窗口事件,如窗口打开、关闭等。 3. MouseListener:用于处理鼠标事件,如单击、双击、拖动等。 4. KeyListener:用于处理键盘事件,如键盘按下、释放等。 5. FocusListener:用于处理组件焦点事件,如获得或失去焦点等。 使用监听器的步骤如下: 1. 创建一个监听器类,该类实现了相应的监听器接口。 2. 在需要监听的组件上添加监听器对象。 3. 在监听器类中实现相应的方法来处理事件。 下面是一个简单的示例代码,演示了如何使用ActionListener监听器处理按钮单击事件: ```java import java.awt.*; import java.awt.event.*; import javax.swing.*; public class ButtonListenerDemo implements ActionListener { private JFrame frame; private JButton button; public ButtonListenerDemo() { frame = new JFrame("Button Listener Demo"); button = new JButton("Click Me"); button.addActionListener(this); frame.getContentPane().add(button); frame.pack(); frame.setVisible(true); } public void actionPerformed(ActionEvent e) { JOptionPane.showMessageDialog(frame, "Button Clicked!"); } public static void main(String[] args) { new ButtonListenerDemo(); } } ``` 在上面的代码中,我们创建了一个ButtonListenerDemo类,该类实现了ActionListener接口。在构造函数中,我们创建了一个按钮对象,然后将该按钮添加到窗口中,并将该按钮的监听器设置为当前类。当用户单击按钮时,程序将调用actionPerformed()方法来处理事件,该方法将弹出一个消息框来告诉用户按钮已被单击。 总之,监听器是Java编程中非常重要的组成部分。使用监听器,我们可以轻松地处理程序中的事件,并实现交互式用户界面。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

swadian2008

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值