Получить номер порта сервера от tomcat без запроса - PullRequest
30 голосов
/ 05 октября 2010

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

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

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

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

Ответы [ 12 ]

26 голосов
/ 31 июля 2013

При этом:

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]
21 голосов
/ 22 июля 2011

Для всех, кто интересуется, как мы решили это, вот пробный код

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


        }
4 голосов
/ 12 августа 2016
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);

    }
2 голосов
/ 18 ноября 2010

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

1 голос
/ 21 ноября 2010

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

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

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

1 голос
/ 18 ноября 2010
  • Получение объекта 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 может быть размещена без знания точного IP-адреса / порта других серверов приложений

1 голос
/ 08 октября 2010

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

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

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

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

РЕДАКТИРОВАТЬ: извините, забыл сказать, чтоя описал разделение объектов между контекстами, но нет, вы не можете знать порт, если не используете какой-либо серверный API (вообще не агностик).

0 голосов
/ 17 мая 2019
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 голосов
/ 19 ноября 2010

Если вы хотите получить доступ к приложению на том же экземпляре сервера, просто пропустите серверную часть URL.Несколько примеров того, чего вы можете достичь.Текущий документ: http://example.com:8080/app2/doc.html

0 голосов
/ 16 ноября 2010

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

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

...