34

アプリケーション(おそらく起動時)に、要求なしで実行されているポートを通知できるTomcat APIまたは構成はありますか?

同じTomcatで実行されている2つのWebアプリケーションがあり、一方が他方からWebサービスを呼び出す必要があるシナリオを想像してみてください。リクエストがTomcatを離れて(Apacheサーバー名または絶対URLを使用する場合、リクエストは送信されて再び返され、任意のインスタンスに戻ることができます)、戻ってくることは望ましくありません。マシンの名前ですが、ポート番号を取得する方法はありません。warこの情報をハードコーディングできることはわかっていますが、ファイルをアプリケーションサーバーに依存しないよう にしたいので、これは行いたくありません。

HTTPServletRequestがあれば見つけることができることを私は知っています

これはTomcat6でのみ機能し、Tomcat7では機能しません。

4

12 に答える 12

29

これとともに:

List<String> getEndPoints() throws MalformedObjectNameException,
        NullPointerException, UnknownHostException, AttributeNotFoundException,
        InstanceNotFoundException, MBeanException, ReflectionException {
    MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
    QueryExp subQuery1 = Query.match(Query.attr("protocol"), Query.value("HTTP/1.1"));
    QueryExp subQuery2 = Query.anySubString(Query.attr("protocol"), Query.value("Http11"));
    QueryExp query = Query.or(subQuery1, subQuery2);
    Set<ObjectName> objs = mbs.queryNames(new ObjectName("*:type=Connector,*"), query);
    String hostname = InetAddress.getLocalHost().getHostName();
    InetAddress[] addresses = InetAddress.getAllByName(hostname);
    ArrayList<String> endPoints = new ArrayList<String>();
    for (Iterator<ObjectName> i = objs.iterator(); i.hasNext();) {
        ObjectName obj = i.next();
        String scheme = mbs.getAttribute(obj, "scheme").toString();
        String port = obj.getKeyProperty("port");
        for (InetAddress addr : addresses) {
            if (addr.isAnyLocalAddress() || addr.isLoopbackAddress() || 
                addr.isMulticastAddress()) {
                continue;
            }
            String host = addr.getHostAddress();
            String ep = scheme + "://" + host + ":" + port;
            endPoints.add(ep);
        }
    }
    return endPoints;
}

次のようなリストが表示されます。

