Eylem ve eylem arasındaki farklar


Yanıtlar:


583

ActionListener

Kullanım actionListenerEğer bir kanca var isterseniz önce gerçek iş eylemin yerine getirilmeyecek, mesela o günlüğe ve / veya (ederek ek özelliği ayarlamak için <f:setPropertyActionListener>) ve / veya tarafından kullanılabilir eylemi (çağrılan bileşen erişmesini ActionEventargüman). Yani, sadece gerçek iş eylemi başlatılmadan önce amaçları hazırlamak için.

actionListenerYöntem varsayılan aşağıdaki imzası ile vardır:

import javax.faces.event.ActionEvent;
// ...

public void actionListener(ActionEvent event) {
    // ...
}

Ve herhangi bir yöntem parantezi olmadan aşağıdaki şekilde ilan edilmesi gerekiyor:

<h:commandXxx ... actionListener="#{bean.actionListener}" />

Eğer geçemez unutmayın ek EL 2.2 ile argümanları. Ancak ActionEventözel bağımsız değişken (ler) geçirerek ve belirterek bağımsız değişkeni tamamen geçersiz kılabilirsiniz . Aşağıdaki örnekler geçerlidir:

<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) {}

Değişken olmayan yöntem ifadesinde parantezlerin önemine dikkat edin. Eğer olmasaydı, JSF yine de ActionEventtartışmalı bir yöntem beklerdi .

EL 2.2+ kullanıyorsanız, birden fazla eylem dinleyici yöntemini aracılığıyla bildirebilirsiniz <f:actionListener binding>.

<h:commandXxx ... actionListener="#{bean.actionListener1}">
    <f:actionListener binding="#{bean.actionListener2()}" />
    <f:actionListener binding="#{bean.actionListener3()}" />
</h:commandXxx>
public void actionListener1(ActionEvent event) {}
public void actionListener2() {}
public void actionListener3() {}

Özellikte parantezlerin önemine dikkat edin binding. Eğer yoklarsa, EL kafa karıştırıcı bir şekilde a atar javax.el.PropertyNotFoundException: Property 'actionListener1' not found on type com.example.Bean, çünkü bindingöznitelik varsayılan olarak bir yöntem ifadesi olarak değil, bir değer ifadesi olarak yorumlanır. EL 2.2+ stili parantezler şeffaf bir şekilde bir değer ifadesini yöntem ifadesine dönüştürür. Ayrıca bkz. Ao Neden JSF tarafından desteklenmiyorsa <f: actionListener> öğesini rastgele bir yönteme bağlayabiliyorum?


aksiyon

actionBir iş eylemi yürütmek ve gerekirse gezinmeyi yönetmek istiyorsanız kullanın . actionYöntemi (ve böylece, gereken olan) bir dönebilir Stringnavigasyon durumda sonuç (hedef görünümü) olarak kullanılacak olan. nullVeya döndürme değeri voidaynı sayfaya dönmesine izin verir ve geçerli görünüm kapsamını canlı tutar. Boş bir dizenin veya aynı görünüm kimliğinin döndürme değeri de aynı sayfaya dönecek, ancak görünüm kapsamını yeniden oluşturacak ve böylece geçerli olarak etkin görünüm kapsamındaki çekirdekleri yok edecek ve varsa yeniden oluşturacaktır.

actionYöntem herhangi bir geçerli olabilir MethodExpression2.2 argümanlar böyle aşağıda EL kullanır, ayrıca olanları:

<h:commandXxx value="submit" action="#{bean.edit(item)}" />

Bu yöntemle:

public void edit(Item item) {
    // ...
}

İşlem yönteminiz yalnızca bir dize döndürdüğünde, yalnızca actionöznitelikte tam olarak bu dizeyi belirtebileceğinizi unutmayın . Böylece, bu tamamen sakar:

<h:commandLink value="Go to next page" action="#{bean.goToNextpage}" />

Sabit kodlu bir dize döndüren bu anlamsız yöntemle:

public String goToNextpage() {
    return "nextpage";
}

Bunun yerine, bu sabit kodlu dizeyi doğrudan niteliğe koyun:

<h:commandLink value="Go to next page" action="nextpage" />

Bunun sırayla kötü bir tasarımı gösterdiğini lütfen unutmayın: POST ile gezinme. Bu kullanıcı veya SEO dostu değildir. Bu, h: commandLink yerine h: outputLink'i ne zaman kullanmalıyım? ve şu şekilde çözülmesi gerekiyordu:

<h:link value="Go to next page" outcome="nextpage" />

Ayrıca bkz . JSF'de nasıl gezinilir? URL'nin mevcut sayfayı (önceki sayfayı değil) yansıtmasını sağlama .


