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
- классaction
template
- шаблонgsp
. Если указан шаблон и не указан атрибутclass
, то в качестве класса принимаетсяjandcode.core.web.std.action.GspAction
, которая рендерит указанный шаблон.