У меня есть приложение REST, которое использует встроенную Jetty в качестве сервера.Большинство конечных точек должны быть общедоступными (и иметь соответствующую встроенную аутентификацию), но некоторые предназначены только для внутреннего использования. Я бы хотел избежать накладных расходов на аутентификацию на них и вместо этого использовать брандмауэр для ограничения доступа:
Внешне видимые конечные точки обслуживаются через порт 10000, который внешний брандмауэр оставляет открытыми. Видимые изнутри конечные точки обслуживаются через порт 20000, который блокируется внешним межсетевым экраном.
Однако я не могу понять, как этого добиться с помощью встроенной Jetty. Я попытался создать два объекта Server
, один на порту 10000 с соответствующими зарегистрированными обработчиками сервлетов, а другой на порту 20000 с соответствующими зарегистрированными обработчиками сервлетов. Однако работает только тот экземпляр сервера, который запускается вторым; запросы к конечным точкам, размещенные первым из запущенных, дают 404 ответа.
В документации Jetty говорится о том, как это сделать с конфигурациями *. Xml , но не для встроенного экземпляра.
Есть мысли или идеи? Или есть лучший способ добиться внутренней / внешней изоляции конечных точек, которая мне нужна? Жесткое требование состоит в том, что и внутренние, и внешние конечные точки должны «работать» в одной JVM.
Оказывается, проблема была связана с использованием Guice и расширения Guice-servlets (проблемы 618 и 635 ). Запуск двух встроенных экземпляров Jetty отлично работает, как описано в ответе Джеймса Кингсбери ниже.
Guice использует фильтр (GuiceFilter), зарегистрированный в контексте сервера, для получения запросов, требующих внедрения зависимостей (DI) в области запроса, и для создания сервлетов и фильтров, требующих DI. К сожалению, он использует статический объект для управления списком связанных с ним сервлетов и фильтров.
В типичной настройке guice-servlet.jar, содержащий GuiceFilter
, включается для каждого приложения и, таким образом, загружается отдельным загрузчиком классов для каждого приложения --- и все работает нормально. Нет, это не так со встроенной Jetty, где практически все загружается системным загрузчиком классов по умолчанию.
Последний мастер (commit fbbb52dcc92e) Guice содержит обновленный GuiceFilter
с поддержкой динамической ссылки на объект FilterPipeline
(статический объект, вызывающий проблемы). К сожалению, конструктор для внедрения экземпляра FilterPipeline
является частным для пакета. Итак, чтобы использовать его, вам нужно создать класс-оболочку в пакете com.google.inject.servlet
, который предоставляет этот конструктор:
package com.google.inject.servlet;
import com.google.inject.Inject;
public class NonStaticGuiceFilter extends GuiceFilter {
/**
* Do not use. Must inject a {@link FilterPipeline} via the constructor.
*/
@SuppressWarnings("unused")
private NonStaticGuiceFilter() {
throw new IllegalStateException();
}
@Inject
public NonStaticGuiceFilter(FilterPipeline filterPipeline) {
super(filterPipeline);
}
}
Чтобы использовать этот класс, создайте экземпляр, используя инжектор с вашим ServletModule
установлен и зарегистрируйте его на своем Jetty Контекст
:
// Create the context handler
ServletContextHandler handler = new ServletContextHandler(myServer, "/context");
// Create the injector, registering your ServletModule
final Injector injector = Guice.createInjector(new MyServletModule());
// Add the Guice listener for this injector
handler.addEventListener(new GuiceServletContextListener() {
@Override
protected Injector getInjector() {
return injector;
}
});
// Filter all requests through Guice via NonStaticGuiceFilter.
// Guice will construct the FilterPipeline instance needed by
// NonStaticGuiceFilter.
handler.addFilter(
new FilterHolder(injector
.getInstance(NonStaticGuiceFilter.class)), "/*", null);