actionListener
Используйте actionListener
, если хотите получить хук перед выполнением реального бизнес-действия, например, для его регистрации и / или для установки дополнительного свойства (by <f:setPropertyActionListener>
) и / или иметь доступ к компоненту, который вызвал действие (доступно по аргументу ActionEvent
).Таким образом, исключительно для подготовки целей перед тем, как будет вызвано реальное деловое действие.
По умолчанию метод actionListener
имеет следующую подпись:
import javax.faces.event.ActionEvent;
// ...
public void actionListener(ActionEvent event) {
// ...
}
И он должен быть объявлен следующим образом:без скобок метода:
<h:commandXxx ... actionListener="#{bean.actionListener}" />
Обратите внимание, что вы не можете передать дополнительные аргументы по EL 2.2.Однако вы можете полностью переопределить аргумент ActionEvent
, передав и указав пользовательский аргумент (ы).Допустимы следующие примеры:
<h:commandXxx ... actionListener="#{bean.methodWithoutArguments()}" />
<h:commandXxx ... actionListener="#{bean.methodWithOneArgument(arg1)}" />
<h:commandXxx ... actionListener="#{bean.methodWithTwoArguments(arg1, arg2)}" />
public void methodWithoutArguments() {}
public void methodWithOneArgument(Object arg1) {}
public void methodWithTwoArguments(Object arg1, Object arg2) {}
Обратите внимание на важность скобок в выражении метода без аргументов.Если бы они отсутствовали, JSF все равно ожидал бы метод с аргументом ActionEvent
.
Если вы используете EL 2.2+, то вы можете объявить несколько методов прослушивателя действий с помощью <f:actionListener binding>
.
* 1033.*
public void actionListener1(ActionEvent event) {}
public void actionListener2() {}
public void actionListener3() {}
Обратите внимание на важность скобок в атрибуте binding
.Если бы они отсутствовали, EL бы сбил с толку javax.el.PropertyNotFoundException: Property 'actionListener1' not found on type com.example.Bean
, потому что атрибут binding
по умолчанию интерпретируется как выражение значения, а не как выражение метода.Добавление скобок в стиле EL 2.2+ прозрачно превращает выражение значения в выражение метода.См. Также Почему я могу связыватьсяк произвольному методу, если он не поддерживается JSF?
action
Используйте action
, если вы хотите выполнить бизнес-действие и при необходимости обработать навигацию.Метод action
может (таким образом, не должен) возвращать String
, который будет использоваться в качестве результата навигации (целевое представление).Возвращаемое значение null
или void
позволит ему вернуться на ту же страницу и сохранить текущую область просмотра.Возвращаемое значение пустой строки или того же идентификатора представления также вернется на ту же страницу, но заново создаст область представления и, таким образом, уничтожит все активные в настоящее время компоненты области видимости и, если применимо, создаст их заново.
Метод action
может быть любым допустимым MethodExpression
, также тот, который использует аргументы EL 2.2, такие как ниже:
<h:commandXxx value="submit" action="#{bean.edit(item)}" />
С этим методом:
public void edit(Item item) {
// ...
}
Обратите внимание, что когда ваш метод действия возвращает только строку, вы также можете просто указать именно эту строку в атрибуте action
.Таким образом, это совершенно неуклюже:
<h:commandLink value="Go to next page" action="#{bean.goToNextpage}" />
С помощью этого бессмысленного метода, возвращающего жестко закодированную строку:
public String goToNextpage() {
return "nextpage";
}
Вместо этого просто поместите эту жестко закодированную строку непосредственно в атрибут:
<h:commandLink value="Go to next page" action="nextpage" />
Обратите внимание, что это, в свою очередь, указывает на плохой дизайн: навигация по POST.Это не является ни пользователем, ни оптимизированным для SEO.Все это объясняется в Когда я должен использовать h: outputLink вместо h: commandLink? и должен быть решен как
<h:link value="Go to next page" outcome="nextpage" />
См. Также Как перемещаться в JSF?Как сделать так, чтобы URL отражал текущую страницу (а не предыдущую) .
f: слушатель ajax
Начиная с JSF 2.x существует третий путь, <f:ajax listener>
.
<h:commandXxx ...>
<f:ajax listener="#{bean.ajaxListener}" />
</h:commandXxx>
Метод ajaxListener
по умолчанию имеет следующую подпись:
import javax.faces.event.AjaxBehaviorEvent;
// ...
public void ajaxListener(AjaxBehaviorEvent event) {
// ...
}
В Мохарре аргумент AjaxBehaviorEvent
является необязательным, ниже работает хорошо.
public void ajaxListener() {
// ...
}
Но в MyFaces было бы выброшено MethodNotFoundException
.Ниже приведено описание обеих реализаций JSF, когда вы хотите опустить аргумент.
<h:commandXxx ...>
<f:ajax execute="@form" listener="#{bean.ajaxListener()}" render="@form" />
</h:commandXxx>
Слушатели Ajax не очень полезны для компонентов команд.Они более полезны при вводе и выбирают компоненты <h:inputXxx>
/ <h:selectXxx>
.В компонентах команд просто придерживайтесь action
и / или actionListener
для ясности и лучшего самодокументируемого кода.Более того, как и actionListener
, f:ajax listener
не поддерживает возврат результатов навигации.
<h:commandXxx ... action="#{bean.action}">
<f:ajax execute="@form" render="@form" />
</h:commandXxx>
Для объяснения атрибутов execute
и render
обратитесь к Общие сведения о процессе / обновлении PrimeFacesи JSF f: атрибуты выполнения / рендеринга ajax .
Порядок вызова
actionListener
всегда вызываются до action
в том же порядке, в каком они были объявлены в представлении и присоединены к компоненту. f:ajax listener
всегда вызывается до любого слушателя действия. Итак, следующий пример:
<h:commandButton value="submit" actionListener="#{bean.actionListener}" action="#{bean.action}">
<f:actionListener type="com.example.ActionListenerType" />
<f:actionListener binding="#{bean.actionListenerBinding()}" />
<f:setPropertyActionListener target="#{bean.property}" value="some" />
<f:ajax listener="#{bean.ajaxListener}" />
</h:commandButton>
Будет вызывать методы в следующем порядке:
Bean#ajaxListener()
Bean#actionListener()
ActionListenerType#processAction()
Bean#actionListenerBinding()
Bean#setProperty()
Bean#action()
Обработка исключений
actionListener
поддерживает специальное исключение: AbortProcessingException
. Если это исключение выдается из метода actionListener
, JSF пропустит все оставшиеся обработчики действий и метод действия и перейдет к непосредственному отображению ответа. Вы не увидите страницу ошибки / исключения, однако JSF зарегистрирует ее. Это также неявно будет выполняться всякий раз, когда из actionListener
выдается любое другое исключение. Таким образом, если вы намереваетесь заблокировать страницу из-за ошибки в результате бизнес-исключения, то вам определенно следует выполнить задание методом action
.
Если единственная причина использования actionListener
состоит в том, чтобы метод void
возвращался на ту же страницу, то это плохая причина. Методы action
могут также отлично возвращать void
, в отличие от того, что некоторые IDE позволяют вам верить посредством проверки EL. Обратите внимание, что примеры PrimeFaces изобилуют такими типами actionListener
s повсюду. Это действительно неправильно. Не используйте это как оправдание, чтобы сделать это самостоятельно.
Однако в ajax-запросах требуется специальный обработчик исключений. Это независимо от того, используете ли вы listener
атрибут <f:ajax>
или нет. Для объяснения и примера обратитесь к Обработка исключений в запросах JSF ajax .