среда, 24 августа 2016 г.

Spring DI для servlet контейнера

Существует вероятность того, что потребуется в существующее приложение на сервлетах добавить допустим REST.
Реализаций REST несколько, наиболее популярные Spring MVC и Jersey. Spring нам дает в придачу механизм DI, что невероятно удобно.

Но нельзя так просто прикрутить REST. Дело в том, что скорее всего вам захочется предоставить REST данные используя уже написанный код. Популярной техникой является создание простого REST контроллера, который использует какой-то внутренний сервис для получения данных. А если этих сервисов много надо заиспользовать в одном REST контроллере, то тогда хорошо бы эти сервисы объединить под одним фасадом. Это нужно для того чтобы соблюдался single responsobility принцип.

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

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

Вот так можно в сервлете написать

public class MyServlet extends HttpServlet { private static final long serialVersionUID = 1L; @Autowired(required = true) //@Qualifier("SettingsService") private SettingsService settingsService; public void init(ServletConfig config) { try { super.init(config); } catch (ServletException e) { e.printStackTrace(); } SpringBeanAutowiringSupport.processInjectionBasedOnServletContext(this, config.getServletContext()); } ... Нужно еще порядок загрузки поменять в web.xml. Сначала нужно инициализировать контекст спринга, а потом контекст сервлетов