2010-10-27 14 views
26

में एक पुनर्निर्देशन कैसे करें मेरे पास एक वेब-एप्लिकेशन है जहां उपयोगकर्ताओं को सीधे कुछ विशिष्ट पृष्ठों पर भेजा जा सकता है (जैसे एक पृष्ठ जहां वह कोई आइटम देख या संपादित कर सकता है)। इसे प्राप्त करने के लिए, हम एक विशिष्ट यूआरएल प्रदान करते हैं। ये यूआरएल के बाहर वर्तमान वेब-एप्लिकेशन (यानी वे किसी अन्य वेब-एप्लिकेशन में या ईमेल में मौजूद हो सकते हैं) के बाहर स्थित हैं।जेएसएफ

  • कार्रवाई पेज जहाँ उपयोगकर्ता पुनः निर्देशित किया जाएगा प्रतिनिधित्व करता है:

    यूआरएल http://myserver/my-app/forward.jsf?action=XXX&param=YYY, जहां तरह दिखता है। faces-config.xml में navigation-case में किसी भी जेएसएफ कार्रवाई के के रूप में आप इसे देख सकते हैं।

    • http://myserver/my-app/forward.jsf?action=viewItem&actionParam=1234
    • http://myserver/my-app/forward.jsf?action=editItem&actionParam=1234
    • :
    • actionParam पिछली कार्रवाई (आम तौर पर एक आइटम आईडी)

    उदाहरण के लिए, मैं यूआरएल इस तरह हो सकता है के लिए एक पैरामीटर है

बेशक, मेरे पास जावा क्लास (बीन) है जो कुछ की जांच करेगी सुरक्षा बाधाएं (यानी क्या उपयोगकर्ता को संबंधित आइटम को देखने/संपादित करने की अनुमति है?) और फिर उपयोगकर्ता को सही पृष्ठ पर रीडायरेक्ट करें (जैसे edit.xhtml, view.xhtml या access-denied.xhtml)।


वर्तमान कार्यान्वयन

वर्तमान में, हम एक बुनियादी आगे का रास्ता पूरा करने के लिए किया है। उपयोगकर्ता लिंक पर क्लिक करता है, निम्नलिखित एक्सएचटीएमएल पृष्ठ कहा जाता है:

<html> 
    <body id="forwardForm"> 
     <h:inputHidden id="myAction" binding="#{forwardBean.hiddenAction}"/> 
     <h:inputHidden id="myParam" binding="#{forwardBean.hiddenActionParam}"/> 
     <h:commandButton id="forwardBtn" actionListener="#{forwardBean.doForward}" style="display: none;"/> 
    </body> 
    <script type="text/javascript"> 
     document.getElementById('forwardForm:forwardBtn').click(); 
    </script> 
</html> 

आप देख सकते हैं, मैं अपने जावा सेम में दो <h:inputHidden> घटकों बाँध। उनका उपयोग action और actionParam अनुरोध पैरामीटर (FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap().get("actiontParam"); का उपयोग करके) के मूल्य को संग्रहीत करने के लिए किया जाएगा। मैं doForward विधि भी प्रदान करता हूं जिसे पृष्ठ प्रदान किए जाने पर तुरंत कॉल किया जाएगा, जो उपयोगकर्ता को वास्तविक पृष्ठ पर रीडायरेक्ट करेगा (फिर से)। विधि है:

public void doForward(ActionEvent evt) { 
    FacesContext facesContext = FacesContext.getCurrentInstance(); 
    String redirect = // define the navigation rule that must be used in order to redirect the user to the adequate page... 
    NavigationHandler myNav = facesContext.getApplication().getNavigationHandler(); 
    myNav.handleNavigation(facesContext, null, redirect); 
} 

