Action
Что такое action
Action - это объекты, реализующие интерфейс jandcode.core.web.action.IAction, которые
обратывают http-запросы пользователя в контексте web-приложения и возвращают
ответ клиенту.
На практике для создания action необходимо создать наследника от класса
jandcode.core.web.action.BaseAction и реализовать ему метод onExec(), в котором
и будет логика обработки запроса.
Каждая action регистрируется в приложении под определенным именем, которое может
включать в себя /:
<root>
<web>
<action name="action1"
class="mymodule.mypackage.Action1"/>
<action name="blog/news"
class="mymodule.mypackage.News"/>
<action name="blog"
class="mymodule.mypackage.Blog"/>
</web>
</root>Упрощенная схема преобразования url в action такова:
среди всех зарегистрированных action ищется такая, имя которой совпадает с
началом pathInfo http-запроса. Остаток pathInfo, из которого удалено имя action
будет передано в обработчик запроса в качестве одного из атрибутов.
Что такое pathInfo? Допустим, что приложение работает
по адресу http://localhost/myapp/. Тогда все, что будет в url
после http://localhost/myapp/ и до начала параметров (символа ?)
является pathInfo. Например в запросе
http://localhost/myapp/a1/a2/a3?param1=1¶m2=2 имеем pathInfo равным a1/a2/a3.
pathInfo доступно через метод jandcode.core.web.Request#getPathInfo.
Для вышеприведенного примера регистрации action будут верны следующие преобразования
pathInfo в action:
| pathInfo | action | Остаток pathInfo | Коментарий |
|---|---|---|---|
action1 | action1 | ||
action1/m1 | action1 | m1 | |
blog/m1/m2 | blog | m1/m2 | |
blog/news/m1 | blog/news | m1 | blog/news длиннее по фасетам, чем blog |
Реализация action
Простейшая реализация action выглядит так:
package web._inc.action
import jandcode.commons.variant.*
import jandcode.core.web.action.*
class SimpleAction extends BaseAction {
protected void onExec() throws Exception {
// это запрос, тут есть все, что известно о запросе + утилиты
ActionRequestUtils req = getReq()
// это параметры запроса
IVariantMap params = getReq().getParams()
// возвращаем результат клиенту как строку
getReq().render("Hello! Params: " + getReq().getParams())
}
}
Интерпретация pathInfo для action
Доупустим, что имеется action, зарегистрированая так:
<root>
<web>
<action name="my/simple/action"
class="web._inc.action.SimpleAction"/>
</web>
</root>и ее экземпляр создан для обработки запроса с таким pathInfo:
my/simple/action/p1/p2/p3
Тогда в атрибуты getRequest().getAttrs() будут дополнительно добавлены следующие
атрибуты:
| Имя атрибута | Константа имени | Значение | Коментарий |
|---|---|---|---|
actionPathInfo | WebConsts.a_actionPathInfo | p1/p2/p3 | pathInfo, из которого убрано имя action |
actionMethod | WebConsts.a_actionMethod | p1 | Первый фасет из actionPathInfo, имя "метода" для action |
actionMethodPathInfo | WebConsts.a_actionMethodPathInfo | p2/p3 | actionPathInfo, из которого убран первый фасет |
Если соответсвующей информации нет в pathInfo, то атрибуты принимают пустые значения.
Методы в классе action
Реализация метода onExec() по умолчанию вызывает публичный метод
с именем, который указан в атрибуте actionMethod. Если в этом атрибуте нет
значения, то значение по умолчанию для него - index. Если метода с таком именем
нет, то генерируется ошибка.
Пример:
import jandcode.core.web.action.BaseAction
class SimpleMethodsAction extends BaseAction {
public void index() throws Exception {
getReq().render("index")
}
public void p1() throws Exception {
getReq().render("p1")
}
}В таблице показаны варианты обработки различных pathInfo, предполагая, что
action зарегистрирована с именем my/act:
| pathInfo | Действие |
|---|---|
my/act | Вызов метода index |
my/act/index | Вызов метода index |
my/act/p1 | Вызов метода p1 |
my/act/p1/p2/p3 | Вызов метода p1, атрибут actionMethodPathInfo=p2/p3 |
my/act/ppp | Ошибка, метода ppp нет |
Если метод возвращает значение, то это значение будет использовано в качестве данных для рендеринга:
import jandcode.core.web.action.*
class FuncMethodsAction extends BaseAction {
public void p1() throws Exception {
getReq().render("data1")
}
public String p2() throws Exception {
return "data1"
}
}В этом примере методы p1 и p2 эквивалентны.
Когда метод onExec() явно перекрыт, то, естественно, эти правила не действуют и
процесс обработки будет вестись по вашим правилам.
ActionMethodExecutor
Если метод action имеет один параметр типа jandcode.core.web.action.ActionMethodExecutor,
то выполнение метода action делегируется экземпляру этого класса.
Пример:
import jandcode.core.web.action.*
import java.lang.reflect.*
class ActionExecutor1 extends BaseAction {
static class Executor1 implements ActionMethodExecutor {
String data
void execActionMethod(BaseAction action, Method method) throws Exception {
// вызываем оригинальный метод и передаем себя в качестве параметра
method.invoke(action, this)
// пользуемся результатами
Map m = new HashMap()
m.put("data", data)
// рендерим результат
action.getReq().render(m)
}
void setData(String data) {
this.data = data
}
}
//////
void m1(Executor1 ex) {
ex.setData("hello")
}
}index.gsp / index.html
Когда при обработке pathInfo не найдена action, которая соответствует
этому pathInfo, делается попытка интерпретировать pathInfo как виртуальную
папку, в которой ищутся файлы index.gsp или index.html.
Если найден index.gsp, то клиенту возвращается результат рендеринга этого файла.
url для клиента выглядит как папка.
Если найден index.html, то делается redirect на на него, соответственно
url для клиента выглядит как файл.
При наличии обоих файлов приоритет имеет index.gsp.
Action 'root'
Специальная action с именем root обрабатывает запрос в корень url
(http://host или http://host/). По умолчанию настроена на рендеринг
заглушки gsp. Ее нужно настроить в приложении.
Можно указать шаблон gsp:
<root>
<web>
<action name="root"
template="my/app/root.gsp"/>
</web>
</root>или класс action:
<root>
<web>
<action name="root"
class="my.app.MyRootAction"/>
</web>
</root>Конфигурация module.cfx
web/action
Регистрация action.
Формат:
<root>
<web>
<action name="NAME"
class="jandcode.core.web.action.BaseAction"
template="template/path.gsp"
/>
</web>
</root>name- уникальное имяaction. Может включать/.class- классactiontemplate- шаблонgsp. Если указан шаблон и не указан атрибутclass, то в качестве класса принимаетсяjandcode.core.web.std.action.GspAction, которая рендерит указанный шаблон.