java - 在不改变 server.xml 或 tomcat/web.xml 的情况下添加 tomcat 监听器 LifecycleListener
问题描述
我有以下代码,需要在 server.xml 中的以下条目,并且文件必须放在 tomcat/lib 中。
我想添加 tomcat 侦听器,不想对tomcat 服务器配置进行任何更改。有什么办法可以做到这一点?
注意:我已经尝试过“ServletContextListener”,但它作为 LifecycleListener 并不准确。
服务器.xml
<Listener className="com.tomcat.listener.TomcatListener"/>
Java 文件
package com.tomcat.listener;
import org.apache.catalina.Lifecycle;
import org.apache.catalina.LifecycleEvent;
import org.apache.catalina.LifecycleListener;
public class TomcatListener implements LifecycleListener {
@Override
public void lifecycleEvent(LifecycleEvent event) {
if(Lifecycle.AFTER_START_EVENT.equals(event.getType())){
System.out.print("Tomcat successfully started");
}
}
}
解决方案
在 ServletContextListener、LifecycleListener 和反射的帮助下,我能够实现我所期望的。
所以在这里我们首先捕获 ServletContextListener 的事件以获取 ServletContext 然后使用反射,我们正在访问私有字段以在 Tomcat 的 ServletContext 实现中添加侦听器
CustomServletListener.java
import org.apache.catalina.core.ApplicationContext;
import org.apache.catalina.core.ApplicationContextFacade;
import org.apache.catalina.core.StandardContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.http.HttpSession;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;
import java.lang.reflect.Field;
public final class CustomServletListener implements ServletContextListener{
@Override
public void contextDestroyed(ServletContextEvent event) {
}
@Override
public void contextInitialized(ServletContextEvent event) {
addLifeCycleListener(event);
}
/**
* Tomcat Implementation of ServletContext in ApplicationContextFacade, ApplicationContext,StandardContext as to addListener is located in StandardContext
* @param event
*/
private void addLifeCycleListener(ServletContextEvent event){
ApplicationContextFacade source = (ApplicationContextFacade) event.getSource();
ApplicationContext objApplicationContext=get(source,"context");
StandardContext objStandardContext = get(objApplicationContext,"context");
objStandardContext.addLifecycleListener(new TomcatListener());
}
/**
* Get class field using reflection as it is no way to direct access
* @param object
* @param fieldName
* @param <V>
* @return
*/
@SuppressWarnings("unchecked")
private <V> V get(Object object, String fieldName) {
Class<?> clazz = object.getClass();
Field field = null;
boolean wasAccessable = false;
while (clazz != null) {
try {
field = clazz.getDeclaredField(fieldName);
wasAccessable = field.isAccessible();
if(!wasAccessable){
field.setAccessible(true);
}
return (V) field.get(object);
} catch (NoSuchFieldException e) {
clazz = clazz.getSuperclass();
} catch (IllegalAccessException e) {
throw new IllegalStateException(e);
} finally {
// Revert the Accessablility flag to previous state
if(null!=field && field.isAccessible()!=wasAccessable){
field.setAccessible(wasAccessable);
}
}
}
return null;
}
}
TomcatListener.java
import org.apache.catalina.Lifecycle;
import org.apache.catalina.LifecycleEvent;
import org.apache.catalina.LifecycleListener;
public class TomcatListener implements LifecycleListener {
@Override
public void lifecycleEvent(LifecycleEvent event) {
if(Lifecycle.AFTER_START_EVENT.equals(event.getType())){
System.out.print("Tomcat successfully started");
}
}
}
推荐阅读
- arrays - 使用正则表达式在 json 数组值中查找数字
- kubernetes - 我找不到用 influxdb 设置 grafana 仪表板来监控 kubernetes 集群的方法
- c++ - 如何用 gcc 或 clang 模拟 _mm256_loadu_epi32?
- android - 如何解决android资源链接失败?
- twitter - rtweet 的 get_timeline 中是否有与 max_id 等效的 min_id?
- html - 需要帮助创建一个充满图像的响应式页脚
- reactjs - 如何将处理函数用于两种不同的目的。SPFX(反应/打字稿)
- c++ - 还有其他方法可以在数组中写入多维数组吗?
- python-3.x - 服务器端的阻塞和非阻塞调用,为什么异步客户端很重要?
- spring - 从 spring 配置服务器获取任何服务的属性