यह समाधान काम कर रहा है, लेकिन मैं उस के साथ दो समस्याएं हैं:

  • मुझे पसंद नहीं है जिस तरह से यह लागू किया गया है। मुझे यकीन है कि मेरे पास कुछ आसान हो सकता है (Servlet का उपयोग कर?)।
  • यह समाधान जावास्क्रिप्ट का उपयोग कर रहा है, और मुझे जावास्क्रिप्ट का उपयोग नहीं करना चाहिए (क्योंकि यह आगे पुराने ब्लैकबेरी उपयोगकर्ताओं द्वारा उपयोग किया जा सकता है, जहां जावास्क्रिप्ट समर्थित नहीं है)।

तो मेरा प्रश्न इस पुनर्निर्देशन/आगे की सुविधा को दोबारा कैसे बदला जाए?

तकनीकी जानकारी

जावा 1.6, JSF 1.2, Facelets, Richfaces

+0

मुझे यकीन है कि क्या यह सबसे अच्छा है या नहीं करने के लिए नहीं कर रहा हूँ, लेकिन आप उपयोगकर्ता एक लिंक पर क्लिक करने के लिए दे रही है और मध्यवर्ती एक्सएचटीएमएल का उपयोग करने और जावास्क्रिप्ट कर रहे हैं क्लिक करें, लेकिन क्यों आप इसे एक सर्वलेट की ओर इशारा करते नहीं कर रहे हैं और वहाँ से आप इस परिदृश्य मैं मध्यवर्ती एक्सएचटीएमएल क्यों सर्वलेट का उपयोग नहीं करने के बजाय मतलब संभाल कर सकते हैं। मैं अपने JSF env –

+0

@org में हमारे अपने सर्वलेट जोड़ने के लिए बुरा नहीं लगता है: यह निश्चित रूप से सर्वलेट्स बिना किया जा सकता। एक सर्वलेट का उपयोग केवल अतिरिक्त रखरखाव सिरदर्द जोड़ देगा क्योंकि इसमें नेविगेशन मामलों में तत्काल पहुंच नहीं है। – BalusC

+0

@ बाल्लूसी धन्यवाद, मैं जानना चाहता हूं, कैसे? , क्या हम सीधे एक्सएचटीएमएल पर जेएसपी स्क्रिप्टलेट का उपयोग कर सकते हैं? –

उत्तर

28

सेट तो faces-config.xml में कामयाब गुण के रूप में प्राप्त क्वेरी पैरामीटर है कि आप उन्हें मैन्युअल रूप से इकट्ठा करने के लिए की जरूरत नहीं है:

<managed-bean> 
    <managed-bean-name>forward</managed-bean-name> 
    <managed-bean-class>com.example.ForwardBean</managed-bean-class> 
    <managed-bean-scope>request</managed-bean-scope> 
    <managed-property> 
     <property-name>action</property-name> 
     <value>#{param.action}</value> 
    </managed-property> 
    <managed-property> 
     <property-name>actionParam</property-name> 
     <value>#{param.actionParam}</value> 
    </managed-property> 
</managed-bean> 

इस तरह अनुरोध forward.jsf?action=outcome1&actionParam=123 दूँगी JSF action के रूप में स्थापित action और actionParam मापदंडों और actionParamForwardBean के गुण।

एक छोटा सा दृश्य बनाएं forward.xhtml (इतना छोटा है कि यह डिफ़ॉल्ट प्रतिक्रिया बफर (अक्सर 2 केबी) में फिट बैठता है ताकि इसे नेविगेशनहैंडर द्वारा रीसेट किया जा सके, अन्यथा आपको servletcontainer की कॉन्फ़िगरेशन में प्रतिक्रिया बफर बढ़ाना होगा), जो आमंत्रित करता है f:view की beforePhase पर एक सेम विधि:

<!DOCTYPE html> 
<html xmlns:f="http://java.sun.com/jsf/core"> 
    <f:view beforePhase="#{forward.navigate}" /> 
</html> 

ForwardBean इस तरह दिख सकता:

public class ForwardBean { 
    private String action; 
    private String actionParam; 

