添加Tomcat监听器LifecycleListener,无需更改server.xml或tomcat/web.xml。

huangapple go评论68阅读模式
英文:

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,&quot;context&quot;);
StandardContext objStandardContext = get(objApplicationContext,&quot;context&quot;);
objStandardContext.addLifecycleListener(new TomcatListener());
}
/**
* Get class field using reflection as it is no way to direct access
* @param object
* @param fieldName
* @param &lt;V&gt;
* @return
*/
@SuppressWarnings(&quot;unchecked&quot;)
private &lt;V&gt; V get(Object object, String fieldName) {
Class&lt;?&gt; 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 &amp;&amp; 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(&quot;Tomcat successfully started&quot;);
}
}
}

huangapple
  • 本文由 发表于 2020年8月26日 01:13:19
  • 转载请务必保留本文链接:https://go.coder-hub.com/63583946.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定