2010-10-05 8 views
27

¿Hay alguna configuración o API de Tomcat disponible que pueda indicarle a una aplicación (probablemente al inicio), en qué puerto se ejecuta sin una solicitud?Obtenga el número de puerto del servidor de tomcat sin una solicitud

Imagine un escenario en el que hay dos aplicaciones web ejecutándose en el mismo Tomcat y una de las cuales necesita invocar un servicio web desde la otra. No queremos que la solicitud abandone Tomcat (si usa el nombre del servidor Apache o la URL absoluta, la solicitud se cerrará y volverá y puede ir a cualquier instancia) y volverá a entrar. Para eso, sé el nombre de la máquina pero no forma de obtener el número de puerto. Sé que puedo codificar esta información pero no quiero hacer esto porque quiero que mi archivo war sea independiente del servidor de aplicaciones.

Sé que lo podemos encontrar si tenemos una HTTPServletRequest

Esto sólo funciona para Tomcat 6 y no funcionará en Tomcat 7

+0

No estoy seguro de por qué una aplicación necesitaría saber ut el puerto. ¿Puede proporcionar algunos detalles adicionales sobre por qué necesita esto? – David

+1

¿quieres todos los puertos disponibles o un puerto específico? Un servidor de aplicaciones puede escuchar en muchos puertos (piense en http puerto 80 y https puerto 443 como ejemplo). – Codemwnci

+0

@Codemwnci - Sí, si puedo ... –

Respuesta

20

Para cualquiera que esté interesado en la forma en que lo resolvió, aquí está el código simulacro

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


     } 
+0

Gracias por este código, parece que no puede encontrarlo en ningún lado. – woolyninja

+8

No funciona en tomcat-7 - ver http://stackoverflow.com/questions/6833947/org-apache-catalina-serverfactory-getserver-equivalent-in-tomcat-7 –

+0

ni en jboss como 7 = \ – thiagoh

-1

Hmm, ¿cómo una aplicación iniciarse en Tomcat sin una solicitud ? Tal vez estoy loco por un momento aquí, pero no creo que ninguna clase se cargue hasta que llegue una solicitud. Claro, podrías tener clases independientes de cualquier solicitud en particular, pero necesitarían una solicitud para que las despidieran en algún momento.

+1

Me refiero a cuando la aplicación se despliega en cualquier servidor de aplicaciones, habrá algunos códigos de arranque o parámetros de inicialización en servlets que hagan que la aplicación funcione y esté lista para servir solicitudes. Cuando se carga la aplicación MVC de primavera, carga toda la configuración y necesito saber el número de puerto en este proceso. Actualizaré la pregunta con más detalles. –

0

No estoy del todo seguro de poder acceder al puerto Tomcat desde el código en la configuración del entorno que necesita. ¿Consideró realmente tener la URL completa del servicio web pasado como un param/configuración de configuración (probablemente en un archivo .properties) a la aplicación?

De esta forma no tendría que codificar el puerto y desconectar las dos aplicaciones para que técnicamente pueda tener el servicio web en un tomcat externo, pero seguir accediendo simplemente cambiando la propiedad, evitando volver a compilar el código .

+0

Sí, en realidad lo consideramos, pero el problema aquí es que cada máquina tiene más de una instancia de tomcat (¿puede ser esto más complicado?) Y obviamente se ejecutan en puertos diferentes. Entonces el puerto no puede ser codificado. –

+0

¿Está diciendo que el servicio web (URL y puerto) se mueve con tanta frecuencia que pasarlo a través de una configuración no funcionará? Si es así, parece que hay un problema con la arquitectura. De lo contrario, pasarlo a través de la configuración no será difícil de codificar, siempre que sepamos (manualmente) dónde reside el servicio web (URL + puerto). – Sarat

+0

En un clúster podría haber varias instancias de tomcat y mi objetivo es redirigir la solicitud de una aplicación a otra, debe ir a la misma instancia de tomcat, no a ninguna instancia aleatoria de tomcat. –

1

Puede usar crossContext. Pero no creo que sea un servidor de aplicaciones agnóstico.

Compartía una clase personalizada, comportándome como un registro de aplicaciones en ejecución en la misma instancia de tomcat a través de JNDI, como expliqué here.

