2015-08-06 3 views
8

istekleri giriş yapabilirsiniz. Gerçekten yapmak istiyorum nenasıl JSF ajax metodu ifadeleri ben bir istek hangi sayfanın bir filtrede, gelen bir ajax isteği ve ne zaman oturum açmak için nasıl anladım var

ajax isteği için aslında ne log olduğunu. Ajax tarafından çağrılan yöntemin adı (ör. Bu çağrıdaki "findAddress" gibi):

Bunu nasıl yapabilirim? Uygulamamın birçok ajax isteği var ve tetiklenen günlüğe kayıt olmak istiyorum. Gerçekten yapmak istiyorum ne

public class TrackingFilter implements Filter { 

private static Logger LOG = Logger.getLogger(TrackingFilter.class); 

@Override 
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException, IOException {  

    HttpServletRequest req = (HttpServletRequest) request; 

    String pageHit = req.getRequestURI().substring(req.getContextPath().length()+1).replace(".xhtml", ""); 
    if(!pageHit.contains("javax.faces.resource")){ // if is a url we want to log 
     if ("partial/ajax".equals(req.getHeader("Faces-Request"))) { 
      LOG.trace("ajax on URI: " + req.getRequestURI()); 
     } 
+0

özellikle dinleyici yöntemi adı, masal lütfen buraya bir göz hakkında: http://stackoverflow.com/questions/11860550/jsf-get-current -işlemde yönetilen-fasulye –

+0

@tt_dev İlginç. Bunu potansiyel olarak kullanabilirim, ancak faceContext benim filtremde fasulye olmadığı için mevcut değildir. Ben faceContext standart istek/oturum içinde bir yerden tutulabilir inanıyorum, ama nerede hatırlamıyorum. Uygulamamı hata ayıklamada kullanıyorum. –

+1

Bu sorunun indirilmesinin bir nedeni yok. – Tiny

cevap

10

ajax isteği için aslında ne log olduğunu. Yöntemin adı (Bu çağrıda örneğin "findAddress": <p:ajax process="contactDetails" update="@form" listener="#{aboutYouController.findAddress}" ....) ajax tarafından çağrılan Mesela

Bu bilgiler JSF bileşen ağacında kullanılabilir. JSF bileşen ağacı yalnızca görünüm oluşturma süresinden sonra kullanılabilir. Bir görünüm yalnızca istek FacesServlet tarafından sunulduğunda oluşturulur. Böylece, bir sunucu filtresi, herhangi bir sunucu uygulamasından önce çalıştığı kadar erken. Bir postback görünüm aşamasını geri yükledikten sonra

Sen en iyisi kodu kaçardım. JSF bileşen ağacının o anda kullanılabilir olduğu garanti edilir. Mevcut isteğin bir geri gönderme olup olmadığını kontrol etmek için FacesContext#isPostback()'u kullanabilirsiniz. Mevcut isteğin bir ajax isteği olup olmadığını kontrol etmek için PartialViewContext#isAjaxRequest()'u kullanabilirsiniz. Ajax isteğinin kaynak bileşeninin istemci kimliğini almak için önceden tanımlanmış javax.faces.source istek parametresini kullanabilirsiniz. Sen ajax Etkinlik adı (örneğin change, click, action, vs) elde etmek için önceden tanımlanmış javax.faces.behavior.event istek parametresini kullanabilirsiniz. ilişkilendirilmiş davranışın dinleyicileri elde

bir öykü dışında sırayla olduğunu. Bu, MethodExpression yalnızca ActionSource2#getActionExpression() tarafından kullanılabilir olduğundan ActionSource2 bileşenlerinde (ör. <h|p:commandButton action="#{...}">) kolaydır. Ancak, bu API'nin getBehaviorListeners() gibi bir yöntemi olmadığı için bu BehaviorBase etiketleyicilerinde (ör. <f|p:ajax listener="#{...}">) kolay değildir. Bunları eklemek ve kaldırmak için yalnızca bir yöntem vardır, ancak bunların bir listesini elde etmek için değil. Yani bazı kötü yansıma hilesi, adı JSF uygulaması özel olan dinleyicilerle private alanına erişmek için gereklidir. Mojarra'da, listeners ve MyFaces'de _behaviorListeners. Her ikisi de List'dan atanabilir ve bu türün tek alanıdır, bu yüzden bunu kontrol edebiliriz. Bir kez o zaman hala o örneğinin MethodExpression alanını elde etmek için başka bir yansıma hile yapmak gerekir, BehaviorListener örneğinin ele sahip. Yuck.

Sonuçta, burada hile afterPhaseRESTORE_VIEW ait dinleyen bir PhaseListener lezzet nasıl göründüğünü nasıl:

o koşmak faces-config.xml gibi, altta kayıt alabilmek için
public class AjaxActionLoggerPhaseListener implements PhaseListener { 

    @Override 
    public PhaseId getPhaseId() { 
     return PhaseId.RESTORE_VIEW; 
    } 

    @Override 
    public void beforePhase(PhaseEvent event) { 
     // NOOP. 
    } 

    @Override 
    public void afterPhase(PhaseEvent event) { 
     FacesContext context = event.getFacesContext(); 

     if (!(context.isPostback() && context.getPartialViewContext().isAjaxRequest())) { 
      return; // Not an ajax postback. 
     } 

     Map<String, String> params = context.getExternalContext().getRequestParameterMap(); 
     String sourceClientId = params.get("javax.faces.source"); 
     String behaviorEvent = params.get("javax.faces.behavior.event"); 

     UIComponent source = context.getViewRoot().findComponent(sourceClientId); 
     List<String> methodExpressions = new ArrayList<>(); 

     if (source instanceof ClientBehaviorHolder && behaviorEvent != null) { 
      for (ClientBehavior behavior : ((ClientBehaviorHolder) source).getClientBehaviors().get(behaviorEvent)) { 
       List<BehaviorListener> listeners = getField(BehaviorBase.class, List.class, behavior); 

       if (listeners != null) { 
        for (BehaviorListener listener : listeners) { 
         MethodExpression methodExpression = getField(listener.getClass(), MethodExpression.class, listener); 

         if (methodExpression != null) { 
          methodExpressions.add(methodExpression.getExpressionString()); 
         } 
        } 
       } 
      } 
     } 

     if (source instanceof ActionSource2) { 
      MethodExpression methodExpression = ((ActionSource2) source).getActionExpression(); 

      if (methodExpression != null) { 
       methodExpressions.add(methodExpression.getExpressionString()); 
      } 
     } 

     System.out.println(methodExpressions); // Do your thing with it. 
    } 

    private static <C, F> F getField(Class<? extends C> classType, Class<F> fieldType, C instance) { 
     try { 
      for (Field field : classType.getDeclaredFields()) { 
       if (field.getType().isAssignableFrom(fieldType)) { 
        field.setAccessible(true); 
        return (F) field.get(instance); 
       } 
      } 
     } catch (Exception e) { 
      // Handle? 
     } 

     return null; 
    } 

} 

:

<lifecycle> 
    <phase-listener>com.example.AjaxActionLoggerPhaseListener</phase-listener> 
</lifecycle> 

Yukarıda, Mojarra ve PrimeFaces ile test edilmiş ve uyumludur ve teorik olarak MyFaces ile uyumludur.


Güncelleme: durumda almak için Components#getActionExpressionsAndListeners() MTU yarar kütüphanesini OmniFaces kullanarak veya açık, yeni Components#getCurrentActionSource() yarar yöntemini kullanabilirsiniz sürüm 2.4 beri mevcut eylem kaynak bileşeni bulmak için ve konum Belirli bir bileşene kayıtlı tüm eylem yöntemlerinin ve dinleyicilerin listesi. Bu, normal (ajax olmayan) isteklerde de kullanılabilir. Bunun üzerine, yukarıdaki PhaseListener örnek olarak aşağıda azaltılabilir:

public class FacesActionLoggerPhaseListener implements PhaseListener { 

    @Override 
    public PhaseId getPhaseId() { 
     return PhaseId.PROCESS_VALIDATIONS; 
    } 

    @Override 
    public void beforePhase(PhaseEvent event) { 
     // NOOP. 
    } 

    @Override 
    public void afterPhase(PhaseEvent event) { 
     if (!event.getFacesContext().isPostback())) { 
      return; 
     } 

     UIComponent source = Components.getCurrentActionSource(); 
     List<String> methodExpressions = Components.getActionExpressionsAndListeners(source); 
     System.out.println(methodExpressions); // Do your thing with it. 
    } 

} 
+0

100 puanlık ödülün ilginizi çekeceğini biliyordum. Tekrar teşekkürler @BalusC SO hakkında cevaplarınızdan dolayı JSF hakkında çok daha fazla şey biliyorum. Çözüm geçerli görünüyor - ve muhtemelen. Önerinizi uygulamaya koyduğumda kısa sürede ödül vereceğim. –

+2

Rica ederim. Ödül olarak, sisteme otomatik olarak izin verebilirsiniz. Listeleme ne kadar uzun bir soru kalırsa, daha fazla kişi, özellikle de ödülün son gününde, Q & A'yı görecek ve onlarla paylaşacak. Böylelikle, ödül için harcadığınız geri bir miktar kazanabilirsiniz. – BalusC

+0

Bu iyi bir ipucu! –