[http://192.168.1.22:8080]
于 2013-07-31T13:43:00.837 に答える
24

これをどのように解決したかに興味がある人のために、ここにモックコードがあります

Server server = ServerFactory.getServer();
        Service[] services = server.findServices();
        for (Service service : services) {
            for (Connector connector : service.findConnectors()) {
                ProtocolHandler protocolHandler = connector.getProtocolHandler();
                if (protocolHandler instanceof Http11Protocol
                    || protocolHandler instanceof Http11AprProtocol
                    || protocolHandler instanceof Http11NioProtocol) {
                    serverPort = connector.getPort();
                    System.out.println("HTTP Port: " + connector.getPort());
                }
            }


        }
于 2011-07-22T18:50:04.867 に答える
7
public void getIpAddressAndPort() 
throws MalformedObjectNameException, NullPointerException,
            UnknownHostException {

        MBeanServer beanServer = ManagementFactory.getPlatformMBeanServer();

        Set<ObjectName> objectNames = beanServer.queryNames(new ObjectName("*:type=Connector,*"),
                Query.match(Query.attr("protocol"), Query.value("HTTP/1.1")));

        String host = InetAddress.getLocalHost().getHostAddress();
        String port = objectNames.iterator().next().getKeyProperty("port");

        System.out.println("IP Address of System : "+host );
        System.out.println("port of tomcat server : "+port);

    }
于 2016-08-12T09:43:03.553 に答える
2

サーバーのポート番号が存在しません。ポート番号はいくつでも持つことができます。したがって、あなたが求めていることは意味がありません。特定のリクエストに関連付けられているポート番号意味があります。

于 2010-11-18T01:08:24.390 に答える
1

これらのタイプのサーバーは、(ほぼ)任意のポートでリッスンし、通常は知る必要のない含まれているアプリケーションからこれらの詳細を隠すことができるように設計されています。

唯一の方法は、構成ファイルを自分で読み取り、構成ファイルがオーバーライドされた可能性のあるサーバーを起動したコマンドライン引数にアクセスできるようにすることです。これを機能させるには、実行しているシステムについて多くのことを知っている必要があります。移植可能にそれを行う方法はありません。

あったとしても、NATや特定のファイアウォールなどの背後にあることは問題ではない場合があります。

于 2010-11-21T20:23:55.813 に答える
1

crossContextを使用できます。しかし、それはアプリサーバーにとらわれないと思います。

ここで説明したように、JNDIを介して同じTomcatインスタンスで実行中のアプリケーションのレジストリとして動作するカスタムクラスを共有します。

起動時、ContextListenerまたはSpringコンテナイベントを介して、JNDIルックアップを介してレジストリを取得し、servletcontext.contextpathから取得したURLを使用してWebアプリインスタンスを追加し、最後にリスナーを登録して、他のアプリケーションが自分自身を登録するのを聞きます。それは私が考えることができるよりサーバーにとらわれないものです。

ポートの取得はサーバーに依存しないため、コンテキストパラメーターを使用する必要があります。

編集:申し訳ありませんが、私が説明したのはコンテキスト間でオブジェクトを共有することであると言うのを忘れましたが、サーバーAPIを使用しない限り(まったく不可知論ではありません)、ポートを知ることはできません。

于 2010-10-07T23:09:59.367 に答える
1
  • Tomcat/サーバーインスタンスのMBean/JMXオブジェクトを取得する
  • そこから仮想サーバーインスタンス関連データを取得する

http://svn-mirror.glassfish.org/glassfish-svn/tags/embedded-gfv3-prelude-b07/web/web-glue/src/main/java/com/sun/enterprise/web/WebContainer.javaを確認してください参考のために

MBeanServerのコンテンツは、プロトコルコネクタ[RMI/IIOP]またはプロトコルアダプタ[SNMP/HTTP]によって実装された、さまざまなプロトコルを介して公開できます。この場合、SNMPアダプターを使用する方が適切なアプローチであるため、他のアプリケーションサーバーの正確なIP/ポートを知らなくてもSNMPトラップを配置できます。

于 2010-11-18T17:43:44.057 に答える
1
public String getPort() {
    MBeanServer beanServer = ManagementFactory.getPlatformMBeanServer();
    Set<ObjectName> objectNames;
    try {
        objectNames = beanServer.queryNames(new ObjectName("*:type=ProtocolHandler,*"),
                Query.match(Query.attr("name"), Query.value("\"http-*")));
    } catch (MalformedObjectNameException e) {
        LOGGER.error("Port not defined!", e);
    }

    return objectNames.iterator().next().getKeyProperty("port");
}

public String getSecurePort() {
    MBeanServer beanServer = ManagementFactory.getPlatformMBeanServer();
    Set<ObjectName> objectNames;
    try {
        objectNames = beanServer.queryNames(new ObjectName("*:type=ProtocolHandler,*"),
                Query.match(Query.attr("name"), Query.value("\"https-*")));
    } catch (MalformedObjectNameException e) {
        LOGGER.error("SecuredPort not defined!", e);
    }

    return objectNames.iterator().next().getKeyProperty("port");
}
于 2019-05-17T08:14:46.163 に答える
0

必要な環境構成のコードからTomcatポートにアクセスできるかどうかは完全にはわかりません。Webサービスへの完全なURLを構成パラメーター/設定(おそらく.propertiesファイル内)としてアプリに渡すことを実際に検討しましたか?

このように、ポートをハードコーディングして両方のアプリを切り離す必要がないため、技術的には外部のTomcatでWebサービスを利用できますが、コードの再構築を避けて、プロパティを変更するだけでアクセスできます。

于 2010-10-05T21:22:58.950 に答える
0

以前、大規模な分散プロジェクトで使用した設計は、集中型サービスが中央サービスのURL(&ポート)を使用していくつかのサービスを初期化することでした。

明らかに、これは、中央サービスが初期化するサービス(URLとポート)のリストを維持する必要があることを意味します。

于 2010-11-16T11:46:46.677 に答える
0

同じサーバーインスタンス上のアプリケーションにアクセスする場合は、URLのサーバー部分を省略してください。あなたが達成できるいくつかの例。現在のドキュメントはにありますhttp://example.com:8080/app2/doc.html

  • xxx.htmlになりますhttp://example.com:8080/app2/xxx.html
  • ../xxx.htmlになりますhttp://example.com:8080/xxx.html
  • ../xxx.htmlになりますhttp://example.com:8080/xxx.html
  • ../foo/xxx.htmlになりますhttp://example.com:8080/foo/xxx.html
  • ../../xxx.htmlになりますhttp://example.com:8080/xxx.html(ルートを超える方法はありません)
  • /xxx.htmlこれはhttp://example.com:8080/xxx.html おそらくあなたが探しているものです。
  • //other.com/xxx.htmlhttp://example.com:8080/xxx.html「https:」を保持したい場合に便利になります
于 2010-11-19T14:16:00.317 に答える
-1

うーん、アプリケーションはリクエストなしでTomcatでどのように開始されますか?ここで一瞬頭がおかしくなるかもしれませんが、リクエストがヒットするまでクラスはロードされないと思います。もちろん、特定のリクエストから独立したクラスを持つこともできますが、ある時点でクラスを解雇するにはリクエストが必要になります。

于 2010-10-05T20:42:37.333 に答える