2

Tomcat でサーブレットを実行しています。いくつかのファイルを提供する必要があります。外部 (WEB-APP への) ディレクトリから準静的 (時折変更される... アプリの別の部分によって更新される) と呼ぶことができると思います。META-INF ディレクトリの context.xml に以下を追加することで、これを行うことができました

<Context aliases="/working_dir=c:/apache_tomcat_working_dir" ></Context>

これは問題なく動作します。私の HTML では、ファイルを次のように参照しています。

<img src="/myWebbApp/working_dir/fixpermin_zoom.png">

そして、WEB-INF内のweb.xmlで、デフォルトサーバーにpngファイルを次のように処理させます

<!-- use default for static serving of png's, js and css, also ico -->
<servlet-mapping>
    <servlet-name>default</servlet-name>
    <url-pattern>*.png</url-pattern>
</servlet-mapping>

したがって、これは正常に機能します。しかし、context.xml ファイルを編集するのではなく、Java コード内から外部ディレクトリを設定したいと考えています。

これでinit()、サーブレットのメソッドで ServletContext を取得できます。

    ServletContext sc =  getServletContext();

デバッガーでこの変数を調べるとsc、エイリアス文字列が数レベル深いことがわかります。添付の​​画像を参照してください。このエイリアス文字列をプログラムで取得するにはどうすればよいですか? ServletContext のドキュメントを確認しましたが、あまり役に立ちません。どんな助けでも大歓迎です。

