写在前面
继前面的Filter``Servlet
内存马技术,这是系列文章的第三篇了,这篇将给大家带来的是Listener
内存马技术。
前置
什么是Listener?
监听器 Listener 是一个实现特定接口的 Java 程序,这个程序专门用于监听另一个 Java
对象的方法调用或属性改变,当被监听对象发生上述事件后,监听器某个方法将立即自动执行。
监听器的相关概念:
事件:方法调用、属性改变、状态改变等。
事件源:被监听的对象( 例如:request、session、servletContext)。
监听器:用于监听事件源对象 ,事件源对象状态的变化都会触发监听器。
注册监听器:将监听器与事件源进行绑定
监听器 Listener 按照监听的事件划分,可以分为 3 类:
监听对象创建和销毁的监听器
监听对象中属性变更的监听器
监听 HttpSession 中的对象状态改变的监听器
Listener的简单案例
在Tomcat中创建Listener有两种方式:
使用web.xml中的
listener
标签创建使用
@WebListener
注册监听器
我们创建一个实现了javax.servlet.ServletRequestListener
接口的类。
package pres.test.momenshell;
import javax.servlet.ServletRequestEvent;
import javax.servlet.ServletRequestListener;
public class ListenerTest implements ServletRequestListener {
@Override
public void requestDestroyed(ServletRequestEvent servletRequestEvent) {
System.out.println("destroy Listener!");
}
@Override
public void requestInitialized(ServletRequestEvent servletRequestEvent) {
System.out.println("initial Listener!");
}
}
将会在请求开始和请求结束分别执行requestInitialized
或者requestDestroyed
方法中的逻辑,
之后再web.xml
中配置Listener。
<listener>
<listener-class>pres.test.momenshell.ListenerTest</listener-class>
</listener>
之后开启tomcat容器。
在请求前和请求后都会执行对应逻辑。
Listener流程分析
首先给出程序到requestInitialized
方法之前的调用栈。
requestInitialized:14, ListenerTest (pres.test.momenshell)
fireRequestInitEvent:5982, StandardContext (org.apache.catalina.core)
invoke:121, StandardHostValve (org.apache.catalina.core)
invoke:81, ErrorReportValve (org.apache.catalina.valves)
invoke:698, AbstractAccessLogValve (org.apache.catalina.valves)
invoke:78, StandardEngineValve (org.apache.catalina.core)
service:364, CoyoteAdapter (org.apache.catalina.connector)
service:624, Http11Processor (org.apache.coyote.http11)
process:65, AbstractProcessorLight (org.apache.coyote)
process:831, AbstractProtocol$ConnectionHandler (org.apache.coyote)
doRun:1673, NioEndpoint$SocketProcessor (org.apache.tomcat.util.net)
run:49, SocketProcessorBase (org.apache.tomcat.util.net)
runWorker:1191, ThreadPoolExecutor (org.apache.tomcat.util.threads)
run:659, ThreadPoolExecutor$Worker (org.apache.tomcat.util.threads)
run:61, TaskThread$WrappingRunnable (org.apache.tomcat.util.threads)
run:748, Thread (java.lang)
将会到达StandardHostValve#invoke
方法。
调用了StandardContext#fireRequestInitEvent
方法进行请求初始化。
在其中,程序通过扫描web.xml中得到了对应的实例化对象,因为我们在web.xml中做出了对应的配置,所以我们能够通过if (instance != null && instance instanceof ServletRequestListener)
的判断,进而调用了listener的requestInitialized
方法。
即为我们的ListenerTest#requestInitia