2013-09-06 32 views
5

Trong một nỗ lực để hiểu cách struts2 tải cấu hình của nó, tôi muốn hiển thị đường dẫn đến JSP sẽ được hiển thị. Với tệp struts.xml rất tối thiểu sau:Hiểu nội bộ của Struts2: Cấu hình kết quả

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

Tôi muốn có thể đăng nhập "/WEB-INF/content/test.jsp" từ bên trong hành động. Căn cứ vào hành động sau đây:

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

Có ba báo cáo in mà cho kết quả sau trên giao diện điều khiển của tôi:

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

Từ thử nghiệm cả hai kết quả "invocation.getResult()" và resultcode là null trước PreResultListener được gọi nhưng trong số PreResultListener mã kết quả được đặt, nhưng kết quả vẫn trả về giá trị rỗng!

Từ javadoc của getResult() phương pháp:

Nếu ActionInvocation đã được thực hiện trước và kết quả là một thể hiện của {@link ActionChainResult}, phương pháp này sẽ đi bộ xuống các chuỗi của ActionChainResult cho đến khi nó tìm thấy kết quả không phải là chuỗi, trong đó sẽ được trả lại. Nếu kết quả của ActionInvocation chưa được thực hiện trước đó, cá thể Kết quả sẽ được tạo và điền với thông số kết quả.

Có vẻ khá rõ ràng rằng bản sao kết quả là không phải là đang được tạo.

Vậy làm cách nào để hiển thị "/WEB-INF/content/test.jsp" trong hành động này? Đây không phải là để sử dụng struts2 điển hình, tôi muốn thử nghiệm một nhà cung cấp cấu hình mà có điều gì đó sai trái với việc xây dựng kết quả cho hành động, hy vọng hiểu tại sao điều này không hoạt động sẽ cho phép tôi khắc phục điều đó.

+0

Bạn có dự án thử nghiệm này là SSCCE không? 1, điều thú vị là –

+0

Nếu bạn gửi email cho tôi (phải ở trong tiểu sử của tôi, hãy sử dụng gmail) Tôi sẽ gửi cho bạn một bản sao. – Quaternion

+1

'ActionInvocatio # getResult' là null bởi vì hành động trả về" thành công "thay vì instance của Result và sau đó không có null. Tôi biết, nó không phải là tài liệu nhưng hành động có thể trả lại kết quả trực tiếp ;-) –

Trả lời

4

Vấn đề là bạn muốn nhận được kết quả từ lời gọi hành động, bạn không nên. Kết quả gọi hành động là để sử dụng nội bộ, và có lẽ nên được bảo vệ.

Để có kết quả, bạn nên tham khảo ActionConfig và nhận kết quả từ đó.

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

Vâng vấn đề là tôi đã xây dựng cấu hình hành động với một nhà cung cấp cấu hình tùy chỉnh, với cấu hình này các hành động tôi cung cấp được tìm thấy, nhưng kết quả là null ... hmm bạn đã cho tôi một cái gì đó để thử ... – Quaternion

+1

Nó hoạt động! ResultBuilder mất một tham số "location". Tôi nghĩ đây là con đường kết quả! Thay vào đó, tôi chỉ định cung cấp nó như một tham số. Việc ánh xạ xml vào các lớp không phải là tài liệu rất tốt. Vì vậy, bây giờ các nhà cung cấp cấu hình tùy chỉnh đang làm việc ... cũng một phần. Có vẻ như tôi cần thông số vị trí vì lý do nào đó ... khi tôi không đặt, tôi nhận được "org.apache.jasper.JasperException: Bộ điều phối Struts không thể tìm thấy" nhưng ngay cả khi tôi xây dựng nó với LocationImpl mới ("" , "") hành động là hạnh phúc. Ồ, một câu hỏi cho mỗi câu hỏi. – Quaternion

+1

Điều này thật tuyệt ... ngoại trừ tôi muốn sửa đổi các tham số resultConfig động, và đó là một UnmodifiableMap - vì vậy tôi đã thử tạo một ResultConfig mới và gắn nó vào bản đồ config.getResults() - nhưng nó cũng là một UnmodifiableMap. – dmansfield

2

Một vài điều:

  1. Tại thời điểm trong thời gian mà bạn đang cố gắng để in + getResultCode() không có mã như vậy tồn tại được nêu ra - nhớ đó là hành động mà sẽ quyết định kết quả bằng cách trả lại chuỗi kết quả . Vì vậy, bạn sẽ muốn in điều đó trong bất kỳ bộ chặn nào bạn có trong hành động đó, sau phần invocation.invoke().

  2. getResultCode() sẽ trả lại chuỗi kết quả (thành công, lỗi) chứ không phải đường dẫn tương ứng.

+0

Cũng giống như tôi đã đi ngủ tôi nhận ra rằng "resultCode" đã được hiển thị trước khi hành động. Mặc dù nó _is_ kết quả mà tôi muốn render (cũng chỉ là một giá trị địa chỉ không null sẽ được yên tâm). Nó làm cho cảm giác hoàn hảo rằng hành động cần phải được gọi trước khi mã kết quả có thể được biết đến tuy nhiên, nó là kết quả mà tôi không muốn là kết quả. Hơn bạn cho sự giúp đỡ, tôi có thể đã được rõ ràng hơn. – Quaternion

1

ActionContext.getContext().getActionInvocation().invokeActionOnly() sẽ trả về chuỗi (thành công, đầu vào, lỗi, v.v.).

Các vấn đề liên quan