f: ajax dinleyicisi

JSF 2.x beri üçüncü bir yol var <f:ajax listener>,.

<h:commandXxx ...>
    <f:ajax listener="#{bean.ajaxListener}" />
</h:commandXxx>

ajaxListenerYöntem varsayılan aşağıdaki imzası ile vardır:

import javax.faces.event.AjaxBehaviorEvent;
// ...

public void ajaxListener(AjaxBehaviorEvent event) {
    // ...
}

Mojarra'da AjaxBehaviorEventargüman isteğe bağlıdır, aşağıda iyi çalışır.

public void ajaxListener() {
    // ...
}

Ama MyFaces'de, a MethodNotFoundException. Argümanı atlamak istediğinizde aşağıdaki her iki JSF uygulamasında da çalışır.

<h:commandXxx ...>
    <f:ajax execute="@form" listener="#{bean.ajaxListener()}" render="@form" />
</h:commandXxx>

Ajax dinleyicileri komut bileşenlerinde gerçekten kullanışlı değildir. Onlar girdi basıp bileşenleri üzerinde daha faydalıdır <h:inputXxx>/ <h:selectXxx>. Komut bileşenlerinde, netlik ve daha iyi kendi kendini belgeleyen kod için actionve / veya bağlı actionListenerkalın. Dahası, böyle actionListener, f:ajax listenerbir navigasyon sonucu dönen desteklemez.

<h:commandXxx ... action="#{bean.action}">
    <f:ajax execute="@form" render="@form" />
</h:commandXxx>

Açıklamalar executeve renderöznitelikler için PrimeFaces işlemini / güncellemesini anlama ve JSF f: ajax yürütme / oluşturma özniteliklerine gidin .


Çağrı sırası

actionListenerHep çağrılan daha önceaction bu görünümde bildirilen ve bileşen eklenmiş olan aynı sırada. Her f:ajax listenerzaman herhangi bir eylem dinleyicisinden önce çağrılır . Yani, aşağıdaki örnek:

<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>

Yöntemleri aşağıdaki sırayla çağırır:

  1. Bean#ajaxListener()
  2. Bean#actionListener()
  3. ActionListenerType#processAction()
  4. Bean#actionListenerBinding()
  5. Bean#setProperty()
  6. Bean#action()

İstisna işleme

actionListenerÖzel bir istisna destekler: AbortProcessingException. Bu kural dışı durum bir actionListeneryöntemden atılırsa , JSF kalan eylem dinleyicilerini ve eylem yöntemini atlar ve doğrudan yanıt vermeye devam eder. Bir hata / istisna sayfası görmezsiniz, ancak JSF bunu kaydeder. Bu aynı zamanda bir başka istisna atılırken örtük olarak yapılacaktır actionListener. Bu nedenle, bir iş istisnası nedeniyle sayfayı bir hata sayfasıyla engellemeyi planlıyorsanız, işi kesinlikle actionyöntemde gerçekleştirmelisiniz.

A kullanmanın tek nedeni aynı sayfaya dönen actionListenerbir voidyönteme sahip olmaksa, bu kötü bir yöntemdir. actionYöntemler mükemmel da dönebilirsiniz voidbazı IDE EL doğrulama yoluyla inandırmak ne tam tersine,. PrimeFaces vitrin örneklerinin actionListenerher yerde bu tür s ile doldurulduğunu unutmayın . Bu gerçekten yanlış. Bunu kendiniz için bir bahane olarak kullanmayın.

Ancak, ajax isteklerinde özel bir istisna işleyicisi gereklidir. Bu, listenerniteliğini kullanıp kullanmadığınıza bakılmaksızın yapılır <f:ajax>. Açıklama ve bir örnek için JSF ajax isteklerinde İstisna işleme bölümüne gidin .


1
ActionListeners özel durumlarının varsayılan olarak yutulması haklısınız, ancak JSF 2.0'da bu davranış değiştirilebilir. Ayrıntılar için aşağıdaki cevabıma bakın.
Arjan Tijms

3
@arjan: JSF 2.0 tarafından atılan istisnaların varsayılan işlemesini değiştirmenize izin veriyor actionListener, ancak bu yine de eylemleri için kötüye kullanım actionListeneriçin iyi bir bahane oluşturmuyor .
BalusC

1
Gerçekten de, iş eylemleri talep / yanıt döngüsünün ana "akışı" ndadır ve sadece buna actionkarşılık gelir. actionListenerikincil şeyler içindir. Sadece gerektiğinde actionListeners istisnalarının çoğaltılabileceğini açıklığa kavuşturmak istedim ;)
Arjan Tijms

