Как встроить Jetty в Spring и заставить его использовать тот же AppContext, в который он был встроен?

У меня есть Spring ApplicationContext, где я объявляю компонент сервера Jetty и запускаю его. Внутри Jetty у меня есть DispatcherServlet и пара контроллеров. Как сделать, чтобы DispatcherServlet и его контроллеры использовали bean-компоненты из того же ApplicationContext, где объявлен Jetty?

На самом деле, в этом внешнем контексте у меня есть пара демоноподобных bean-компонентов и их зависимостей. Контроллеры внутри Jetty используют одни и те же зависимости, поэтому я хотел бы избежать их дублирования внутри и снаружи Jetty.


person Fixpoint    schedule 02.07.2010    source источник


Ответы (1)


Я сделал это некоторое время назад.

В документации Spring предлагается использовать ContextLoaderListener для загрузки контекста приложения для сервлетов. Вместо этого класса Spring используйте свой собственный слушатель. Ключевым моментом здесь является то, что ваш собственный прослушиватель может быть определен в конфигурации Spring и может знать контекст приложения, в котором он определен; поэтому вместо загрузки нового контекста приложения он просто возвращает этот контекст.

Слушатель будет выглядеть примерно так:

public class CustomContextLoaderListener extends ContextLoaderListener implements BeanFactoryAware {

    @Override
    protected ContextLoader createContextLoader() {
        return new DelegatingContextLoader(beanFactory);
    }

    protected BeanFactory beanFactory;

    @Override
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
       this.beanFactory = beanFactory;
    }

}

и DelegatingContextLoader делает это:

public class DelegatingContextLoader extends ContextLoader {

    protected BeanFactory beanFactory;

    public DelegatingContextLoader(BeanFactory beanFactory) {
        this.beanFactory = beanFactory;
    }

    @Override
    protected WebApplicationContext createWebApplicationContext(ServletContext servletContext, ApplicationContext parent) throws BeansException {
        return new GenericWebApplicationContext((DefaultListableBeanFactory) beanFactory);
    }

}

Это немного грязно, и, вероятно, его можно улучшить, но это сработало для меня.

person Richard Fearn    schedule 02.07.2010
comment
Спасибо! После некоторых модификаций я решил свою проблему. С этим решением я получил исключение ApplicationEventMulticaster not initialized, потому что этот GWAC не был обновлен, но когда я вызвал на нем refresh(), я получил исключение о том, что постпроцессоры вызываются во второй раз. Поэтому вместо использования GWAC я создал класс WrapperWebApplicationContext, который делегировал все вызовы ApplicationContext, переданные в конструкторе. Теперь он работает отлично. Кроме того, я переопределил createWebApplicationContext из ContextLoaderListener - таким образом, нет необходимости использовать класс ContextLoader. - person Fixpoint; 02.07.2010
comment
В порядке. Я в тупике. Как заставить контейнер сервлета использовать bean-компонент Listener, который вы определили в конфигурации spring, вместо создания нового экземпляра, который ничего не знает о applicationContext/beanFactory? - person CupawnTae; 27.06.2013