it-swarm.com.de

Rufen Sie die Server-Portnummer ohne Anforderung von Tomcat ab

Gibt es eine Tomcat-API oder -Konfiguration, die einer Anwendung mitteilen kann (wahrscheinlich beim Start), auf welchem ​​Port sie ohne Anforderung ausgeführt wird?

Stellen Sie sich ein Szenario vor, in dem zwei Webanwendungen in demselben Tomcat ausgeführt werden und eine davon einen Webdienst vom anderen aufrufen muss. Wir möchten nicht, dass die Anfrage den Tomcat verlässt (wenn Sie den Apache-Servernamen oder die absolute URL verwenden, wird die Anfrage ausgehen und wieder zurückkehren, und sie kann zu jeder beliebigen Instanz gelangen) Name der Maschine, aber keine Möglichkeit, die Portnummer abzurufen. Ich weiß, dass ich diese Informationen hart codieren kann, aber ich möchte dies nicht tun, da meine war-Datei Anwendungsserver-agnostisch sein soll. 

Ich weiß, dass wir es finden können, wenn wir ein HTTPServletRequest haben

Dies funktioniert nur für Tomcat 6 und nicht für Tomcat 7

28
Teja Kantamneni

Für jeden, der daran interessiert ist, wie wir das gelöst haben, hier der Mock-Code

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());
                }
            }


        }
20
Teja Kantamneni

Mit diesem:

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;
}

Sie erhalten eine Liste wie diese:

[http://192.168.1.22:8080]
24
ggrandes
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);

    }
3
Arun Maharana

Die Portnummer des Servers ist nicht vorhanden. Es kann eine beliebige Anzahl von Portnummern haben. Also, was Sie fragen, macht keinen Sinn. Die Portnummer, die einer bestimmten Anforderung zugeordnet ist. Do ist sinnvoll.

2
user207421
  • Holen Sie sich MBean/JMX-Objekt für die Tomcat/Server-Instanz
  • Rufen Sie von dort aus die mit der virtuellen Serverinstanz verbundenen Daten ab

Überprüfen Sie http://svn-mirror.glassfish.org/glassfish-svn/tags/embedded-gfv3-prelude-b07/web/web-glue/src/main/Java/com/Sun/enterprise/web/WebContainer .Java als Referenz

Der Inhalt des MBeanServers kann dann über verschiedene -Protokolle verfügbar gemacht werden, die durch Protokoll-Konnektoren [RMI/IIOP] oder Protokoll-Adapter [SNMP/HTTP] implementiert werden. In diesem Fall ist die Verwendung eines SNMP-Adapters der bessere Weg, um einen SNMP-Trap zu platzieren, ohne die genaue IP/den Port anderer Anwendungsserver zu kennen. 

1

Diese Arten von Servern können (fast) beliebige Ports überwachen und diese Details vor den enthaltenen Anwendungen verbergen, die normalerweise nicht bekannt sein müssen.

Die einzige Möglichkeit ist, die Konfigurationsdateien selbst zu lesen. Und haben Zugriff auf die Befehlszeilenargumente, mit denen der Server gestartet wurde, auf dem die Konfigurationsdateien möglicherweise überschrieben wurden. Damit dies funktioniert, müssen Sie viel über das System wissen, auf dem Sie laufen. Es gibt keine Möglichkeit, dies tragbar zu machen.

Selbst wenn es so wäre, gibt es Fälle, in denen es einfach egal ist, wie hinter einem NAT zu sein, bestimmte Firewalls usw.

1
Allen

Sie könnten crossContext verwenden. Aber ich denke nicht, dass das App Server agnostisch ist.

Ich würde eine benutzerdefinierte Klasse freigeben, die sich wie eine Registrierung der Ausführung von Anwendungen in derselben Tomcat-Instanz über JNDI verhält, wie ich hier erklärte.

Während des Startvorgangs, über eine ContextListener- oder über ein Spring-Containerereignis, würde ich die Registrierung über eine JNDI-Suche abrufen, meine Webanwendungsinstanz mit einer aus dem Servletcontext.contextpath abgerufenen URL hinzufügen und schließlich einen Listener registrieren, um andere Anwendungen zu hören, die sich registrieren. Das ist der Server-Agnostiker, den ich mir vorstellen kann.

Das Abrufen des Ports ist nicht serverunabhängig. Sie sollten einen Kontextparameter verwenden.

BEARBEITEN: Es tut mir leid, ich habe vergessen zu sagen, dass das, was ich beschrieben habe, Objekte zwischen Kontexten gemeinsam genutzt wird, aber nein, Sie können den Port nicht kennen, es sei denn, Sie verwenden eine Server-API (überhaupt keine Agnostik).

1
mschonaker

Wenn Sie auf eine Anwendung in derselben Serverinstanz zugreifen möchten, lassen Sie den Serverteil der URL einfach weg. Einige Beispiele, was Sie erreichen können. Das aktuelle Dokument befindet sich unter http://example.com:8080/app2/doc.html

  • xxx.html wird http://example.com:8080/app2/xxx.html
  • ../xxx.html wird http://example.com:8080/xxx.html
  • ../xxx.html wird http://example.com:8080/xxx.html
  • ../foo/xxx.html wird http://example.com:8080/foo/xxx.html
  • ../../xxx.html wird zu http://example.com:8080/xxx.html (es gibt keine Möglichkeit, über die Wurzel zu gehen)
  • /xxx.html wird http://example.com:8080/xxx.html Dies ist wahrscheinlich das, wonach Sie suchen.
  • //other.com/xxx.html wird http://example.com:8080/xxx.html Nützlich, wenn Sie "https:" beibehalten möchten.
0
Aaron Digulla
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");
}
0
Sergey I

Ich bin mir nicht ganz sicher, ob Sie vom Code in der gewünschten Umgebungskonfiguration auf den Tomcat-Port zugreifen können. Haben Sie in Erwägung gezogen, tatsächlich die vollständige URL des Web-Service als Konfigurationsparameter/-einstellung (wahrscheinlich in einer .properties-Datei) an die App übergeben zu haben? 

Auf diese Weise müssten Sie den Port nicht hardcodieren und beide Anwendungen entkoppeln, sodass Sie den Web-Service technisch auf einem externen Tomcat installieren können, aber trotzdem auf den Port zugreifen können, indem Sie einfach die Eigenschaft ändern und den Code nicht neu erstellen.

0
Sarat

Zuvor hatte ich bei einem großen verteilten Projekt das Design verwendet, das der zentralisierte Dienst die verschiedenen Dienste mit der URL (& port) des zentralen Dienstes initialisiert. 

Dies bedeutet natürlich, dass der zentrale Dienst eine Liste der Dienste (URL und Port) zur Initialisierung führen muss.

0
Ashley Walton