Подтвердить что ты не робот

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

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

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

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

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

4b9b3361

Ответ 1

Для кого-то, кто интересуется тем, как мы это решили, вот макет кода

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


        }

Ответ 2

При этом:

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]

Ответ 3

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

    }

Ответ 4

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

Ответ 5

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

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

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

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

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

Ответ 6

  • Получить удержание объекта 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/порта других серверов приложений

Ответ 7

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

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

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

Ответ 8

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

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

Ответ 9

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

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

Ответ 10

Если вы хотите получить доступ к приложению на том же экземпляре сервера, просто опустите серверную часть 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:"

Ответ 11

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

Ответ 12

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