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.
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());
}
}
}
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]
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);
}
_ {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.
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.
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.
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).
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:"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.
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.