Давайте поділимось архітектурами веб-додатків на базі Java!
Існує безліч різних архітектур для веб-додатків, які потрібно реалізувати за допомогою Java. Відповіді на це запитання можуть слугувати бібліотекою різних дизайнів веб-додатків із їх плюсами та мінусами. Хоча я усвідомлюю, що відповіді будуть суб’єктивними, спробуємо бути максимально об'єктивними та мотивувати переліки, які ми перераховуємо.
Використовуйте рівень деталізації, який ви віддаєте перевагу для опису вашої архітектури. Щоб ваша відповідь мала будь-яку цінність, вам потрібно, принаймні, описати основні технології та ідеї, що використовуються в описуваній архітектурі. І останнє, але не менш важливе, коли ми повинні використовувати вашу архітектуру?
Почну ...
Огляд архітектури
Ми використовуємо трирівневу архітектуру, засновану на відкритих стандартах від Sun, таких як Java EE, Java Persistent API, Servlet та Java Server Pages.
- Наполегливість
- Бізнес
- Презентація
Можливі комунікаційні потоки між шарами представлені:
Persistence <-> Business <-> Presentation
Що, наприклад, означає, що презентаційний шар ніколи не викликає і не виконує операції зі збереженням, він завжди робить це через бізнес-рівень. Ця архітектура призначена для задоволення запитів веб-програми високої доступності.
Наполегливість
Виконує операції зі створення, читання, оновлення та видалення ( CRUD ) збереження. У нашому випадку ми використовуємо ( Java Persistent API ) JPA, і в даний час ми використовуємо Hibernate як наш постачальник стійкості та використовуємо його EntityManager .
Цей шар розділений на кілька класів, де кожен клас має справу з певним типом сутностей (тобто сутностей, пов’язаних із кошиком для покупок, може оброблятись одним класом стійкості) і використовується одним та лише одним менеджером .
Крім того, цей шар також зберігає об'єкти JPA, які є такими Account
, як ShoppingCart
тощо.
Бізнес
Вся логіка, пов'язана з функціональністю веб-додатків, знаходиться в цьому шарі. Ця функціональність може ініціювати переказ коштів клієнту, який хоче оплатити продукт в режимі он-лайн за допомогою своєї / його кредитної картки. Це також може бути створення нового користувача, видалення користувача або обчислення результату битви у веб-грі.
Цей шар розділений на декілька класів, і кожен з цих класів позначається, @Stateless
щоб перетворитись на сеанс без громадянства (SLSB). Кожен SLSB називається менеджером, і, наприклад, менеджер може бути класом, який позначається як згадується AccountManager
.
Коли AccountManager
потрібно виконувати операції CRUD, він здійснює відповідні виклики до екземпляра AccountManagerPersistence
, який є класом у стійкості шару. Приблизним ескізом двох методів AccountManager
може бути:
...
public void makeExpiredAccountsInactive() {
AccountManagerPersistence amp = new AccountManagerPersistence(...)
// Calls persistence layer
List<Account> expiredAccounts = amp.getAllExpiredAccounts();
for(Account account : expiredAccounts) {
this.makeAccountInactive(account)
}
}
public void makeAccountInactive(Account account) {
AccountManagerPersistence amp = new AccountManagerPersistence(...)
account.deactivate();
amp.storeUpdatedAccount(account); // Calls persistence layer
}
Ми використовуємо транзакції менеджера контейнерів, тому нам не потрібно робити розмежування транзакцій. Що в основному відбувається під кришкою, це те, що ми ініціюємо транзакцію під час введення методу SLSB та здійснюємо її (або відмовляємо) безпосередньо перед виходом із методу. Це приклад домовленості щодо конфігурації, але у нас ще нічого не було, окрім за замовчуванням, Необхідно, але.
Ось як навчальний посібник Java EE 5 від Sun пояснює необхідний атрибут транзакції для Enterprise JavaBeans (EJB):
Якщо клієнт працює в рамках транзакції і використовує метод корпоративного боба, метод виконується в межах транзакції клієнта. Якщо клієнт не пов'язаний з транзакцією, контейнер починає нову транзакцію перед запуском методу.
Потрібний атрибут - це неявний атрибут транзакції для всіх методів бін підприємства, що працюють з розмежуванням транзакцій, керованих контейнерами. Зазвичай ви не встановлюєте атрибут "Обов'язковий", якщо вам не потрібно перекрити інший атрибут транзакції. Оскільки атрибути транзакцій є декларативними, їх можна легко змінити пізніше.
Презентація
Наш презентаційний шар відповідає за ... презентацію! Він відповідає за користувальницький інтерфейс і показує інформацію користувачеві, будуючи HTML-сторінки та отримуючи введення користувачів через GET та POST-запити. На даний момент ми використовуємо стару комбінацію сервертів + Java Server Pages ( JSP ).
Шар викликає методи в менеджерах бізнес-рівня для виконання операцій, запитуваних користувачем, і отримання інформації для показу на веб-сторінці. Іноді інформація, отримана від бізнес-рівня, має менш складні типи, як String
's і int
egers', а в інший час об'єкти JPA .
Плюси і мінуси архітектури
Плюси
- Маючи все, що стосується конкретного способу наполегливості в цьому шарі, це означає лише те, що ми можемо помінятися з використання JPA на щось інше, без необхідності переписувати щось на рівні бізнесу.
- Нам легко поміняти наш презентаційний шар на щось інше, і цілком ймовірно, що ми зможемо знайти щось краще.
- Дозволити контейнеру EJB керувати межами транзакцій - це приємно.
- Використовувати серверт + JPA легко (для початку), а технології широко використовуються та впроваджуються на багатьох серверах.
- Використання Java EE повинно полегшити нам створення системи високої доступності з балансуванням навантаження та відмовою . Обидва ми відчуваємо, що маємо мати.
Мінуси
- Використовуючи JPA, ви можете зберігати часто використовувані запити як іменовані запити, використовуючи
@NamedQuery
примітку до класу об'єктів JPA. Якщо ви якомога більше пов'язані зі стійкістю в класах стійкості, як і в нашій архітектурі, це розширить місця, де ви можете знайти запити щодо включення також і об'єктів JPA. Це буде складніше переглянути операції, що підтримують стійкість, і, таким чином, важче підтримувати. - У нас є структури Спільної спільної діяльності як частина нашої стійкості. Але
Account
іShoppingCart
, що не вони на насправді бізнес - об'єкти? Це робиться так, як вам потрібно торкнутися цих класів і перетворити їх на сутності, з якими JPA знає, як поводитися. - Суб'єкти JPA, які також є нашими бізнес-об'єктами, створюються як об'єкти передачі даних ( DTO ), також відомі як об'єкти цінності (VO). Це призводить до анемічної моделі домену, оскільки бізнес-об'єкти не мають власної логіки, крім методів аксесуарів. Вся логіка виконується нашими менеджерами на рівні бізнесу, що призводить до більш процедурного стилю програмування. Це не гарний об'єктно-орієнтований дизайн, але, можливо, це не проблема? (Адже орієнтація на об'єкт - не єдина парадигма програмування, яка дала результати.)
- Використання EJB та Java EE вносить трохи складності. І ми не можемо використовувати суто Tomcat (додавання мікроконтейнера EJB не є суто Tomcat).
- Проблем із використанням Сервлета + JPA є багато. Використовуйте Google для отримання додаткової інформації про ці проблеми.
- Оскільки транзакції закриваються під час виходу з бізнес-рівня, ми не можемо завантажувати будь-яку інформацію від об'єктів JPA, яка налаштована для завантаження з бази даних, коли це потрібно (використовуючи
fetch=FetchType.LAZY
) зсередини шару презентації. Це призведе до виключення. Перед поверненням сутності, що містить такі види полів, ми повинні бути обов'язково зателефонували до відповідних користувачів. Іншим варіантом є використання мови запиту на постійну підтримку Java ( JPQL ) і виконайтеFETCH JOIN
. Однак обидва ці варіанти трохи громіздкі.