# Лабораторная 2 веб ## 1. Java-сервлеты. Особенности реализации, ключевые методы, преимущества и недостатки относительно CGI и FastCGI. __Servlet__ – в первую очередь это простой Java интерфейс, реализация которого расширяет функциональные возможности сервера. Сервлет взаимодействует с клиентами посредством принципа запрос-ответ. #### Что же такое сервлет ? В двух словах описать работу сервлета можно так: Web-сервер, который умеет работать с сервлетами, запускает Java-машину, которая в свою очередь выполняет сервлет, а сервлет отдает данные, которые он сформирует. Т.е. при приходе запроса от клиента сервер с помощью специального конфигурационного файла может определить, какой сервлет выполнить, сервлет выполняется и создает HTML-страницу, которую сервер отправляет клиенту. На сервер приходит запрос от клиента, запрос содержит внутри себя URL и параметры. Сервер имеет специальный конфигурационный файл, который ему сообщает о том, какой сервлет надо выполнить в случае прихода определенного URL. Сервлет выполняется (там вы можете использовать параметры) и создает HTML-страницу, которая отсылается клиенту. Сервер по сути является контейнером (теперь уже не визуальных компонентов), который загружает сервлеты, выполняет их, вызывая определенные методы и получив от них результат, отправляет его клиенту. Таким образом сервлет — это Java-класс, который наследуется обычно от класса • HttpServlet и переопределяет часть методов: - doGet — если мы хотим, чтобы сервлет реагировал на GET запрос. - doPost — если мы хотим, чтобы сервлет реагировал на POST запрос. - doPut, doDelete — если мы хотим, чтобы сервлет реагировал на PUT и DELETE запрос (есть и такие в HTTP). Эти методы реализуются крайне редко, т.к. сами команды тоже очень редко встречаются. - init, destroy — для управления ресурсами в момент создания сервлета и в момент его уничтожения. Если же необходимо перехватывать все команды, то проще переопределить метод __service__. Именно этот метод вызывается при приходе запроса от клиента. В HttpServlet происходит разбор запроса и в соответствии с указанной командой вызывается метод doGet, doPost и т.д. #### Важно !!! - ServletContext живет до тех пор, пока живет веб-приложение. Он является общим для всех запросов во всех сеансах. - HttpSession живет до тех пор, пока клиент взаимодействует с веб-приложением с одним и тем же экземпляром браузера, а время ожидания сеанса на стороне сервера не истекло. Он является общим для всех запросов в одном сеансе. - HttpServletRequest и HttpServletResponse живут с момента получения сервлетом запроса HTTP от клиента, пока не будет получен полный ответ (веб-страница). Он не разделяется в других местах. - Все экземпляры Servlet , Filter и Listener живут до тех пор, пока живет веб-приложение. Они являются общими для всех запросов во всех сеансах. - Любой attribute , определенный в ServletContext, HttpServletRequest и HttpSession , будет жить до тех пор, пока живет рассматриваемый объект. Сам объект представляет собой "scope" в рамках управления бобами, таких как JSF, CDI, Spring и т.д. Эти фреймворки хранят свои ограниченные бобы как attribute из своей ближайшей совпадающей области. #### Преимущества и недостатки относительно CGI и FastCGI Преимущества: - Выполняются быстрее, чем CGI-сценарии. - Хорошая масштабируемость. - Надежность и безопасность (реализованы на JAVA) - Платформенно-независимы - Множество инструментов мониторинга и отладки Недостатки: - Слабое разделение уровня представления и бизнес-логики. - Возможны конфликты при параллельной обработке запросов. ## 2. Контейнеры сервлетов. Жизненный цикл сервлета. Сервлет-контейнер поддерживает только API сервлета (включая JSP, JSTL). Сервер приложений поддерживает весь JavaEE - EJB, JMS, CDI, JTA, API сервлета (включая JSP, JSTL) и т.д. #### Жизненный цикл сервлета Для каждого сервлета движок сервлетов создает только одну копию. Вне зависимости от того, сколько запросов будет отправлено сервлету, все запросы будут обрабатываться толькой одной копией сервлета. Объект сервлета создается либо при запуске движка сервлетов, либо когда сервлет получает первый запрос. Затем для каждого запроса запускается поток, который обращается к объекту сервлета. При работе с сервлетом движок сервлетов вызывает у класса сервлета ряд методов, которые определены в родительском абстрактном классе HttpServlet. Когда движок сервлетов создает объект сервлета, у сервлета вызывается метод init(). ```java public void init(ServletConfig config) throws ServletException { } ``` Этот метод вызывается только один раз - при создании сервлета. Мы можем переопределить этот метод, чтобы определить в нем некоторую логику инициализации. Когда к сервлету приходит запрос, движок сервлетов вызывает метод service() сервлета. А этот метод, исходя из типа запроса (GET, POST, PUT и т.д.) решает, какому методу сервлета (doGet, doPost и т.д.) обрабатывать этот запрос. ```java public void service(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException{ } ``` Этот метод также можно переопределить, однако в этом нет смысла. В реальности для обработки запроса переопределяются методы onGet, onPost и т.д., которые обрабатывают конкретные типы запросов. Если объект сервлета долгое время не используется (к нему нет никаких запросов), или если происходит завершение работы движка сервлетов, то движок сервлетов выгружает из памяти все созданные экземпляры сервлетов. Однако до выгрузки сервлета из памяти у сервлета вызывается метод destroy(). ```java public void destroy() ``` При необходимости мы также можем его переопределить, например, определить в нем логику логгирования или что иное. В то же время следует учитывать, что если сервер вдруг упадет по какой-то причине, например, отключится электричество и т.д., тогда данный метод естественно не будет вызван и его логика не сработает. Поскольку для обработки всех запросов создается один экземпляр сервлета, и все обращения к нему идут в отдельных потоках, то не рекомендуется в классе сервлета объявлять и использовать глобальные переменные, так как они не будут потокобезопасными. ## 3.Диспетчеризация запросов в сервлетах. Фильтры сервлетов. #### Диспетчеризация запросов в сервлетах - Сервлеты могут делегировать обработку запросов другим ресурсам (сервлетам, JSP и HTML-страницам). - Диспетчеризация осуществляется с помощью реализаций интерфейса javax.servlet.RequestDispatcher. - Два способа получения RequestDispatcher — через ServletRequest (абсолютный или относительный URL) (RequestDispatcher view = request.getRequestDispatcher(“result.jsp”);) и ServletContext (только абсолютный URL). (RequestDispatcher reqDispObj = getServletContext().getRequestDispatcher("/ContextRoot/home.jsp");) - Два способа делегирования обработки запроса — forward и include (include используется чтобы вставить вывод другого сервлета в текущий. forward позволяет провести предварительную обработку запроса и потом полностью передать управление другому сервлету) __Отличие include от forward:__ - Assume you have two pages, pageA, and pageB. In pageA you wrote the include tag. In this case the control was in pageA til you called the include tag. At this point the full control goes to pageB. When It's done, control is returned to pageA starting from the next point of coding after the include tag and continuing to the rest of pageA. - Well, to get things much clearer, let's say that we have the same pages, pageA and pageB, but this time we will use the forward tag in pageA, not the include tag. Again, the control will begin in pageA till we call the forward tag in pageA, at this point, control is transfered to pageB, just like the include tag. But the difference is what happens when pageB completes. In case of the forward tag, control doesn't go back to pageA again. Отличие redirect от forward: - response.sendRedirect(""); используется для перенаправления ресурсов на разные серверы или домены. Эта передача задачи управления делегируется браузеру контейнером. То есть, перенаправление отправляет заголовок обратно в браузер/клиент. Этот заголовок содержит URL-адрес ресурса, который будет перенаправлен браузером. Затем браузер инициирует новый запрос к указанному URL-адресу. - request.getRequestDispathcer("login.jsp").forward(request, response); используется для пересылки ресурсов, доступных на сервере, с которых выполняется вызов. Эта передача управления осуществляется контейнером внутри, а браузер/клиент не задействован. __мы должны использовать forward() при доступе к ресурсам в том же приложении, потому что это быстрее, чем метод sendRedirect(), который требовал дополнительного сетевого вызова.__ #### Фильтры сервлетов Сервлетный фильтр занимается предварительной обработкой запроса, прежде чем тот попадает в сервлет, и/или последующей обработкой ответа, исходящего из сервлета. Сервлетные фильтры могут: - Перехватывать инициацию сервлета прежде, чем сервлет будет инициирован; - Определить содержание запроса прежде, чем сервлет будет инициирован; - Модифицировать заголовки и данные запроса, в которые упаковывается поступающий запрос; - Модифицировать заголовки и данные ответа, в которые упаковывается получаемый ответ; - Перехватывать инициацию сервлета после обращения к сервлету. Основой для формирования фильтров служит интерфейс javax.servlet.Filter, который реализует три метода: ```java <filter> <filter-name>FilterName</filter-name> <filter-class>common.FilterConnect</filter-class> <init-param> <param-name>active</param-name> <param-value>true</param-true> </init-param> </filter> <filter-mapping> <filter-name>FilterName</filter-name> <servlet-name>ServletName</servlet-name> </filter-mapping> ``` ```java void init (FilterConfig config) throws ServletException; void destroy (); void doFilter (ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException; ``` __Пример предобработки:__ ```java if (userAuthorized()) { chain.doFilter(request, response); } else { httpResponse.sendRedirect("login.jsp"); } ``` __Пример постобработки__ Чтобы манипулировать ответами от сервера, прежде чем они будут отправлены обратно клиенту. ## 5. Контекст сервлета - назначение, способы взаимодействия сервлетов с контекстом. Для доступа из сервлета к параметрам WEB-приложения необходимо использовать интерфейс javax.servlet.ServletContext. Объект ServletContext является уникальным и доступен всем сервлетам. ServletContext позволяет получить доступ к параметрам WEB-приложения, определенным в дескрипторе web.xml тегом <context-param> : getAttribute () Гибкий способ получения информации о сервере через пары атрибутов имя/значение. Зависит от сервера. GetMimeType () Возвращает тип MIME данного файла. getRealPath () Этот метод преобразует относительный или виртуальный путь в новый путь относительно месторасположения корня HTML-документов сервера. getServerInfo () Возвращает имя и версию сетевой службы, в которой исполняется сервлет. getServlet () Возвращает объект Servlet указанного имени. Полезен при доступе к службам других сервлетов. getServletNames () Возвращает список имен сервлетов, доступных в текущем пространстве имен. log () Записывает информацию в файл регистрации сервлета. Имя файла регистрации и его формат зависят от сервера. ## 6. JavaServer Pages. Особенности, преимущества и недостатки по сравнению с сервлетами, область применения. Страницы JSP — это текстовые файлы, содержащие статический HTML и JSP-элементы. - JSP-элементы позволяют формировать динамическое содержимое. - При загрузке в веб-контейнер страницы JSP транслируются компилятором (jasper) в сервлеты. - Позволяют отделить бизнес-логику от уровня представления (если их комбинировать с сервлетами). Преимущества: - Высокая производительность — транслируются в сервлеты. - Не зависят от используемой платформы — код пишется на Java. - Позволяют использовать Java API. - Простые для понимания — структура похожа на обычный HTML. Недостатки: - Трудно отлаживать, если приложение целиком основано на JSP. - Возможны конфликты при параллельной обработке нескольких запросов. ЕЩЕ!1!1! - Модификация в сервлете является трудоемкой задачей, поскольку включает в себя перезагрузку, перекомпиляцию и перезапуск сервера. В то время как модификация JSP быстрая, просто нажмите кнопку обновления. - В сервлете мы должны выполнить все, как бизнес-логику и логику представления, в одном файле сервлета. Принимая во внимание, что в JSP бизнес-логика изолирована от логики представления с помощью JavaBeans. - Сервлет может принимать любые запросы к протоколу и может переопределять метод service (). В то время как JSP получает только HTTP-запросы и не может переопределить его метод service (). - Более того, сервлет - это Java-код. Написание кода для сервлета сложнее, чем JSP, так как это HTML в Java. Принимая во внимание, что JSP - это код на основе HTML, а JSP прост в кодировании, так как это Java в HTML. - Сервлеты выполняются на веб-сервере, таком как Tomcat, а программа JSP перед выполнением компилируется в сервлет Java. Как только он скомпилирован в сервлет, его жизненный цикл будет аналогичен сервлету. Однако у JSP есть свой индивидуальный API для жизненного цикла. ## 9. Правила записи Java-кода внутри JSP. Стандартные переменные, доступные в скриптлетах и выражениях. 2 варианта синтаксиса — на базе HTML и XML. - Обозначаются тегами <% %> (HTML-вариант): <html> <%-- scripting element --%> </html> - Существует 5 типов JSP-элементов: - Комментарий — <%-- Comment --%>; Поддерживаются 3 типа комментариев: * HTML-комментарии: <!-ч- This is an HTML comment. It will show up in the response. -ч-> * JSP-комментарии: <%-- This is a JSP comment. It will only be seen in the JSP code. It will not show up in either the servlet code or the response. --%> * Java-комментарии: <% /* This is a Java comment. It will show up in the servlet code. It will not show up in the response. */ %> - Директива — <%@ directive %>; Управляют процессом трансляции страницы в сервлет. * Директива страницы (Директива страницы используется для предоставления инструкций контейнеру. Эти инструкции относятся к текущей странице JSP.) <%@ page session=”false” %> <%@ page import="java.util.ArrayList" %> <%@ page import="helpers.Point" %> <%@ page contentType="text/html;charset=UTF-8" language="java" %> (buffer, contentType, language, isThreadSafe) * Директива включения (Директива include используется для включения файла на этапе перевода. Эта директива указывает контейнеру объединять содержимое других внешних файлов с текущим JSP на этапе трансляции.) <%@ include file=”incl/copyright.html” %> Эквивалент на XML:<jsp:directive.include file="url"\>. URL должен быть относительным . Для подключения файла в процессе запроса а не в ходе трансляции используйте действие jsp:include. 1) Директива include : <%@ include file="header.html" %> Статический : добавляет содержимое из значения атрибута файла на текущую страницу во время перевода . Директива изначально предназначалась для статических шаблонов макета, таких как заголовки HTML. 2) <jsp:include> Стандартное действие : <jsp:include page="header.jsp" /> Динамический : добавляет содержимое из значения атрибута страницы на текущую страницу во время запроса . Был предназначен больше для динамического контента, поступающего из JSP. 3) <c:import>Тег JSTL: <c:import url=”http://www.example.com/foo/bar.html” /> Динамический : добавляет содержимое из значения атрибута URL на текущую страницу во время запроса . Он работает примерно так же <jsp:include>, но он более мощный и гибкий: в отличие от двух других включений, <c:import> URL-адрес может быть извне веб-контейнера ! * Директива taglib ( Библиотеки тегов-это фрагменты кода Java, которые могут использоваться в JSP, но которые соответствуют определенному API и которые выглядят как теги HTML в JSP. Файл описания библиотеки тегов (TLD) описывает имена этих тегов, какие атрибуты они могут иметь и какие классы Java реализуют их) Директива taglib имеет следующий синтаксис: <%@ taglib uri="URI включаемой библиотеки тегов" prefix="имяПрефикса" %> Префикс "имяПрефикса" используется при обращении к библиотеке. Пример использования библиотеки тегов mytags: <%@ taglib uri="http://www.taglib/mytags" prefix="customs" %> . . . <customs:myTag> - Объявление — <%! decl %>;(declarations не производят никакого вывода в стандартный выходной поток out. Переменные и методы, декларированные в объявлениях, инициализируются и становятся доступными для скриптлетов и других объявлений в момент инициализации страницы JSP.) Позволяют объявлять поля и методы: * Синтаксис: ```jsp <%! JavaClassDeclaration %> ``` * Примеры: ```jsp <%! public static final String DEFAULT_NAME = “World”; %> <%! public String getName(HttpServletRequest request) { return request.getParameter(“name”); } %> <%! int counter = 0; %> ``` - Скриптлет — <% code %>; (Позволяют задать Java-код, который будет выполняться при обработке запросов (при вызове метода _jspService).) * Синтаксис: ```jsp <% JavaCode %> ``` * Примеры: ```jsp <% int i = 0; %> <% if ( i > 10 ) %> I am a big number <% } else { %> I am a small number <% } %> ``` - Выражение — <%= expr %>. (Позволяют вывести результат вычисления выражения.) * Синтаксис: ```jsp <%= JavaExpression %> ``` * Примеры: ``` <B>Ten is <%= (2 * 5) %></B> Thank you, <I><%= name %></I>, for registering for the soccer league. The current day and time is: <%= new java.util.Date() %> ``` ### Стандартные переменные, доступные в скриптлетах и выражениях. В процессе трансляции контейнер добавляет в метод _jspService ряд объектов, которые можно использовать в скриптлетах и выражениях: - application javax.servlet.ServletContext - config javax.servlet.ServletConfig - exception java.lang.Throwable. (используется только на страницахперенаправлениях с информацией об ошибках (Error Pages).) - out javax.servlet.jsp.JspWriter - page java.lang.Object (API для доступа к экземпляру класса сервлета, в который транслируется JSP.) - PageContext javax.servlet.jsp.PageContext (PageContext — контекст JSP-страницы) - request javax.servlet.ServletRequest - response javax.servlet.ServletResponse - session javax.servlet.http.HttpSession ## Jasper Jasper -- движок JSP, который является реализацией спецификации JavaServer Pages 2.0 Sun Microsystems. Jasper анализирует JSP-файлы, чтобы компилировать их в Java-код как сервлеты (которые могут быть обработаны с помощью контейнера-сервлетов). Во время выполнения Jasper может автоматически обнаруживать изменения JSP-файла и перекомпилировать его ## 10. Bean-компоненты и их использование в JSP. JavaBeans — классы в языке Java, написанные по определённым правилам. Они используются для объединения нескольких объектов в один для удобной передачи данных. Чтобы класс мог работать как bean, он должен соответствовать определённым соглашениям об именах методов, конструкторе и поведении. Эти соглашения дают возможность создания инструментов, которые могут использовать, замещать и соединять JavaBeans. Правила описания: - Класс должен иметь конструктор без параметров, с модификатором доступа public. Такой конструктор позволяет инструментам создать объект без дополнительных сложностей с параметрами. - Свойства класса должны быть доступны через get, set и другие методы (так называемые методы доступа), которые должны подчиняться стандартному соглашению об именах. Это легко позволяет инструментам автоматически определять и обновлять содержание bean’ов. - Класс должен быть сериализуем. Это даёт возможность надёжно сохранять, хранить и восстанавливать состояние bean независимым от платформы и виртуальной машины способом. - Класс должен иметь переопределенные методы equals(), hashCode() и toString(). JavaBean – это одноуровневые объекты, использующиеся для того, чтобы инкапсулировать в одном объекте код, данные или и то и другое. Компонент JavaBean может иметь свойства, методы и события, открытые для удаленного доступа. ```jsp <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@ page import="java.util.*, java.text.*" %> <jsp:useBean id="hello" class="example.JavabeanHello" scope="page" /> <%! String getFormattedDate() { SimpleDateFormat sdf = new SimpleDateFormat("dd.MM.yyyy hh:mm:ss"); return sdf.format(new Date()); } %> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>JavaBean с JSP!</title> </head> <body> <h2>${hello.message}</h2> <i>Сегодня <%= getFormattedDate() %></i> </body> </html> ``` __Scope__ Атрибут, определяющий область видимости ссылки на экземпляр объекта JavaBean. Допустимыми значениями являются page, request, session, application. Данный атрибут фактически описывает пространство имен и цикл жизни ссылки на объект. По умолчанию значение объекта равно page. - page (страница). Объект, определенный с областью видимости page, доступен до тех пор, пока не будет отправлен ответ клиенту или пока запрос к текущей странице JSP не будет перенаправлен куда-нибудь еще. Ссылки на объект возможны только в пределах страницы, в которой этот объект определен. Объекты, объявленные с атрибутом page, сохраняются в объекте pageContext. - request (запрос). Объект, имеющий область видимости request, существует и доступен в течение текущего запроса, и остается видимым, даже если запрос перенаправляется другому ресурсу в том же самом цикле выполнения. Объекты, декларированные с атрибутом области видимости request, сохраняются в объекте request. - session (сессия). Объект, имеющий область видимости session доступен в течение текущего сеанса, если страница JSP "знает" о сеансе. - application (приложение). Объект, имеющий область видимости application доступен страницам, обрабатывающим запросы в одном и том же приложении Web, и cуществует до тех пор, пока сервер приложений поддерживает объект ServletContext. Объекты, объявленные с атрибутом области видимости application, сохраняются в объекте application. ## 11. Стандартные теги JSP. Использование Expression Language (EL) в JSP. ### Стандартные теги JSP. Стандартная библиотека тегов JSP (JavaServer Pages Standard Tag Library, JSTL) является расширением её спецификации, используемая для условной обработки, создания циклов, интернационализации страницы, разбора XML данных. JSTL является альтернативой скриплетам, встроенным в JSP, то есть прямым вставкам Java кода. JSTL представляет собой набор тегов в стиле HTML, позволяющих обращаться к объектам Java и выполнять многие из конструкций языка Java. Для подключения библиотеки тегов JSTL используются следующие выражения: ```jsp // Основные теги создания циклов, определения условий, вывода информации на страницу и т.д. <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> // Теги для работы с XML-документами <%@ taglib prefix="x" uri="http://java.sun.com/jsp/jstl/xml" %> // Теги для работы с базами данных <%@ taglib prefix="s" uri="http://java.sun.com/jsp/jstl/sql" %> // Теги для форматирования и интернационализации информации (i10n и i18n) <%@ taglib prefix="f" uri="http://java.sun.com/jsp/jstl/fmt" %> ``` __Тэг <c:out>__ Тэг <c:out> используется для вывода данных на экран. Следующий код отобразит выражение, представленное в атрибуте value. ```jsp // отображение текста 16+64*2 <c:out value="16+64*2" /> ``` __Тэг <c:set>__ Тег c:set используется для определения переменной подобно <jsp:setProperty>. Пример использования : ```jsp <c:set var="user" scope="session" value="Sergey" /> <c:out value="${user}" /> ``` __Тэг <c:remove>__ Для удаления переменной следует использовать тэг <c:remove>. ```jsp <c:remove var="user" scope="request" /> ``` __Тэг <c:if>__ Тег <c:if> серьезно отличается от того, что мы используем в других языках программирования. Он не позволяет определить ветку else или elseif. Можно только проверить некоторое условие. Пример : ```jsp <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <html> <head> <title>Пример тега <c:if> библиотеки JSTL</title> </head> <body> <c:set var="salary" scope="session" value="${23400*2}"/> <c:if test="${salary > 45000}"> <p>Salary = <c:out value="${salary}"/><p> </c:if> </body> </html> ``` ### Использование Expression Language (EL) в JSP. Expression Language или сокращенно EL предоставляет компактный синтаксис для обращения к массивам, коллекциям, объектам и их свойствам внутри страницы jsp. Он довольн прост. Вставку окрывает знак $, затем в фигурные скобки {} заключается выводимое значение: Откуда эти данные берутся? EL пытается найти значения для этих данных во всех доступных контекстах. И EL просматривает все эти контексты в следующем порядке: 1. Контекст страницы (данные сохраняются в PageContext) 2. Контекст запроса 3. Контекст сессии 4. Контекст приложения Соответственно, если контексты запроса и сессии содержат атрибут с одним и тем же именем, то будет использоваться атрибут из контекста запроса. Затем найденное значение (если оно было найдено) конвертируется в строку и выводится на страницу. ## 13. Шаблоны проектирования и архитектурные шаблоны. Использование в веб-приложениях. __Шаблон проектирования или паттерн__ — повторимая архитектурная конструкция, представляющая собой решение проблемы проектирования в рамках некоторого часто возникающего контекста (© Wikipedia). - Описывает подход к решению типовой задачи. - Одну и ту же задачу часто можно решить с использованием разных шаблонов. - Существует много литературы с описанием различных шаблонов проектирования. __Зачем нужно__ - Позволяют избежать «типовых» ошибок при разработке типовых решений. - Позволяют кратко описать подход к решению задачи; программистам, знающим шаблоны, проще обмениваться информацией. - Легче поддерживать код — его поведение более предсказуемо. __GoF-паттерны__ Описаны в книге 1994 г. «Design Patterns: Elements of Reusable Object-Oriented Software» («Приёмы объектно-ориентированного проектирования. Паттерны проектирования»). _Порождающие GoF-паттерны_ - Abstract Factory — Абстрактная фабрика. - Builder — Строитель. - Factory Method — Фабричный метод. - Prototype — Прототип. - Singleton — Одиночка. _Структурные GoF-паттерны_ - Adapter — Адаптер. - Bridge — Мост. - Composite — Компоновщик. - Decorator — Декоратор. - Facade — Фасад. - Flyweight — Приспособленец. - Proxy — Заместитель. _Поведенческие GoF-паттерны_ - Chain of responsibility — Цепочка обязанностей. - Command — Команда. - Interpreter — Интерпретатор. - Iterator — Итератор. - Mediator — Посредник. - Memento — Хранитель. - Observer — Наблюдатель. - State — Состояние. - Strategy — Стратегия. - Template — Шаблонный метод. - Visitor — Посетитель. __Архитектурные шаблоны__ - Более высокий уровень по сравнению с шаблонами проектирования. - Описывают архитектуру всей системы или приложения. - Обычно имеют дело не с отдельными классами, а с целыми компонентами или модулями. - Компоненты и модули могут быть построены с использованием различных шаблонов проектирования. ## Model 1 ![](https://i.imgur.com/0J9Mv7v.png) Исходя их того, какой набор уровней используется и каким образом они скомпонованы, исторически сложились две основных архитектуры: Model 1 and Model 2 (Model 1 была названа так только после того, как появилась Model 2). В чем мысль. Model 1 - это то, что у нас получается стихийно при разработке типичного веба в лоб. То есть в первой лабораторной работе. Model 1 ни для чего в принципе не предназначена, если вы просто механически попробуете реализовать веб-приложение без особых попыток декомпозиции компонентов на различные слои, то у вас получится Model 1. Плюс Model 1 в простоте, то есть ее можно быстро сделать. Однако при этом ее минусы: она плохо масштабируется и плохо поддерживаема большими командами разработчиков. В силу этого она нормально подходит для разработки приложений небольшого масштаба и сложности, но для сложных приложений с ней надо что-то делать. Ключевой особенностью Model 1 является то, что за обработку данных и представление отвечает один и тот же элемент архитектуры приложения (сервлет или JSP). То есть получается, что браузер формирует request, этот запрос получает какой-то компонент, компонент его обрабатывает и обратно отдает response`у - формирует его и обратно отдает. Всем этим занимается один и тот же компонент. С точки зрения доработки, поддержки и достаточного долгого жизненного цикла работать будет очень плохо. ## MVC Model-View-Controller — схема разделения данных приложения, и управляющей логики на три отдельных компонента: модель, представление и контроллер В силу проблем которые были с Model 1, сформировалась архитектура приложения, построенная на архитектуре MVC. Одной из возможных реализаций MVC является архитектура Model 2. Мысль в том, что все компоненты нашего приложения разбиваются на 3 основных группы: - контроллер - представлене - модель С точки зрения того, что из себя представляют эти компоненты: - View (представление) Занимается формированием интерфейса, описывает шаблоны интерфейса. Например, JSP или шаблонизатор, который интерфейс формирует. - Model (модель) Компоненты, которые отвечают за описание модели данных. > То есть если, например, сайт формирует какую-нибудь корзину покупателя, то структура этой корзины - наименование, общая стоимость заказов, список товаров - будет описана на уровне модели. Уровень модели также будет отвечать за вытягивание данных из уровня данных - из БД. А представление сверстает страничку из всего этого. - Controller (Контроллер) Логический уровень, который отвечает за диспетчеризацию запросов и за взаимодействие модели с представлением. То есть, когда приходит запрос из браузера, контроллер должен понять, куда этот запрос пришел, и что нужно сделать. > То есть, условно нужно сходить в модель и попросить ее выбрать данные из базы, нужно сходить в представление и попросить скомпоновать соответсвующее представление (страничку корзины покупателя, например), и связать их друг с другом. Нам в лабе нужно было реализовать веб-приложение на основе MVC и получается что * model это у нас класс AreaCheckServlet и класс Point * view это jsp страница * controller это ControllerServlet Ключевым отличием Model 1 от Model 2 является то, что за представление и обработку данных отвечают разные компоненты ## Model 2 ![](https://i.imgur.com/4UeJSJu.png) Model 2 - это одна из возможных реализаций паттерна MVC. Собственно, классическая - на базе тех технологий, которые используются в стеке Java EE. Получается, что в качестве представления используется, например, JSP (хотя в этом случае это необязательно - могут использоваться другие шаблонизаторы). В качестве модели используются какие-то Java-ские классы, не суть важно какие, например, бины. В качестве контроллера используются сервлеты. > Обращаю внимание, что полная реализация MVC предполагает полносвязность всех трех элементов (Model, view and controller), то есть предполагает, что каждый элемент связан с каждым, каждый может каждого вызвать. Видим, в случае реализации Model 2, что контроллер получает запрос, определяет, что за представление должно эти запросы обработать (показать страничку или вернуть response клиенту), определяет, что нужно сделать с моделью (вызвать метод наполнения бинов данными), и после этого представление вызывает скомпонованную модель (получает новые данные из тех самых бинов). Контроллер получил запрос, сказал: "Опа, это запрос на страничку такую-то. Опа, для этой странички нужны такие-то данные.". Затем страничка вызывает бин с подготовленными данными. Еще раз, говоря про бизнес-логику: В простом случае вся бизнес-логика действительно здесь. То есть вот этот самый бин (или набор EJB-классов, которые формируют бины). Контроллер сказал: "хочу видеть корзину покупателя". Соответственно бин корзины покупателя начал инициализироваться, в ините понял, что ему нужны такие-то данные из базы данных - сделал там набор селектов к БД, заполнил свои там поля, которые нужно было заполнить. И после этого его вызвала вьюшка. В этом случае вся логика здесь. Если у вас приложение совсем сложное, то под моделью - в слое данных, вокруг БД, есть еще одна прослойка, где живут, например, EJB. То есть модель - это описание данных, которые предназначены для вывода в веб. Реальные данные, хранящиеся в базе, базах или других хранилищах, могут иметь абсолютно другую структуру. И, соответственно, есть отдельный уровень, который тащит эти данные из базы (баз и тд), как-то процессит какую-то логику (формирует, например, отчет), и только после отдает их на уровень веб-приложения. То есть в сложных приложениях модель ходит не в базу, а в промежуточный слой бизнес-логики, который уже сам ходит в базу для подготовки данных и передачи их на веб. ## Http-session ![](https://i.imgur.com/DejSSAX.png)