    public void navigate(PhaseEvent event) { 
     FacesContext facesContext = FacesContext.getCurrentInstance(); 
     String outcome = action; // Do your thing? 
     facesContext.getApplication().getNavigationHandler().handleNavigation(facesContext, null, outcome); 
    } 

    // Add/generate the usual boilerplate. 
} 

navigation-rule बोलती ही (<redirect /> प्रविष्टियों जो ExternalContext#redirect() बजाय ExternalContext#dispatch() करना होगा कवर के तहत ध्यान दें) के लिए:

<navigation-rule> 
    <navigation-case> 
     <from-outcome>outcome1</from-outcome> 
     <to-view-id>/outcome1.xhtml</to-view-id> 
     <redirect /> 
    </navigation-case> 
    <navigation-case> 
     <from-outcome>outcome2</from-outcome> 
     <to-view-id>/outcome2.xhtml</to-view-id> 
     <redirect /> 
    </navigation-case> 
</navigation-rule> 

एक विकल्प के रूप

<!DOCTYPE html> 
<html>#{forward}</html> 

forward.xhtml उपयोग करने के लिए है और navigate() विधि अपडेट

: @PostConstruct (जो सेम के निर्माण और सभी प्रबंधित संपत्ति सेटिंग के बाद लागू किया जाएगा) पर लागू किया जा करने के लिए
@PostConstruct 
public void navigate() { 
    // ... 
}  

यह वही प्रभाव पड़ता है, फिर भी दृश्य पक्ष वास्तव में आत्म दस्तावेज़ीकृत नहीं है। सभी यह मूल रूप से करता है मुद्रण ForwardBean#toString() (और यदि अभी तक मौजूद नहीं इसके द्वारा परोक्ष सेम के निर्माण) है। JSF2 उपयोगकर्ताओं के लिए


ध्यान दें, वहाँ <f:event type="preRenderView"> द्वारा रीडायरेक्ट/नेविगेशन से निपटने में <f:viewParam> और अधिक मजबूत तरीके के साथ पैरामीटर प्रदान करने का एक क्लीनर तरीका है। अन्य लोगों के अलावा यह भी देखें:

+0

मुझे '' का उपयोग करने का विचार पसंद है। हालांकि, मेरे पहले परीक्षण सफल नहीं हैं, क्योंकि * पहले चरण * विधि नहीं कहा जाता है। मुझे समझ में नहीं आता क्यों ... – romaintaz

+0

मैं अभी भी समझ में नहीं क्यों पहला समाधान काम नहीं करता है (हो सकता है मुझे लगता है कि के लिए एक अलग पोस्ट पैदा करेगा), लेकिन दूसरा समाधान वास्तव में काम कर रहा है! धन्यवाद एक बहुत! – romaintaz

+0

'PhaseEvent' तर्क उपस्थित था? जेएसएफ इंप/वर्जन वास्तव में क्या है? मुझे यह स्वीकार करना होगा कि मैंने 2.1-रात को चेहरे-कॉन्फ़िगरेशन के साथ 1.2 के रूप में घोषित किया है (ताकि 2.x फीचर्स काम नहीं करेंगे)। यह विशेषता 1.2 में पेश की गई थी (इसलिए जीता ' टी 1.1 या उससे अधिक उम्र में काम नहीं करते हैं) लेकिन '@ पोस्टकस्ट्रक्चर' भी है। – BalusC

1

आप ActionListener के बजाय कार्रवाई का उपयोग करना चाहिए:

<h:commandLink id="close" action="#{bean.close}" value="Close" immediate="true" 
            /> 

और करीब विधि में आप सही तरह कुछ:

public String close() { 
    return "index?faces-redirect=true"; 
} 

जहां इंडेक्स आपके पृष्ठों में से एक है (index.xhtml)

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

+0

'एक्शन' या 'एक्शनलिस्टर' का उपयोग करके मेरी वर्तमान समस्या पर बिल्कुल कोई प्रभाव नहीं पड़ता है। – romaintaz

+0

और ओपी JSF 1.x उपयोग कर रहा है, नहीं 2. x साथ ही, रीडायरेक्ट अनुरोध पैरामीटर खोने का कारण बन जाएगा। – BalusC

5
FacesContext context = FacesContext.getCurrentInstance(); 
HttpServletResponse response = (HttpServletResponse)context.getExternalContext().getResponse(); 
response.sendRedirect("somePage.jsp"); 
+0

मेरे प्रश्न का उत्तर नहीं देता है। आप मुझे यह कोड कहां रखना चाहते हैं? और बिना किसी उपयोगकर्ता इंटरैक्शन और न ही जावास्क्रिप्ट कॉल के इसे कैसे कहा जा सकता है? – romaintaz

1

संपादित 2

मैं अंत में इस तरह मेरे आगे कार्रवाई को लागू करने से एक समाधान पाया:

private void applyForward() { 
    FacesContext facesContext = FacesContext.getCurrentInstance(); 
    // Find where to redirect the user. 
    String redirect = getTheFromOutCome(); 

    // Change the Navigation context. 
    NavigationHandler myNav = facesContext.getApplication().getNavigationHandler(); 
    myNav.handleNavigation(facesContext, null, redirect); 

    // Update the view root 
    UIViewRoot vr = facesContext.getViewRoot(); 
    if (vr != null) { 
     // Get the URL where to redirect the user 
     String url = facesContext.getExternalContext().getRequestContextPath(); 
     url = url + "/" + vr.getViewId().replace(".xhtml", ".jsf"); 
     Object obj = facesContext.getExternalContext().getResponse(); 
     if (obj instanceof HttpServletResponse) { 
      HttpServletResponse response = (HttpServletResponse) obj; 
      try { 
       // Redirect the user now. 
       response.sendRedirect(response.encodeURL(url)); 
      } catch (IOException e) { 
       e.printStackTrace(); 
      } 
     } 
    } 
} 

यह काम करता है (कम से कम मेरा पहला परीक्षण के बारे में), लेकिन मैं अभी भी डॉन जिस तरह से इसे लागू किया गया है ... कोई बेहतर विचार?


संपादित यह समाधान नहीं काम करता है। दरअसल, जब doForward() फ़ंक्शन कहा जाता है, तो जेएसएफ लाइफसाइक्ल पहले ही शुरू हो चुका है, और उसके बाद एक नया अनुरोध फिर से संभव नहीं है।

private boolean actionDefined = false; 
private boolean actionParamDefined = false; 

public void setHiddenActionParam(HtmlInputHidden hiddenActionParam) { 
    this.hiddenActionParam = hiddenActionParam; 
    String actionParam = FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap().get("actionParam"); 
    this.hiddenActionParam.setValue(actionParam); 
    actionParamDefined = true; 
    forwardAction(); 
} 

public void setHiddenAction(HtmlInputHidden hiddenAction) { 
    this.hiddenAction = hiddenAction; 
    String action = FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap().get("action"); 
    this.hiddenAction.setValue(action); 
    actionDefined = true; 
    forwardAction(); 
} 

private void forwardAction() { 
    if (!actionDefined || !actionParamDefined) { 
     // As one of the inputHidden was not binded yet, we do nothing... 
     return; 
    } 
    // Now, both action and actionParam inputHidden are binded, we can execute the forward... 
    doForward(null); 
} 

यह समाधान किसी भी जावास्क्रिप्ट को शामिल नहीं करता: इस समस्या को हल करने के लिए


एक विचार है, लेकिन मैं वास्तव में यह पसंद नहीं है, setBindedInputHidden() विधि से एक के दौरान doForward() कार्रवाई के लिए मजबूर करने के लिए है कॉल, और काम करता है काम नहीं करता है।

+1

यह वास्तव में अजीब है :) 'हैंडल नेविगेशन()' पूरी तरह से अनावश्यक है (इसे बदले में 'respond.sendRedirect() ') द्वारा ओवरराइड किया गया है और' बाहरी कॉन्टैक्स्ट 'में' रीडायरेक्ट()' विधि है। – BalusC