Как мне реализовать фронт-контроллер в Java?
Я пишу очень простой веб-фреймворк с использованием Java-сервлетов в учебных целях. Я делал это раньше в PHP, и он работал, обращаясь к URI запроса, а затем создавая соответствующий класс и метод.
Это работало нормально в PHP, так как можно сделать что-то вроде $c = new $x; $x->$y;
, Однако я не уверен, как перевести это на Java или даже если это подходящий способ сделать это.
Пока что я пробовал:
Router router = new Router(request.getPathInfo());
String className = router.route(); //returns com.example.controller.Foo
Class c = Class.forName(className);
Object x = c.newInstance();
Foo y = (Foo) x;
y.doSomething();
Это кажется подходящим для пары маршрутов, но не похоже, что оно будет хорошо масштабироваться и не позволит получать маршруты из файла конфигурации.
Как я должен заставить это работать?
4 ответа
Я бы использовал Servlet Filter в качестве фронт-контроллера. Маршрутизатор будет соединять пути с диспетчерами запросов. В методе doFilter вы должны преобразовать ServletRequest в HttpServletRequest, извлечь путь запроса и сопоставить его с зарегистрированными сопоставлениями. Результатом этого сопоставления является диспетчер запросов, с которым вы бы отправляли запрос.
В псевдокоде:
doFilter(ServletRequest request, ServletResponse response) {
httpServletRequest = (HttpServletRequest) request;
path = httpServletRequest.getRequestURI();
dispatcher = router.getTarget(path);
dispatcher.dispatch(request, response);
}
В зависимости от ваших потребностей может быть достаточно стандартного механизма маршрутизации Servlet API.
Захватить действия в Map<String, Action>
где String
Ключ представляет собой более или менее комбинацию метода запроса и запроса pathinfo. Я уже публиковал подобный ответ здесь: Java Front Controller
Вы можете заполнить такую карту либо статически (жестко закодировать все действия), либо динамически (соглашение о конфигурации, поиск классов в определенном пакете, или сканирование всего пути к классам для классов с определенной аннотацией или реализация определенного интерфейса).
И просто придерживайтесь Servlet. Фильтр не существует для. При максимальном использовании используйте его для отправки запроса сервлету контроллера. В сервлете просто реализуем HttpServlet#service()
,
Не совсем уверен, что вы ищете, но вы можете взглянуть на Java-сервлеты. Конечно, многие веб-фреймворки абстрагируются от простых сервлетов, но это очень хорошее место, чтобы начать изучать веб-приложения на Java, если вы спросите меня (что вы косвенно сделали;))
Загрузите спецификацию Java-сервлета здесь: Java Servlet Spec - это довольно интересно.
Как вы должны заставить это работать? Однако вы хотите этого. Если вы просто делаете это в учебных целях, все, что вы делаете, будет хорошо.
Я бы посоветовал, чтобы все ваши действия реализовывали один и тот же интерфейс (возможно, расширяя Servlet), чтобы вам не приходилось компилировать во всех разных классах.
Тогда вы можете делать то, что делаете, за исключением того, что Foo
становится актером Servlet
и тогда вам не нужно иметь особый случай для всех ваших разных классов.
Затем вы также можете загрузить маршруты из конфигурации (возможно, XML-файл).
По сути, то, что вы делаете, реализовано инфраструктурой Struts 1, так что, возможно, стоит почитать об этом (это открытый исходный код, поэтому вы также можете посмотреть на источник, если хотите).