Durante el inicio, a través de un ContextListener oa través de un evento contenedor Spring, obtengo el registro a través de una búsqueda JNDI, agrego la instancia de mi aplicación web con una URL obtenida del servletcontext.contextpath y finalmente registro un oyente para escuchar otras aplicaciones que se registran. Eso es lo más agnóstico del servidor que se me ocurre.

La obtención del puerto no será independiente del servidor, debe usar un parámetro de contexto.

EDIT: Perdón, me olvidé de decir que lo que he descrito es compartir objetos entre contextos, pero no, no puede no saber el puerto a menos que use alguna API de servidor (no es para nada agnóstico) .

0

Anteriormente en un gran proyecto distribuido, el diseño que utilicé consistía en hacer que el servicio centralizado inicializara los diversos servicios con la URL del servicio central (puerto &).

Obviamente, esto significa que el servicio central debe mantener una lista de los servicios (URL & puerto) para inicializar.

1

El número de puerto del servidor no existe. Puede tener cualquier cantidad de números de puerto. Entonces, lo que estás preguntando no tiene sentido.El número de puerto asociado a una solicitud específica tiene tiene sentido.

+0

@downvoter Por favor, explique. Tengo tomcats de producción en ejecución usando cinco puertos cada uno. ¿Qué significa exactamente * el * número de puerto del servidor en dicho contexto? – EJP

1
  • hacerse con MBean Objeto/JMX para Tomcat/Servidor Instancia
  • Obtener instancia de servidor virtual datos relacionados desde allí

Comprobar http://svn-mirror.glassfish.org/glassfish-svn/tags/embedded-gfv3-prelude-b07/web/web-glue/src/main/java/com/sun/enterprise/web/WebContainer.java para referencia

El contenido de la MBeanServer puede luego se expondrá a través de varios protocolos, implementados por conectores de protocolos [RMI/IIOP] o adaptadores de protocolo [SNMP/HTTP]. En este caso, el uso del adaptador SNMP será un mejor enfoque para que se pueda colocar una trampa SNMP sin conocer la IP/puerto exacta de otros servidores de aplicación

0

Si desea acceder a una aplicación en la misma instancia de servidor , simplemente omita la parte del servidor de la URL. Algunos ejemplos de lo que puedes lograr El documento actual se encuentra en http://example.com:8080/app2/doc.html

  • xxx.html convierte http://example.com:8080/app2/xxx.html
  • ../xxx.html convierte http://example.com:8080/xxx.html
  • ../xxx.html convierte http://example.com:8080/xxx.html
  • ../foo/xxx.html convierte http://example.com:8080/foo/xxx.html
  • ../../xxx.html convierte http://example.com:8080/xxx.html (no hay manera de ir más allá de la raíz)
  • /xxx.html se convierte en http://example.com:8080/xxx.htmlEsto es probablemente lo que buscas.
  • //other.com/xxx.html convierte http://example.com:8080/xxx.html Es útil si se quiere mantener "https:"
+0

Pero la pregunta es sobre detectar el puerto de escucha. –

+1

No, la pregunta es cómo acceder a otra aplicación en el mismo servidor. –

+0

-1 Teja dijo "Sé que podemos encontrarlo si tenemos una HTTPServletRequest", y su respuesta implica una solicitud entrante. – mschonaker

1

Estos tipos de servidores están diseñados para ser capaz de escuchar en (casi) puertos arbitrarios y para ocultar estos detalles de las aplicaciones contenidas cuales normalmente no necesita saber.

La única forma es leer los archivos de configuración usted mismo y tienen acceso a los argumentos de línea de comandos que iniciaron el servidor donde los archivos de configuración pueden haber sido anulados. Debe saber mucho sobre el sistema en el que se está ejecutando para que esto funcione. No hay forma de hacerlo de forma portátil.

Incluso si hubiera, hay casos en los que simplemente no importa estar detrás de un NAT, ciertos firewalls, etc.

23

Con esta:

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

Usted obtendrá una lista como esta:

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

    } 
+1

Si bien este código puede responder a la pregunta, proporcionar un contexto adicional con respecto a * cómo * y/o * por qué * resuelve el problema mejoraría el valor de la respuesta a largo plazo. - [De la crítica] (http://stackoverflow.com/review/low-quality-posts/13317054) –

Cuestiones relacionadas