Доброе время суток всем, кто читает мой блог.
Начинаем цикл статей, а возможно и не цикл, посвященных проектированию «корпоративных» приложений. Сегодня разберем паттерн Front Controller. Пример будет на Java, возможно в последующих статьях появятся примеры на PHP.
Итак, начнем.
Зачем нужен этот паттерн. Front Controller или контроллер запросов объединяет все действия по обработке запросов в одном месте, распределяя их выполнение посредством единого объекта обработчика. Это бывает очень удобно, когда, например, для web-сайта нам надо выполнить вначале проверку на авторизацию пользователя, а потом производить другие действия.
Uml диаграмма данного паттерна выглядит так:
![]() |
| Рис. 1 - UML диаграмма паттерна |
Реализуем данный шаблон.
Структура проекта:
![]() |
| Рис. 2 - структура проекта |
Класс FrontServlet реализует паттерн Front Controller. Данный контроллер будет обрабатывать запрос get стиля: http://localhost:8080/index?command=ggg
public class FrontServlet extends HttpServlet{
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
FrontCommand command = null;
try {
command = getCommand(request);
command.init(getServletContext(), request, response);
command.process();
} catch (ApplicationException e) {
e.printStackTrace();
}
}
private FrontCommand getCommand(HttpServletRequest request)
throws ApplicationException {
try {
return (FrontCommand) getCommandClass(request).newInstance();
} catch (Exception e) {
throw new ApplicationException();
}
}
private Class getCommandClass(HttpServletRequest request) {
Class result;
final String commandClassName = "net.inver.web." +
(String) request.getParameter("command") + "Command";
try {
result = Class.forName(commandClassName);
} catch (ClassNotFoundException e) {
result = UnknownCommand.class;
}
return result;
}
}
Контроллер выполняет команды, которые являются наследниками абстрактного класса FrontCommand.
abstract public class FrontCommand {
protected ServletContext context;
protected HttpServletRequest request;
protected HttpServletResponse response;
public void init(ServletContext context,
HttpServletRequest request,
HttpServletResponse response) {
this.context = context;
this.request = request;
this.response = response;
}
abstract public void process() throws ServletException, IOException;
protected void forward(String target) throws ServletException, IOException {
RequestDispatcher dispatcher = context.getRequestDispatcher(target);
dispatcher.forward(request, response);
}
}
Метод, который надо реализовать в наследниках – process. В ваших командах в данном методе будет происходить выполнение вашей логики.
Метод init будет выполняться в самом начале.
В нашем приложении у нас будет 2 команды – home и unknown.
2-я команда – это логика, которая будет выполняться при запросе несуществующей страницы.
Для каждой команды нам надо создать по JSP странице, которые собственно и будут выводиться. По Фаулеру, в этом приложении, кроме шаблона Front Controller, применяется еще несколько. Рассказ о них мы опустим:)
Ну и web.xml:
FrontController net.inver.web.FrontServlet FrontController /index
В результате:
Все http-запросы будут обрабатываться этим сервлетом. Для того, чтобы ипользовать запросы к картинкам, стилям и прочему, нужно это реализовывать отдельно.
Пример реального использования данного шаблона во фреймворках – Spring framework, Zend framework.
В спринге в действии по-умолчанию вызывается – home, в зенде – indexAction.
Исходники: Source
Спасибо за внимание.
P.S. Для того, чтобы действия выполнять по адресам, которые нам нужны, применяется другой паттерн, который, возможно. называется Router(в зенде по крайней мере так). Но об этом в другой статье.


Front controller один на все приложение? В таком случае получается что для более менее "ентерпрайзного" приложения прийдется пол сотни разных команд делать, для каждой из которых отдельный класс итд. вагон "холостого" кодирования. Какие бенефиты перед Dispatcher(Router) + Controllers? имхо задача структурирования запросов там лучше решается.
ОтветитьУдалитьPS.
и PS. в чем отличие от Command из GoF?
ОтветитьУдалитьАга.. хорошие кстати вопросы)
ОтветитьУдалитьУ меня встречный! Под Controllers ты что подразумевал?
по этому же Фаулеру есть 3 типа:
Page Controller
Front Controller
Application Controller
Который из них?
Page controller навеное, тот что из MVC
ОтветитьУдалить