2015-08-06 5 views
8

मैंने यह पता लगाया है कि अनुरोध कब एक एजेक्स अनुरोध है और यह कौन सा पृष्ठ है, फ़िल्टर में।मैं जेएसएफ AJAX अनुरोधों के विधि अभिव्यक्तियों को कैसे लॉग कर सकता हूं

मैं वास्तव में क्या करना चाहता हूं लॉग इन है कि AJAX अनुरोध वास्तव में क्या है। जैसे कि इस कॉल में अजाक्स (उदाहरण के लिए "findAddress" नामक विधि का नाम: <p:ajax process="contactDetails" update="@form" listener="#{aboutYouController.findAddress}" ....)

मैं यह कैसे कर सकता हूं? मेरे ऐप में कई AJAX अनुरोध हैं और मैं लॉग इन करना चाहता हूं जो ट्रिगर किए जा रहे हैं।

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

विशेष रूप से श्रोता विधि नाम, कहानी यहाँ पर कृपया एक नज़र के बारे में: http://stackoverflow.com/questions/11860550/jsf-get-current -क्शन-इन-प्रबंधित-बीन –

+0

@tt_dev दिलचस्प। मैं संभावित रूप से इसका उपयोग कर सकता हूं, हालांकि चेहरे का चयन मेरे फ़िल्टर में उपलब्ध नहीं है क्योंकि यह एक बीन नहीं है। मुझे विश्वास है कि मैं चेहरों को मानक अनुरोध/सत्र के भीतर कहीं से पकड़ लिया जा सकता है, लेकिन मुझे याद नहीं है। मेरे पास कोई ऐप नहीं होने के लिए डीबग खोज में मेरा ऐप है। –

+1

इस प्रश्न को कम करने के लिए कोई कारण नहीं है। – Tiny

उत्तर

10

मैं सच में करना चाहते हैं क्या लोग इन क्या ajax अनुरोध के लिए वास्तव में है। इस तरह के रूप में विधि का नाम ajax (उदाहरण के लिए "findAddress" इस कॉल में: <p:ajax process="contactDetails" update="@form" listener="#{aboutYouController.findAddress}" ....) द्वारा बुलाया जा रहा है

यह जानकारी JSF घटक पेड़ में ही उपलब्ध है। जेएसएफ घटक पेड़ केवल निर्माण समय देखने के बाद उपलब्ध है। एक दृश्य केवल तभी बनाया जाता है जब अनुरोध FacesServlet द्वारा किया गया हो। इस प्रकार, एक सर्वलेट फ़िल्टर बहुत जल्दी है क्योंकि यह किसी भी सर्वलेट से पहले चलता है।

आप पोस्टबैक के पुनर्स्थापना दृश्य चरण के बाद कोड को बेहतर ढंग से चलाएंगे। जेएसएफ घटक पेड़ उस पल के दौरान उपलब्ध होने की गारंटी है। वर्तमान अनुरोध एक पोस्टबैक है या नहीं, यह देखने के लिए आप FacesContext#isPostback() का उपयोग कर सकते हैं। यह जांचने के लिए कि वर्तमान अनुरोध अजाक्स अनुरोध है या नहीं, आप PartialViewContext#isAjaxRequest() का उपयोग कर सकते हैं। AJAX अनुरोध के स्रोत घटक की क्लाइंट आईडी प्राप्त करने के लिए आप पूर्वनिर्धारित javax.faces.source अनुरोध पैरामीटर का उपयोग कर सकते हैं। आप AJAX ईवेंट नाम प्राप्त करने के लिए पूर्वनिर्धारित javax.faces.behavior.event अनुरोध पैरामीटर का उपयोग कर सकते हैं (उदा। change, click, action, आदि)।

संबंधित व्यवहार श्रोताओं को प्राप्त करना बदले में एक कहानी अलग है। यह ActionSource2 घटकों (उदा। <h|p:commandButton action="#{...}">) पर आसान है क्योंकि MethodExpression केवल ActionSource2#getActionExpression() द्वारा उपलब्ध है। हालांकि, BehaviorBase टैगहैंडर्स (उदा। <f|p:ajax listener="#{...}">) पर यह आसान नहीं है क्योंकि इस एपीआई में getBehaviorListeners() जैसी कोई विधि नहीं है। उन्हें जोड़ने और हटाने के लिए केवल विधियां हैं, लेकिन उनमें से एक सूची प्राप्त नहीं करने के लिए। तो उन श्रोताओं के साथ private फ़ील्ड तक पहुंचने के लिए कुछ बुरा प्रतिबिंब चालना आवश्यक है जिसका नाम जेएसएफ कार्यान्वयन विशिष्ट है। Mojarra में यह listeners है और MyFaces में यह _behaviorListeners है। दोनों सौभाग्य से List से असाइन किए जा सकते हैं और यह उस प्रकार का एकमात्र क्षेत्र है, इसलिए हम इसकी जांच कर सकते हैं। एक बार BehaviorListener उदाहरण का हाथ रखने के बाद, आप अभी भी को उस उदाहरण के MethodExpression फ़ील्ड को प्राप्त करने के लिए एक और प्रतिबिंब चालबाजी करने की आवश्यकता है। छी।

कुल मिलाकर, यहाँ प्रवंचना एक PhaseListener का स्वाद RESTORE_VIEW की afterPhase पर सुनने में की तरह लग रहे तरीका देखें:

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

} 

ताकि इसे चलाने रजिस्टर faces-config.xml में नीचे के रूप में करने के लिए प्राप्त करने के लिए:

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

ऊपर मोजोजरा और प्राइमफेस के साथ परीक्षण और संगत है और सैद्धांतिक रूप से माईफेस के साथ भी संगत है।


अद्यतन: मामले में आप JSF उपयोगिता पुस्तकालय OmniFaces उपयोग कर रहे हैं, या के लिए खुले हैं, संस्करण 2.4 के बाद से आप नए Components#getCurrentActionSource() उपयोगिता विधि का उपयोग कर सकते हैं वर्तमान कार्रवाई स्रोत घटक पता लगाने के लिए और Components#getActionExpressionsAndListeners() पाने के लिए किसी दिए गए घटक पर पंजीकृत सभी क्रिया विधियों और श्रोताओं की एक सूची। यह नियमित (गैर-AJAX) अनुरोधों पर भी प्रयोग योग्य है। इसी के साथ, ऊपर PhaseListener उदाहरण के रूप में नीचे कम किया जा सकता:

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 अंक बक्षीस आपका ध्यान आकर्षित करेंगे। धन्यवाद फिर से @ बाल्लूसी मैं एसओ पर आपके उत्तरों के कारण जेएसएफ के बारे में बहुत कुछ जानता हूं। समाधान व्यवहार्य लगता है - और शायद है। जब मैं आपके सुझाव को लागू करने के लिए घूमता हूं तो मैं जल्द ही बक्षीस का पुरस्कार दूंगा। –

+2

आपका स्वागत है। बक्षीस के रूप में, आप सिस्टम को इसे स्वचालित रूप से स्वचालित भी कर सकते हैं। अब तक एक बक्षीस सवाल सूची में रहता है, अधिक लोग क्यू एंड ए को विशेष रूप से बक्षीस के आखिरी दिन में देखेंगे और ऊपर उठाएंगे। इस तरह आप बकाया राशि के लिए खर्च किए गए कुछ प्रतिनिधि वापस कमा सकते हैं। – BalusC

+0

यह एक अच्छी टिप है! –

संबंधित मुद्दे

 संबंधित मुद्दे