Вопрос-ответ

Design Patterns web based applications [closed]

Шаблоны проектирования веб-приложений

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

На самом деле, у меня на домашней странице есть несколько объектов, и для каждого из них у нас есть несколько опций, таких как добавление, редактирование и удаление. Ранее я использовал по одному сервлету на параметры, такие как Servlet1 для добавления entity1, Servlet2 для редактирования entity1 и так далее, и таким образом у нас получилось большое количество сервлетов.

Теперь мы меняем наш дизайн. Мой вопрос в том, как именно вы выбираете ответственность сервлета. Должны ли у нас быть по одному сервлету на объект, который будет обрабатывать все свои параметры и пересылать запрос на уровень обслуживания. Или у нас должен быть один сервлет для всей страницы, который будет обрабатывать запрос всей страницы, а затем пересылать его на соответствующий уровень обслуживания? Кроме того, должен ли объект запроса перенаправляться на уровень обслуживания или нет.

Переведено автоматически
Ответ 1

Немного приличное веб-приложение состоит из сочетания шаблонов проектирования. Я упомяну только самые важные из них.


Шаблон контроллера представления модели

Основной (архитектурный) шаблон проектирования, который вы хотели бы использовать, - это шаблон Model-View-Controller. Контроллер должен быть представлен сервлетом, который (в) напрямую создает / использует определенную модель и представление на основе запроса. Модель должна быть представлена классами Javabean. Часто это можно разделить на бизнес-модель, которая содержит действия (поведение), и модель данных, которая содержит данные (информацию). Представление должно быть представлено файлами JSP, которые имеют прямой доступ к модели (Данных) с помощью EL (языка выражений).

Кроме того, существуют варианты, основанные на способах обработки действий и событий. Популярными из них являются:


  • MVC на основе запросов (действий): это самый простой в реализации. (бизнес) модель работает непосредственно с HttpServletRequest и HttpServletResponse объектами. Вы должны собирать, преобразовывать и проверять параметры запроса (в основном) самостоятельно. Представление может быть представлено простым ванильным HTML / CSS / JS, и оно не поддерживает состояние между запросами. Именно так, среди прочих, работают Spring MVC, Struts и Stripes.



  • Компонентный MVC: это сложнее реализовать. Но в итоге вы получаете более простую модель и представление, в которых полностью абстрагируются все "необработанные" API сервлетов. Вам не нужно будет самостоятельно собирать, преобразовывать и проверять параметры запроса. Контроллер выполняет эту задачу и устанавливает собранные, преобразованные и проверенные параметры запроса в модели. Все, что вам нужно сделать, это определить методы действий, которые работают непосредственно со свойствами модели. Представление представлено "компонентами" в виде тегов JSP или XML-элементов, которые, в свою очередь, генерируют HTML / CSS / JS. Состояние представления для последующих запросов сохраняется в сеансе. Это особенно полезно для событий преобразования, проверки и изменения значений на стороне сервера. Именно так, среди прочих, работают JSF, Wicket и Play! .



В качестве дополнительного примечания, знакомство с доморощенным фреймворком MVC - очень приятное учебное упражнение, и я действительно рекомендую его, если вы сохраняете его для личных целей. Но как только вы станете профессионалом, настоятельно рекомендуется выбрать существующий фреймворк, а не изобретать свой собственный. Изучение существующего и хорошо разработанного фреймворка занимает в долгосрочной перспективе меньше времени, чем самостоятельная разработка и обслуживание надежного фреймворка.

В приведенном ниже подробном объяснении я ограничусь MVC на основе запросов, поскольку это проще реализовать.


Шаблон фронтального контроллера (Шаблон посредника)

Во-первых, часть контроллера должна реализовывать шаблон Front Controller (который является специализированным видом шаблона посредника). Он должен состоять только из одного сервлета, который обеспечивает централизованную точку входа всех запросов. Он должен создавать модель на основе информации, доступной по запросу, такой как pathinfo или servletpath, метод и / или конкретные параметры. Бизнес-модель называется 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 Следует следовать шаблону стратегии. Его необходимо определить как абстрактный / интерфейсный тип, который должен выполнять работу на основе переданных аргументов абстрактного метода (в этом разница с шаблоном команд, в котором абстрактный / интерфейсный тип должен выполнять работу на основе аргументов, которые были переданы во время создания реализации).

public interface Action {
public String execute(HttpServletRequest request, HttpServletResponse response) throws Exception;
}

Возможно, вы захотите сделать Exception более конкретным с помощью пользовательского исключения, подобного ActionException. Это всего лишь базовый начальный пример, остальное зависит от вас.

