Хотя наш уровень представления не основан на Struts (обычно это Spring Web MVC или JSF), мы используем Spring 3.0 + Java EE 6, в частности EJB 3.0 и JPA 2.0 для таких ситуаций.
EJB 3.0 сессионные компоненты без сохранения состояния работают отлично - они могут иметь декларативное (основанное на аннотациях) внедрение зависимостей и разграничение транзакций, или они могут сами управлять своими транзакциями, зависимостями и ресурсами, используя любой традиционный механизм. Они легко интегрируются с JPA 2.0 и достаточно просты для модульного тестирования. Основное преимущество перед чистыми компонентами Spring заключается в том, что они могут быть развернуты независимо от веб-приложения (как EJB JAR).
В интерфейсных веб-службах мы также используем Jersey / JAX-RS. Поскольку внедрение зависимостей в Jersey / JAX-RS не работает (он не использует Weld / CDI, как в остальной части Java EE), нам пришлось прибегнуть к Spring DI, чтобы «соединить» передние классы ресурсов REST с 'back-end' EJB. Хорошо, что это работает достаточно хорошо для внедрения EJB-компонентов в наши контроллеры MVC, а также может использоваться с управляемыми компонентами JSF. Кроме того, вы можете написать свои ресурсы REST-ful, используя только Spring (в любом случае есть свои плюсы и минусы, но в целом оба хорошо справляются со своей задачей).
Я знаю, что замалчивал все это, но я был бы рад поделиться более подробной информацией по запросу.
РЕДАКТИРОВАТЬ: Некоторые дополнительные сведения, согласно запросу.
Вы - первая остановка в изучении Jersey / JAX-RS - это Руководство пользователя Jersey . Есть также несколько учебных пособий / примеров, которые вы можете легко найти в сети.
Несмотря на то, что вы должны быть в состоянии упаковать ресурсы Jersey / JAX-RS в ту же WAR, что и ваши страницы Struts, мы пошли с более простой альтернативой их развертывания по отдельности.
Теперь, при развертывании на Glassfish 3.1, мы нажимаем эту ошибку, также задокументированную здесь . Суть в том, что @EJB
инъекция не работает для нас, как ожидалось.
Итак, вместо этого мы вернулись к Spring с помощью модуля jersey-spring
contrib, следуя этому примеру .
В любом случае, все остальное - стандартная Java EE 6 / EJB 3.0. Мы идентифицируем и помещаем все общие функциональные возможности в слой «обслуживания», который в значительной степени реализован как @Stateless
EJB.
Постоянство обрабатывается через JPA @Entity
s, доступ к которому осуществляется через JPA-инъекцию EntityManager
. Транзакции декларативно разграничиваются с использованием @TransactionAttribute
.
Вот краткая иллюстрация типичного служебного компонента EJB + JPA:
@Stateless
public class WidgetServiceBean implements WidgetService {
@PersistenceContext
private EntityManager em;
@Override
public List<Widget> findWidgetByName(String name) {
return em.createNamedQuery("Widget.findByName", Widget.class)
.setParam("name", name).getResultList();
}
@Override
@TransactionAttribute(TransactionAttributeType.REQUIRED)
public void removeWidgetById(int id) {
em.find(Widget.class, id).remove();
}
}
(Очевидно, не качество продукции, а просто показывает, насколько они могут быть "худыми".)
Сервисный уровень и сущности упакованы как EJB JAR, который можно развернуть отдельно и сделать доступным для всех других модулей через глобальный поиск JNDI. Или же они могут быть развернуты в Struts или JAX-RS WAR, а с Java EE 6 (Glassfish 3.x) они будут найдены, развернуты как часть модуля и предоставлены другим компонентам в рамках той же WAR.
Некоторые могут возразить, что проще использовать бины Spring, если вы все равно используете контейнер Spring. Я бы сказал, вероятно, но тогда вам также придется использовать среду персистентности Spring и среду транзакций Spring. (Spring также предоставляет декларативные транзакции и постоянство.) Если вы уже вложили значительные средства в Spring, это может быть более простой путь.
OTOH, EJB 3.0, JPA 2.0 и JTA также были радикально упрощены по сравнению со своими предшественниками и являются частью стандарта Java EE, поэтому это архитектурное решение с большим количеством измерений.