Получить номер порта сервера от tomcat без запроса

есть ли какой-либо API Tomcat или конфигурация, которая может сказать приложению (возможно, при запуске), какой порт работает без запроса?

представьте себе сценарий, в котором есть два веб-приложения, запущенные в одном Tomcat, и одно из которых должно вызвать веб-службу из другого. Мы не хотим, чтобы запрос покидал Tomcat (если вы используете имя сервера Apache или абсолютный URL-адрес, запрос выйдет и вернется снова, и он может перейти в любой экземпляр) и вернуться. Для этого я знаю имя машины, но не могу получить номер порта. Я знаю, что могу жестко закодировать эту информацию, но я не хочу делать это, как я хочу мой war файл будет агностиком сервера приложений.

Я знаю, что мы можем найти его если у нас есть HTTPServletRequest

это работает только для Tomcat 6 и не будет работать на Tomcat 7

11 ответов


С этого:

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]

для всех, кто заинтересован в том, как мы решили это, вот макет кода

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


        }

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

    }

на номер порта сервера не существует. Он может иметь любое количество портов. То, о чем ты просишь, не имеет смысла. на номер порта, связанный с конкретной просьбой тут смысла.


  • получить объект MBean/JMX для экземпляра Tomcat / Server
  • получить данные, связанные с экземпляром виртуального сервера оттуда

проверить 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-адаптера будет лучшим подходом, так что SNMP trap можно разместить, не зная точного IP / порта других серверов приложений


эти типы серверов разработаны, чтобы иметь возможность прослушивать (почти) произвольные порты и скрывать эти данные от содержащихся приложений, которые обычно не нужно знать.

единственный способ-прочитать файлы конфигурации самостоятельно и иметь доступ к аргументам командной строки, запустил сервер, где файлы конфигурации могут быть переопределены. Вы должны много знать о системе, в которой вы работаете, чтобы это работало. Это невозможно. делать это сносно.

даже если бы были, есть случаи, когда это просто не имеет значения, как быть за NAT, определенные брандмауэры и т. д.


можно использовать crossContext. Но я не думаю, что это агностик сервера приложений.

Я бы поделился пользовательским классом, действуя как реестр запущенных приложений в том же экземпляре tomcat через JNDI, как я объяснил здесь.

во время запуска, через ContextListener или через событие Spring container я бы получил реестр через поиск JNDI, добавьте мой экземпляр веб-приложения с url-адресом, полученным из servletcontext.самом contextpath, и, наконец, зарегистрировать слушателя, чтобы услышать другие приложения, регистрирующие себя. Это больше серверный агностик, который я могу придумать.

получение порта не зависит от сервера, вы должны использовать параметр контекста.

EDIT: извините, забыл сказать, что то, что я описал, - это совместное использование объектов среди контекстов, но нет, вы не можете не знать порт, если вы не используете какой-то серверный API (не агностик вообще).


Я не совсем уверен, что вы можете получить доступ к порту Tomcat из кода в конфигурации среды, которая вам нужна. Рассматривали ли вы на самом деле полный URL-адрес веб-службы, переданный как параметр/параметр конфигурации (возможно, в a .файл свойств) в приложение?

таким образом, вам не придется жестко кодировать порт и де-пару обоих ваших приложений, чтобы вы могли технически иметь веб-службу на внешнем tomcat, но все равно получить к нему доступ, просто изменив свойство, избегая перестройка кода.


ранее в большом распределенном проекте я использовал дизайн, чтобы централизованная служба инициализировала несколько служб с URL-адресом Центральной службы (&port).

очевидно, это означает, что Центральная служба должна поддерживать список служб (URL & port) для инициализации.


если вы хотите получить доступ к приложению на том же экземпляре сервера, просто опустить серверную часть 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.html становится http://example.com:8080/xxx.html полезно, если вы хотите сохранить " https:"

Хм, как приложение будет запускаться в Tomcat без запроса? Может быть, у меня на мгновение отключится мозг, но я не думаю, что какие-либо занятия будут загружаться, пока не поступит запрос. Конечно, у вас могут быть классы, независимые от любого конкретного запроса, но им понадобится запрос, чтобы их уволили в какой-то момент.