2
@Kawy: actionListeneröznitelikte kullanıldığında yöntem adı seçim ücretsizdir ve aynı zamanda olması gerekir public. Bu processActionad yalnızca, yalnızca tam olarak bu yöntem adının tanımlandığı arabirimi <f:actionListener type>uygulamak zorunda ActionListenerolduğu için kullanılırken processActionzorunludur.
BalusC

2
@Muhammed: ajax aksiyon dinleyicisi, tüm normal aksiyon dinleyicilerinden önce çağrılır. Kullanırken bile <f:ajax>, komut bileşenlerinin actioniş eylemleri için öznitelik kullanmayı tercih edeceğinizi unutmayın . Örn <h:commandButton action="#{bean.businessAction}"><f:ajax/></h:commandButton>.
BalusC

47

BalusC'nin belirttiği gibi, actionListenervarsayılan olarak istisnaları yutar, ancak JSF 2.0'da bunun biraz daha fazlası vardır. Yani, sadece yutar ve günlükleri değil, aynı zamanda istisnayı yayınlar .

Bu, şöyle bir çağrı ile gerçekleşir:

context.getApplication().publishEvent(context, ExceptionQueuedEvent.class,                                                          
    new ExceptionQueuedEventContext(context, exception, source, phaseId)
);

Bu olay için varsayılan dinleyici ExceptionHandlerMojarra için ayarlanmış olan dinleyicidir com.sun.faces.context.ExceptionHandlerImpl. Bu uygulama, günlüğe kaydedilen bir AbortProcessingException özel durumu dışında tüm istisnaları yeniden içerecektir. ActionListeners, istemci kodu tarafından atılan özel durumu, bu tür bir AbortProcessingException içine sararak bunların neden her zaman günlüğe kaydedildiğini açıklar.

Bu ExceptionHandlerözel bir uygulaması ile yüzler-config.xml ancak değiştirilebilir:

<exception-handlerfactory>
   com.foo.myExceptionHandler
</exception-handlerfactory>

Küresel olarak dinlemek yerine, tek bir fasulye de bu olayları dinleyebilir. Aşağıdakiler bunun kavramının bir kanıtıdır:

@ManagedBean
@RequestScoped
public class MyBean {

    public void actionMethod(ActionEvent event) {

        FacesContext.getCurrentInstance().getApplication().subscribeToEvent(ExceptionQueuedEvent.class, new SystemEventListener() {

        @Override
        public void processEvent(SystemEvent event) throws AbortProcessingException {
            ExceptionQueuedEventContext content = (ExceptionQueuedEventContext)event.getSource();
            throw new RuntimeException(content.getException());
        }

        @Override
        public boolean isListenerForSource(Object source) {
            return true;
        }
        });

        throw new RuntimeException("test");
    }

}

(not, normalde dinleyicileri bu şekilde kodlamamalıdır, bu sadece gösterim amaçlıdır!)

Bunu böyle bir Facelet'ten çağırmak:

<html xmlns="http://www.w3.org/1999/xhtml"
    xmlns:h="http://java.sun.com/jsf/html"
    xmlns:f="http://java.sun.com/jsf/core">
    <h:body>
        <h:form>
            <h:commandButton value="test" actionListener="#{myBean.actionMethod}"/>
        </h:form>
    </h:body>
</html>

Bir hata sayfasının görüntülenmesine neden olur.


43

ActionListener, Action çağrılmadan ve sonraki sayfanın konumunu belirlemeden önce, yanıtı değiştirme seçeneği ile önce tetiklenir.

Aynı sayfada aynı yere gitmesi gereken, ancak biraz farklı şeyler yapan birden fazla düğmeniz varsa, her bir düğme için aynı Eylemi kullanabilir, ancak biraz farklı işlevleri işlemek için farklı bir ActionListener kullanabilirsiniz.

İlişkiyi tanımlayan bir link:

http://www.java-samples.com/showtutorial.php?tutorialid=605


3
artı bir, Kalın harfler neredeyse her şeyi söylüyor.
Shirgill Farhan

0

TL; DR :

ActionListenerS (birden olabilir) onlar ÖNCE kaydedildi sırayla yürütmekaction

Uzun Cevap :

Bir iş actiontipik bir EJB hizmete neden ve gerekli Ayrıca farklı bir görünüme nihai sonucu ve / veya Navigates'ten ayarlar eğer bir ne yaptığını değilse actionListenerdaha uygun yani ne zaman gibi bileşenlerle Kullanıcı etkileşimde, h:commandButtonya h:linkonlar actionListenerUI Bileşeninin özelliğinde yönetilen fasulye yönteminin adını geçirerek veya bir ActionListenerarabirim uygulayarak ve uygulama sınıfı adını bir UI Bileşeninin özelliğine geçirerek ele alınabilir actionListener.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.