Вот пример LoginAction который (как следует из названия) регистрирует пользователя. User Сам по себе, в свою очередь, является моделью данных. Представление знает о присутствии 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 (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());
// ...

Или настраивается на основе файла конфигурации properties / XML в classpath: (псевдо)

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) then .


Другие шаблоны

До сих пор это были важные шаблоны.

Чтобы продвинуться дальше, вы могли бы использовать шаблон фасада для создания Context класса, который, в свою очередь, оборачивает объекты запроса и ответа и предлагает несколько удобных методов, делегирующих функции объектам запроса и ответа и передающих их в качестве аргумента в Action#execute() метод вместо этого. Это добавляет дополнительный абстрактный слой, чтобы скрыть необработанный Servlet API. В конечном итоге вы должны получить нулевые import javax.servlet.* объявления в каждой Action реализации. В терминах JSF это то, что делают классы FacesContext и ExternalContext. Вы можете найти конкретный пример в этом ответе.

Затем есть шаблон состояния для случая, когда вы хотели бы добавить дополнительный уровень абстракции, чтобы разделить задачи сбора параметров запроса, их преобразования, проверки, обновления значений модели и выполнения действий. В терминах JSF это то, что LifeCycle делает.

Затем есть составной шаблон для случая, когда вы хотите создать представление на основе компонентов, которое может быть присоединено к модели и поведение которого зависит от состояния жизненного цикла на основе запроса. В терминах JSF это то, что UIComponent представляют.

Таким образом, вы можете постепенно переходить к компонентному фреймворку.


Смотреть также:

Ответ 2

В избитом шаблоне MVC сервлет является контроллером "C".

Его основная задача - выполнить первоначальную оценку запроса, а затем отправить обработку на основе первоначальной оценки конкретному работнику. Одной из обязанностей рабочего может быть настройка некоторых компонентов уровня представления и пересылка запроса на страницу JSP для отображения HTML. Итак, только по этой причине вам необходимо передать объект запроса на уровень обслуживания.

Однако я бы не стал начинать писать необработанные Servlet классы. Работа, которую они выполняют, очень предсказуема и шаблонна, что фреймворк делает очень хорошо. К счастью, существует множество доступных, проверенных временем кандидатов ( в алфавитном порядке ): Apache Wicket, Java Server Faces, Spring и это лишь некоторые из них.

Ответ 3

ИМХО, в случае веб-приложения особой разницы нет, если смотреть на это с точки зрения распределения ответственности. Однако сохраняйте ясность на уровне. Сохраняйте на уровне представления все, что предназначено исключительно для целей презентации, например элементы управления и код, специфичный для веб-элементов управления. Просто сохраните свои объекты на бизнес-уровне, а все функции (например, добавление, редактирование, удаление) и т.д. - на бизнес-уровне. Однако их рендеринг в браузере будет выполняться на уровне представления. Для .Net шаблон ASP.NET MVC очень хорош с точки зрения разделения слоев. Ознакомьтесь с шаблоном MVC.

Ответ 4

Я использовал фреймворк struts и нахожу его довольно простым в освоении. При использовании фреймворка struts на каждой странице вашего сайта будут присутствовать следующие элементы.

1) Используемое действие вызывается каждый раз при обновлении HTML-страницы. Действие должно заполнять данные в форме при первой загрузке страницы и обрабатывать взаимодействия между веб-интерфейсом и бизнес-уровнем. Если вы используете страницу jsp для изменения изменяемого объекта java, копия объекта java должна храниться в форме, а не в оригинале, чтобы исходные данные не изменялись, пока пользователь не сохранит страницу.

2) Форма, которая используется для передачи данных между действием и страницей jsp. Этот объект должен состоять из набора средств получения и установки атрибутов, которые должны быть доступны в файле jsp. В форме также есть метод проверки данных перед их сохранением.

3) Страница jsp, которая используется для отображения окончательного HTML-кода страницы. Страница jsp представляет собой гибрид HTML и специальных тегов struts, используемых для доступа к данным в форме и манипулирования ими. Хотя struts позволяет пользователям вставлять Java-код в jsp-файлы, вам следует быть очень осторожными при выполнении этого, потому что это затрудняет чтение вашего кода. Код Java внутри файлов jsp сложно отлаживать, и его невозможно модульно протестировать. Если вы обнаружите, что пишете более 4-5 строк кода Java внутри файла jsp, код, вероятно, следует перенести в действие.

java jsp servlets