Получить порт сервера при запуске контейнера сервлетов (независимо от сервера)

Я хочу восстановить хост и порт сервера, на котором работает мой контейнер Jersey 2.6. Контейнер в настоящее время развернут на Tomcat 7. Однако я вынужден выпустить свое приложение, которое можно развернуть на каждом сервере, поддерживающем сервлеты Java. В данном случае это Tomcat, но решение должно быть независимым от сервера.

Я зарегистрировал класс запуска Джерси, где я хочу получить хост и порт. Однако я еще не нашел решения для получения порта.

Мой класс, который вызывается при инициализации моего сервлета из Джерси:

public class ServletInitialization extends ResourceConfig {
    public ServletInitialization() {
        int port    = ???;
        String host = InetAddress.getLocalHost().getHostName();
    }
}

В своих исследованиях я нашел вопрос трехлетней давности, относящийся к той же проблеме. Принятый ответ ориентирован на кота, и я думаю, что он будет правильно работать только на коте (import org.apache.catalina.*). Я бы не хотел изменять серверный движок, конфигурацию сервера и ничего не вводить в сервер при запуске.

Я попытался использовать простой сервлет Java, но не могу найти способ получить порт и там:

public class ServletInitializationPlain extends HttpServlet {

    @Override
    public void init() {
       int port = ???;  
    }   
}

Кто-нибудь знает, как получить порт из контейнера сервлета при запуске (независимо от сервера, на котором он работает)?


ИЗМЕНИТЬ

Я принял решение Steohans, но я думаю, что это довольно сложно, почему моя ServletInitialization не вызывается при запуске веб-контейнера. Потому что на самом деле ResourceConfig не является сервлетом. Я объясню этот вопрос сейчас:

Я расширил ResourceConfig.class, который является подклассом Application.class. Этот класс приложения не является расширенным сервлетом Java, а является собственным классом Джерси. Хотя приложение вызывается при запуске веб-контейнера. Однако в спецификации Джерси можно прочитать, что класс приложения должен сам обрабатываться ServletContainer.class, который является подклассом сервлета Java. Эта обработка определена в файле web.xml. И, в конце концов, здесь все является сервлетом.

Поскольку невозможно получить порт при запуске, это, конечно, возможно при отправке запроса:

@Path("example")
public class ServletMethods {
    @GET
    public Response example(@HeaderParam("Host") String host) {
         return Response.ok(host).build();
    }
}

person Peter Merkert    schedule 04.04.2014    source источник


Ответы (2)


Преамбула. Обязательно проводите различие между веб-контейнером (также называемым контейнером сервлетов) и т.д. Кот. И класс Jersey ServletContainer, который является просто сервлетом. (см. javadoc)

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

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

У вашего веб-контейнера есть задача организовать прослушивание, и ему даже не нужно справляться с этим самостоятельно. Например, вы также можете использовать apache для прослушивания запросов, передавая их tomcat, который вызывает ваш сервлет. Также ваш веб-контейнер вообще не должен слушать, когда вызывается ваша функция инициализации.

Вы также можете указать tomcat прослушивать два разных порта, передавая запросы одному и тому же сервлету. Посмотрите это руководство по коннекторам tomcat, если вы хотите узнать больше об этом.

Однако, как только у вас есть запрос, вы знаете, какой порт использовался, и вы можете использовать getLocalPort() из своего HttpServletRequest, чтобы получить порт.

person Steohan    schedule 04.04.2014
comment
Что вы имеете в виду, когда apache прослушивает запросы, передавая их tomcat? - person Peter Merkert; 06.04.2014

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

List<String> getEndPoints() throws MalformedObjectNameException,
        NullPointerException, UnknownHostException, AttributeNotFoundException,
        InstanceNotFoundException, MBeanException, ReflectionException {
    MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
    Set<ObjectName> objs = mbs.queryNames(new ObjectName("*:type=Connector,*"),
            Query.match(Query.attr("protocol"), Query.value("HTTP/1.1")));
    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) {
            String host = addr.getHostAddress();
            String ep = scheme + "://" + host + ":" + port;
            endPoints.add(ep);
        }
    }
    return endPoints;
}

К сожалению, это работает только для tomcat

person Victor Cruz    schedule 05.01.2015