英文:
Add tomcat listener LifecycleListener without changing server.xml or tomcat/web.xml
问题
我有以下代码,需要在server.xml中添加以下条目,并且文件必须放置在tomcat/lib中。
我想要添加Tomcat监听器,并且不想在tomcat服务器配置中做任何更改。我是否有办法实现这一点?
注意:我已经尝试过"ServletContextListener",但它不如LifecycleListener准确。
server.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成功启动");
}
}
}
英文:
I have below code which required below entry in server.xml and file must placed in tomcat/lib.
I want to add tomcat listener and do not want to make any changes in tomcat server configuration. Is there any way I can achieve this?
Note : I have already tried "ServletContextListener" but it is not accurate as LifecycleListener.
Server.xml
<Listener className="com.tomcat.listener.TomcatListener"/>
Java file
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");
}
}
}
答案1
得分: 1
使用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中ServletContext的实现位于ApplicationContextFacade、ApplicationContext和StandardContext中,因此将监听器添加到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());
}
/**
* 使用反射获取类字段,因为无法直接访问
* @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 {
// 恢复Accessablility标志到之前的状态
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成功启动");
}
}
}
英文:
With the help of ServletContextListener, LifecycleListener and reflection I am able to achieve what I was expecting.
So here we are first capturing event of ServletContextListener to get the ServletContext and then using reflection and we are accessing private fields to add listener in ServletContext implementation of Tomcat
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");
}
}
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论