2013-09-06 17 views
5

Aby zrozumieć, w jaki sposób struts2 ładuje swoją konfigurację, chciałbym wyświetlić ścieżkę do strony JSP, która byłaby renderowana. Biorąc pod uwagę następujące bardzo minimalny struts.xml:Opis wewnętrznych elementów Struts2: Konfiguracja wyników

<struts> 
    <constant name="struts.devMode" value="true" /> 
    <constant name="struts.ui.theme" value="simple" /> 

    <package name="base" namespace="/"> 
     <result-types> 
      <result-type name="dispatcher" class="org.apache.struts2.dispatcher.ServletDispatcherResult" default="true"/> 
     </result-types> 
     <action name="test" class="com.kenmcwilliams.badwebapp.action.Test"> 
      <result>/WEB-INF/content/test.jsp</result> 
     </action> 
    </package> 
</struts> 

Chcę być w stanie zalogować się „/WEB-INF/content/test.jsp” od wewnątrz działania. Biorąc pod uwagę następujące działania:

package com.quaternion.badwebapp.action; 

import com.opensymphony.xwork2.ActionContext; 
import com.opensymphony.xwork2.ActionInvocation; 
import com.opensymphony.xwork2.ActionSupport; 
import com.opensymphony.xwork2.interceptor.PreResultListener; 
import java.util.logging.Level; 
import java.util.logging.Logger; 

public class Test extends ActionSupport { 
    //used for a sanity test on JSP 
    public String getMessage() { 
     return "From test"; 
    } 

    @Override 
    public String execute() throws Exception { 
     System.out.println("ActionContext.getContext().getActionInvocation().getResultCode(): " + ActionContext.getContext().getActionInvocation().getResultCode()); 
     ActionInvocation ai = ActionContext.getContext().getActionInvocation(); 
     ai.addPreResultListener(new PreResultListener() { 
      @Override 
      public void beforeResult(ActionInvocation invocation, String resultCode) { 
       try { 
        System.out.println("PreResultListener resultCode: " + resultCode); 
        System.out.println("PreResultListener result: " + invocation.getResult()); 
       } catch (Exception ex) { 
        Logger.getLogger(Test.class.getName()).log(Level.SEVERE, null, ex); 
       } 
      } 
     }); 
     return SUCCESS; 
    } 
} 

Istnieją trzy oświadczenia drukowania, które produkują następujące dane wyjściowe na mojej konsoli:

INFO: ActionContext.getContext().getActionInvocation().getResultCode(): null 
INFO: PreResultListener resultCode: success 
INFO: PreResultListener result: null 

Od testowania zarówno „invocation.getResult()” wynik i ResultCode jest null przed PreResultListener jest wywoływany, ale w ciągu PreResultListener kod wyniku jest ustawiony, ale wynik nadal zwraca wartość null!

Z JavaDoc z getResult() metoda:

Jeśli ActionInvocation zostało wykonane przed i wynik jest instancją {@link ActionChainResult}, metoda ta będzie schodzić z łańcucha ActionChainResult, dopóki nie znajdzie wyniku niezwiązanego, który zostanie zwrócony. Jeśli wynik ActionInvocation nie został wcześniej wykonany, instancja wyniku zostanie utworzona i zapełni się parametrami wyników w postaci .

wydaje się dość oczywiste, że instancja wynik jest nie tworzone.

Jak wyświetlić "/WEB-INF/content/test.jsp" w ramach tej akcji? Nie jest to typowe użycie struts2, chcę przetestować dostawcę konfiguracji, dla którego jest coś nie tak z budową wyniku działania, mam nadzieję, że zrozumienie, dlaczego to nie działa, pozwoli mi to naprawić.

+0

Czy masz ten projekt testowy jako SSCCE? +1, to jest interesujące –

+0

Jeśli wyślesz mi e-mail (powinien być na moim profilu, użyj adresu gmail) Wyślę ci kopię. – Quaternion

+1

'ActionInvocatio # getResult' ma wartość null, ponieważ akcja zwróciła" sukces "zamiast instancji wyniku, a następnie nie ma wartości zerowej. Wiem, że nie jest to udokumentowane, ale działania mogą zwrócić wynik bezpośrednio ;-) –

Odpowiedz

4

Problem polega na tym, że chcesz uzyskać wynik z wywołania akcji, nie powinieneś. Wynik wywołania akcji jest przeznaczony do użytku wewnętrznego i prawdopodobnie powinien być chroniony.

Aby uzyskać wynik, należy skonsultować się z ActionConfig i uzyskać z tego wynik.

ActionInvocation invocation = ActionContext.getContext().getActionInvocation(); 
ActionProxy proxy = invocation.getProxy(); 
ActionConfig config = proxy.getConfig(); 
Map<String, ResultConfig> results = config.getResults(); 
ResultConfig resultConfig = results.get(Action.SUCCESS); 
String lastFinalLocation = null; 
Map<String, String> params = resultConfig.getParams(); 
if (resultConfig.getClassName().equals("org.apache.struts2.dispatcher.ServletDispatcherResult")) { 
    lastFinalLocation = params.get("location"); 
} 
System.out.println("location: " + lastFinalLocation); 
+0

Tak, tak, problem polega na tym, że zbudowałem konfigurację działania z dostawcą konfiguracji niestandardowej, dzięki tej konfiguracji można znaleźć akcje, które zapewniłem, ale wynik jest zerowy ... hmm dałeś mi coś do spróbowania ... – Quaternion

+1

Udało się! ResultBuilder ma parametr "location". Myślałem, że to jest ścieżka wyników! Zamiast tego powinienem podać go jako parametr. Mapowanie xml na klasy nie jest dobrze udokumentowane. Więc teraz niestandardowy dostawca konfiguracji działa ... częściowo. Wygląda na to, że potrzebuję parametru lokalizacji z jakiegoś powodu ... gdy go nie ustawię, dostaję "org.apache.jasper.JasperException: Nie można znaleźć programu rozsyłającego Struts", ale nawet jeśli skonstruuję go z nowym LocationImpl ("" , "") akcja jest szczęśliwa. No cóż, jedno pytanie za, dobrze pytanie. – Quaternion

+1

To jest świetne ... z wyjątkiem tego, że chcę zmodyfikować parametry resultConfig dynamicznie, i jest to UnmodifiableMap - więc próbowałem zbudować nowy ResultConfig i przykleić go na mapie config.getResults() - ale jest to również UnmodifiableMap. – dmansfield

2

Kilka rzeczy:

  1. W tej chwili w czasie, gdy próbujesz wydrukować + getResultCode() ma takiego kodu istnieje jeszcze - pamiętaj, że jest to działanie, które zadecyduje wynik wracając ciąg wynik . Więc będziesz chciał wydrukować to w dowolnym przechwytywaczu, który masz w tej akcji, po części invocation.invoke().

  2. getResultCode() zwróci ciąg wyniku (sukces, błąd), a nie odpowiadającą ścieżkę.

+0

Podobnie jak ja zasypiałem zdałem sobie sprawę, że "resultCode" był wyświetlany przed akcją. Chociaż jest to wynik, który chcę renderować (dobrze tylko wartość adresu o wartości zerowej byłaby uspokajająca). To ma doskonały sens, że akcja musi zostać wywołana, zanim kod wyniku będzie znany, ale jest to wynik, który nie chce kodu wynikowego. Niż za pomoc, mógłbym być jaśniejszy. – Quaternion

1

ActionContext.getContext().getActionInvocation().invokeActionOnly() zwróci ciąg (sukces, wejście, błędów, itp).

Powiązane problemy