サーブレット コンテキストのデバッグ ビュー
(出典:choicecomp.com

4

4 に答える 4

2

これは、さまざまなオペレーティング システムに応じて Tomcat7 コンテキスト エイリアスを動的に設定する作業コードです。確かにあなたはそれを改善することができます

public class ContextListener implements ServletContextListener {
@Override
public void contextInitialized(ServletContextEvent sce) {
    ServletContext context = sce.getServletContext();

    // tomcat 7.x
    try {
        MBeanServer mBeanServer = MBeanServerFactory.findMBeanServer(null).get(0);
        ObjectName name = new ObjectName("Catalina", "type", "Server");
        Object server = mBeanServer.getAttribute(name, "managedResource");

        Object service = server.getClass().getMethod("findService", String.class).invoke(server, "Catalina");  //StandardService[Catalina]
        Object connectors = service.getClass().getMethod("findConnectors").invoke(service);
        Object engine = service.getClass().getMethod("getContainer").invoke(service);  //StandardEngine[Catalina]
        Object host = Array.get(engine.getClass().getMethod("findChildren").invoke(engine), 0);  //StandardHost[Catalina]
        Object stdContext = Array.get(host.getClass().getMethod("findChildren").invoke(host), 0);  //StandardContext[Catalina]
        Object mapper = stdContext.getClass().getMethod("getMapper").invoke(stdContext);
        //just a clean up step(remove the host)
        Field f1 = mapper.getClass().getDeclaredField("context");
        f1.setAccessible(true);
        Object ct = f1.get(mapper);

        Field f2 = ct.getClass().getDeclaredField("resources");
        f2.setAccessible(true);
        Object rs = f2.get(ct);

        Field f3 = rs.getClass().getDeclaredField("dirContext");
        f3.setAccessible(true);
        Object dc = f3.get(rs);

        mapper.getClass().getMethod("removeHost",String.class).invoke(mapper, host.getClass().getMethod("getName").invoke(host));
        //add the host back with all required aliases
        switch (OsCheck.getOperatingSystemType()) {
            case Windows:
                dc.getClass().getMethod("setAliases",String.class).invoke(dc,"/img/avatars=" + winAvatarAlias);
                break;
            default:
                dc.getClass().getMethod("setAliases",String.class).invoke(dc,"/img/avatars=" + linuxAvatarAlias);
                break;
        }
        String ports = "";
        for (Object o :(Object[]) connectors ) {
            ports = ports + (Integer)o.getClass().getMethod("getPort").invoke(o) + " ";
        }
        log.info("Tomcat 7.x detected, service {}, engine {}, host {}, stdContext {}, server port: {}",
                service.getClass().getMethod("getName").invoke(service),
                engine.getClass().getMethod("getName").invoke(engine),
                host.getClass().getMethod("getName").invoke(host),
                stdContext.getClass().getMethod("getDisplayName").invoke(stdContext),
                ports);
    } catch (Exception e) {
        e.printStackTrace();
    }
}

}

于 2014-10-06T20:07:55.120 に答える
2

デバッガーでわかるように、コンテキストは Tomcat のコンテキスト オブジェクトです。org.apache.catalina.core.StandardContext

Tomcat 6 以下で次の手順を試すことができます。

    StandardEngine engine = (StandardEngine) ServerFactory.getServer().findService("Catalina").getContainer();
    StandardContext context = (StandardContext) engine.findChild(engine.getDefaultHost()).findChild(getServletContext().getContextPath());
    Mapper mapper = context.getMapper();

addHostAlias(String HostName, String alias)これで、Mapper クラスのメソッドを使用してホスト エイリアスを追加できるようになりました。

    mapper.addHostAlias(engine.getDefaultHost(), "myAlias");

Tomcat 7 のコード スニペットは次のとおりです。

    MBeanServer mBeanServer = MBeanServerFactory.findMBeanServer(null).get(0);
    ObjectName name = new ObjectName("Catalina", "type", "Server");
    Server server = (Server) mBeanServer.getAttribute(name, "managedResource");
    StandardEngine engine = (StandardEngine) server.findService("Catalina").getContainer();
    StandardContext context = (StandardContext) engine.findChild(engine.getDefaultHost()).findChild(getServletContext().getContextPath());
    Mapper mapper = context.getMapper();
    mapper.addHostAlias(engine.getDefaultHost(), "myAlias");

マッパーにホストがない場合は、以下を試してください。

    MBeanServer mBeanServer = MBeanServerFactory.findMBeanServer(null).get(0);
    ObjectName name = new ObjectName("Catalina", "type", "Server");
    Server server = (Server) mBeanServer.getAttribute(name, "managedResource");
    StandardEngine engine = (StandardEngine) server.findService("Catalina").getContainer();
    StandardContext context = (StandardContext) engine.findChild(engine.getDefaultHost()).findChild(getServletContext().getContextPath());
    Mapper mapper = context.getMapper();
    //just a clean up step(remove the host)
    mapper.removeHost(engine.getDefaultHost());
    //add the host back with all required aliases 
    mapper.addHost(engine.getDefaultHost(), new String[]{"myAlias"}, engine.getDefaultHost());

お役に立てれば!

于 2012-10-03T19:44:13.010 に答える
2

別の方法を見つけましたStandardContext.setAliases。Tomcat 7.0.30 の完全に機能するコード スニペットを以下に示します。

        MBeanServer mBeanServer = MBeanServerFactory.findMBeanServer(null).get(0);
        ObjectName name = new ObjectName("Catalina", "type", "Server");
        Server server = (Server) mBeanServer.getAttribute(name, "managedResource");
        StandardEngine engine = (StandardEngine) server.findService("Catalina").getContainer();
        StandardContext context = (StandardContext) engine.findChild(engine.getDefaultHost()).findChild(getServletContext().getContextPath());
        context.setAliases("myAlias");
        //infact aliases should be proper e.g. below 
        //context.setAliases("/aliasPath1=docBase1,/aliasPath2=docBase2");
        Mapper mapper = context.getMapper();
        mapper.removeHost(engine.getDefaultHost());
        mapper.addHost(engine.getDefaultHost(), new String[]{"myAlias"}, engine.getDefaultHost());
        mapper.addHostAlias(engine.getDefaultHost(), "myAlias");
        //infact aliases should be proper e.g. below 
        //mapper.addHostAlias(engine.getDefaultHost(), "/aliasPath1=docBase1,/aliasPath2=docBase2");

以下のデバッガーのスクリーンショットを見つけてください。

コード スニペットの実行前: ここに画像の説明を入力 ここに画像の説明を入力

コード スニペットの実行後: ここに画像の説明を入力 ここに画像の説明を入力

これがより役立つことを願っています。

于 2012-10-04T15:01:54.177 に答える
1

Khanh のアプローチに基づいて、組み込みの maven tomcat (v.7.0.62) で機能するコンテキスト リスナーを次に示します。

違い ("Catalina" の代わりに "Tomcat" があり、findService("Catalina") がない) に注意してください。このアプローチは、組み込みの Tomcat に対して機能します。Khanh とは対照的に、リフレクションの代わりに通常のメソッドを使用して BaseDirContext オブジェクトを取得しました。

最後に、StandardContext オブジェクトではなく BaseDirContext オブジェクトで setAliases() を呼び出す必要があることに注意してください。内部的には、StandardContext の setAliases() はセッターにすぎませんが、BaseDirContext の setAliases() は他の多くのことを行うため、既に実行中の tomcat が実際に新しいエイリアスを登録します。

import org.apache.catalina.Container;
import org.apache.catalina.Server;
import org.apache.catalina.Service;
import org.apache.catalina.core.StandardContext;
import org.apache.catalina.core.StandardEngine;
import org.apache.log4j.Logger;
import org.apache.naming.resources.BaseDirContext;
import org.apache.naming.resources.ProxyDirContext;

import javax.management.MBeanServer;
import javax.management.MBeanServerFactory;
import javax.management.ObjectName;
import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;

public class AliasesContextListener implements ServletContextListener {
    private static Logger log = Logger.getLogger(AliasesContextListener.class);

    @Override
    public void contextInitialized(ServletContextEvent sce) {
        try {
            String aliases = "/foo=C:\\bar";

            //get current tomcat server, engine and context objects
            MBeanServer mBeanServer = MBeanServerFactory.findMBeanServer(null).get(0);
            ObjectName name = new ObjectName("Tomcat", "type", "Server");
            Server server = (Server) mBeanServer.getAttribute(name, "managedResource");
            Service[] services = server.findServices();
            StandardEngine engine = (StandardEngine) services[0].getContainer();
            Container defaultHostContainer = engine.findChild(engine.getDefaultHost());

            ServletContext servletContext = sce.getServletContext();
            StandardContext standardContext = (StandardContext) defaultHostContainer.findChild(servletContext.getContextPath());
            ProxyDirContext proxyDirContext = (ProxyDirContext) standardContext.getResources();
            BaseDirContext baseDirContext = (BaseDirContext) proxyDirContext.getDirContext();

            //modify the aliases entry
            baseDirContext.setAliases(aliases);
        } catch (Exception e) {
            log.error("error while setting aliases in context listener", e);
        }
    }

    @Override
    public void contextDestroyed(ServletContextEvent sce) {
        //not implemented
    }
}
于 2015-07-08T16:00:34.517 に答える