Трохи пристойний веб-додаток складається з поєднання моделей дизайну. Згадаю лише найважливіші.
Основний (архітектурний) шаблон дизайну, який ви хочете використовувати, - це модель Model-View-Controller . Контролер повинен бути представлений сервлету , який (в) безпосередньо створює / використовує конкретний модель і View на основі запиту. Модель повинні бути представлені класами JavaBeans. Це часто можна розділити в бізнес-моделі, яка містить дії (поведінка) та моделі даних, яка містить дані (інформацію). View повинен бути представлений JSP файли , які мають прямий доступ до ( Data ) Модель Е.Л. (Expression Language).
Потім існують варіанти залежно від способів обробки дій та подій. Популярними є:
MVC на основі запиту (дії) : це найпростіший спосіб реалізації. ( Бізнес ) Модель працює безпосередньо HttpServletRequest
і HttpServletResponse
об'єкти. Ви повинні зібрати, перетворити та перевірити параметри запиту (в основному) самостійно. View може бути представлений простий ванілі HTML / CSS / JS і не підтримувати стан між запитами. Так працює серед інших весняний MVC , Struts and Stripes .
MVC на основі компонентів : це важче здійснити. Але ви закінчуєте більш просту модель і вигляд, в якому всі "сирі" сервлетські API абстрагуються повністю. У вас не повинно виникати необхідності самостійно збирати, конвертувати та перевіряти параметри запиту. Контролер виконує це завдання і встановлює зібраний, перетворені і підтверджені параметри запиту в моделі . Все, що вам потрібно зробити - це визначити методи дій, які безпосередньо працюють із властивостями моделі. View представлений «компонент» в ароматі JSP або бібліотеки тегів XML елементів , які , в свою чергу , генерує HTML / CSS / JS. Стан Поглядудля наступних запитів зберігається в сесії. Це особливо корисно для подій на конвертації, валідації та зміні значення на стороні сервера. Ось як серед інших JSF , Wicket and Play! працює.
Як зауваження, захоплення навколо доморощеної рамки MVC - це дуже приємна навчальна робота, і я рекомендую її до тих пір, поки ви зберігаєте це в особистих / приватних цілях. Але після того, як ви будете професійними, настійно рекомендується вибирати існуючі рамки, а не винаходити власні. Навчання існуючих та добре розроблених рамок займає в довгостроковій перспективі менше часу, ніж самостійно розробляти та підтримувати міцні рамки.
У нижченаведеному детальному поясненні я обмежуся запитувати MVC на основі запиту, оскільки це легше здійснити.
По-перше, частина контролера повинна реалізувати схему переднього контролера (що є спеціалізованим видом шаблону посередника ). Він повинен складатися лише з одного сервлета, який забезпечує централізовану точку входу для всіх запитів. Він повинен створити Модель на основі інформації, доступної запитом, наприклад, інформація про шлях або сервлет-шлях, метод та / або конкретні параметри. Бізнес - модель називається Action
в наведеному нижче HttpServlet
прикладі.
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
try {
Action action = ActionFactory.getAction(request);
String view = action.execute(request, response);
if (view.equals(request.getPathInfo().substring(1)) {
request.getRequestDispatcher("/WEB-INF/" + view + ".jsp").forward(request, response);
}
else {
response.sendRedirect(view); // We'd like to fire redirect in case of a view change as result of the action (PRG pattern).
}
}
catch (Exception e) {
throw new ServletException("Executing action failed.", e);
}
}
Виконання дії має повернути деякий ідентифікатор, щоб знайти представлення. Найпростіше було б використовувати його як ім'я файлу JSP. Карта цього сервлета на певному url-pattern
в web.xml
, наприклад /pages/*
, *.do
або навіть просто *.html
.
У разі префіксів-моделей , як, наприклад , /pages/*
ви могли б потім викликати URL як http://example.com/pages/register , http://example.com/pages/login , і т.д. , і забезпечити /WEB-INF/register.jsp
, /WEB-INF/login.jsp
з відповідним GET і POST дій . Частини register
, login
і т.д. будуть доступні з допомогою , request.getPathInfo()
як і в наведеному вище прикладі.
Коли ви використовуєте шаблони суфіксів, наприклад *.do
, *.html
і т. Д., Тоді ви можете викликати такі URL-адреси, як http://example.com/register.do , http://example.com/login.do тощо, і вам слід змінити приклади коду в цій відповіді (також ActionFactory
), щоб замість цього витягти register
та login
частини request.getServletPath()
.
Action
Повинні дотримуватися шаблоном стратегії . Її потрібно визначити як абстрактний / тип інтерфейсу, який повинен виконувати роботу на основі переданих аргументів абстрактного методу (це різниця із шаблоном Command , де абстрактний / інтерфейсний тип повинен виконувати роботу на основі аргументи, які передаються під час створення реалізації).
public interface Action {
public String execute(HttpServletRequest request, HttpServletResponse response) throws Exception;
}
Ви можете зробити Exception
більш конкретні за допомогою спеціального винятку типу ActionException
. Це лише основний приклад, що стосується кік-коффу, все ж залежить від вас.
Ось приклад того, LoginAction
який (як випливає з його назви) реєструє у користувача. Сама User
по собі є модель даних . View відомо про присутність User
.
public class LoginAction implements Action {
public String execute(HttpServletRequest request, HttpServletResponse response) throws Exception {
String username = request.getParameter("username");
String password = request.getParameter("password");
User user = userDAO.find(username, password);
if (user != null) {
request.getSession().setAttribute("user", user); // Login user.
return "home"; // Redirect to home page.
}
else {
request.setAttribute("error", "Unknown username/password. Please retry."); // Store error message in request scope.
return "login"; // Go back to redisplay login form with error.
}
}
}
ActionFactory
Повинні дотримуватися шаблоном Фабричний метод . В основному, він повинен забезпечувати метод творчості, який повертає конкретну реалізацію абстрактного / інтерфейсного типу. У цьому випадку він повинен повернути реалізацію Action
інтерфейсу на основі інформації, наданої запитом. Наприклад, метод та інформація про шлях (pathinfo - це частина після контексту та шлях сервлетів у URL-адресі запиту, виключаючи рядок запиту).
public static Action getAction(HttpServletRequest request) {
return actions.get(request.getMethod() + request.getPathInfo());
}
Своєю actions
чергою має бути статичний / застосований у Map<String, Action>
всьому світі, який містить усі відомі дії. Ви можете вирішити, як заповнити цю карту. Жорстке кодування:
actions.put("POST/register", new RegisterAction());
actions.put("POST/login", new LoginAction());
actions.put("GET/logout", new LogoutAction());
// ...
Або конфігурується на основі файлу конфігурації властивостей / XML у класі class: (псевдо)
for (Entry entry : configuration) {
actions.put(entry.getKey(), Class.forName(entry.getValue()).newInstance());
}
Або динамічно на основі сканування класового шляху для класів, що реалізують певний інтерфейс та / або анотацію: (псевдо)
for (ClassFile classFile : classpath) {
if (classFile.isInstanceOf(Action.class)) {
actions.put(classFile.getAnnotation("mapping"), classFile.newInstance());
}
}
Майте на увазі, щоб створити "не робити нічого" Action
для випадку, коли немає відображення. Нехай, наприклад, повернеться безпосередньо request.getPathInfo().substring(1)
тодішнє.
Інші зразки
Це були важливі моделі досі.
Щоб зробити крок далі, ви можете використовувати шаблон « Фасад», щоб створити Context
клас, який, в свою чергу, обертає об’єкти запиту та відповіді та пропонує кілька зручних методів делегування об’єктам запиту та відповіді та передає це як аргумент в Action#execute()
метод. Це додає додатковий абстрактний шар, щоб приховати сирої API сервлетів. Тоді в основному ви повинні мати нульові import javax.servlet.*
декларації в кожній Action
реалізації. З точки зору JSF, саме цим FacesContext
і займаються ExternalContext
заняття. Конкретний приклад ви можете знайти в цій відповіді .
Тоді існує шаблон стану для випадку, до якого потрібно додати додатковий рівень абстракції, щоб розділити завдання збору параметрів запиту, перетворення їх, перевірки їх, оновлення значень моделі та виконання дій. З точки зору JSF, це те, що LifeCycle
робиться.
Тоді є складений шаблон для випадку, який ви хочете створити на основі компонента, який можна приєднати до моделі і поведінка якого залежить від стану життєвого циклу на основі запиту. З точки зору JSF, це те, що UIComponent
представляють.
Таким чином, ви можете еволюціонувати поступово до рамки, що базується на компонентах.
Дивись також: