web-dev-qa-db-fra.com

Obtenez le numéro de port du serveur auprès de Tomcat sans demande

Existe-t-il une API ou une configuration Tomcat disponible permettant d'indiquer à une application (probablement au démarrage) le port sur lequel elle s'exécute sans demande?

Imaginez un scénario dans lequel deux applications Web s'exécutent dans le même Tomcat et dont l'une doit faire appel à un service Web de l'autre. Nous ne voulons pas que la demande quitte Tomcat (si vous utilisez le nom du serveur Apache ou l'URL absolue, la demande sera émise, puis renvoyée et elle pourra être renvoyée à n'importe quel exemple), puis renvoyée nom de la machine mais aucun moyen d’obtenir le numéro de port. Je sais que je peux coder cette information en dur mais je ne veux pas le faire car je veux que mon fichier war soit agnostique sur le serveur d'applications. 

Je sais que nous pouvons le trouver si nous avons un HTTPServletRequest

Cela ne fonctionne que pour Tomcat 6 et ne fonctionnera pas sur Tomcat 7.

28
Teja Kantamneni

Pour tous ceux qui s'intéressent à la façon dont nous avons résolu ce problème, voici le code factice

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

Avec ça:

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

Vous obtiendrez une liste comme celle-ci:

[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

_ {Le} numéro de port du serveur n'existe pas. Il peut avoir un nombre quelconque de numéros de port. Donc, ce que vous demandez n'a pas de sens. Le numéro de port associé à une demande spécifique fait ont un sens.

2
user207421
  • Obtenir un objet MBean/JMX pour une instance de Tomcat/Server
  • Obtenir des données relatives à l'instance de serveur virtuel à partir de là

Vérifier http://svn-mirror.glassfish.org/glassfish-svn/tags/embedded-gfv3-prelude-b07/web/web-glue/src/main/Java/com/Sun/enterprise/web/WebContainer .Java pour référence

Le contenu de MBeanServer peut ensuite être exposé via divers protocoles, implémentés par les connecteurs de protocole [RMI/IIOP] ou par des adaptateurs protocole [SNMP/HTTP]. Dans ce cas, l'utilisation de l'adaptateur SNMP sera une meilleure approche afin de pouvoir placer une interruption SNMP sans connaître l'adresse IP/le port exact des autres serveurs d'applications

1
Puspendu Banerjee

Ces types de serveurs sont conçus pour pouvoir écouter des ports (presque) arbitraires et masquer ces détails aux applications contenues qu'il n'est normalement pas nécessaire de connaître.

Le seul moyen consiste à lire vous-même les fichiers de configuration. Et ont accès aux arguments de ligne de commande qui ont démarré le serveur sur lequel les fichiers de configuration peuvent avoir été remplacés. Vous devez en savoir beaucoup sur le système sur lequel vous travaillez pour que cela fonctionne. Il n'y a aucun moyen de le faire de manière portable.

Même s'il y en avait, il y a des cas où ce n'est tout simplement pas important d'être derrière un NAT, certains pare-feu, etc.

1
Allen

Vous pouvez utiliser crossContext . Mais je ne pense pas que ce soit agnostique sur le serveur d'applications.

Je partagerais une classe personnalisée, se comportant comme un registre d'applications en cours d'exécution dans la même instance de Tomcat via JNDI, comme je l'expliquais ici .

Lors du démarrage, via un événement ContextListener ou un conteneur Spring, j'obtenais le registre par le biais d'une recherche JNDI, ajoutais mon instance d'application Web avec une URL obtenue à partir du servletcontext.contextpath et, enfin, inscrivions un auditeur pour entendre d'autres applications s'enregistrer. C'est le serveur le plus agnostique auquel je peux penser.

L'obtention du port ne sera pas agnostique sur le serveur, vous devez utiliser un paramètre de contexte.

EDIT: Je suis désolé, j'ai oublié de dire que ce que j'ai décrit est de partager des objets entre contextes, mais non, vous ne pouvez pas connaître le port à moins d'utiliser une API de serveur (pas du tout agnostique).

1
mschonaker

Si vous souhaitez accéder à une application sur la même instance de serveur, omettez simplement la partie serveur de l'URL. Quelques exemples de ce que vous pouvez réaliser. Le document actuel est à http://example.com:8080/app2/doc.html

  • xxx.html devient http://example.com:8080/app2/xxx.html
  • ../xxx.html devient http://example.com:8080/xxx.html
  • ../xxx.html devient http://example.com:8080/xxx.html
  • ../foo/xxx.html devient http://example.com:8080/foo/xxx.html
  • ../../xxx.html devient http://example.com:8080/xxx.html (il n'y a pas moyen d'aller au-delà de la racine)
  • /xxx.html devient http://example.com:8080/xxx.html C'est probablement ce que vous recherchez.
  • //other.com/xxx.html devient http://example.com:8080/xxx.html Utile si vous souhaitez conserver "https:"
0
Aaron Digulla

Je ne suis pas tout à fait sûr que vous puissiez accéder au port Tomcat à partir du code de la configuration d’environnement dont vous avez besoin. Avez-vous envisagé de transférer l'URL complète du service Web en tant que paramètre/paramètre de configuration (probablement dans un fichier .properties) à l'application? 

Ainsi, vous n'auriez pas besoin de coder en dur le port et de découpler vos deux applications afin que vous puissiez techniquement avoir le service Web sur un Tomcat externe, tout en y accédant simplement en modifiant la propriété, en évitant la reconstruction du code.

0
Sarat

Auparavant, sur un grand projet distribué, la conception que j'avais utilisée consistait à faire que le service centralisé initialise plusieurs services avec l'URL (& port) du service central. 

Évidemment, cela signifie que le service central doit maintenir une liste des services (URL et port) à initialiser.

0
Ashley Walton