3

struts2 チェーン アクションに関してかなり複雑な問題があります。私の問題を読んでいただき、ありがとうございます。私はそれを明確に説明するために最善を尽くします。

以下は私のstruts.xmlです:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
    "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
    "http://struts.apache.org/dtds/struts-2.0.dtd">

<struts>
    <constant name="struts.enable.DynamicMethodInvocation" value="false" />
    <constant name="struts.enable.SlashesInActionNames" value="true" />
    <constant name="struts.devMode" value="false" />


    <package name="default" extends="struts-default" namespace="/">
        <action name="test" class="com.bv.test.TestAction1" >
            <result name="success" type="chain">y</result>
        </action>

        <action name="x">
            <result name="success">/index.jsp</result>
        </action>

        <action name="y" class="com.bv.test.TestAction2">
            <result name="success">/index.jsp</result>
        </action>
    </package>
</struts>

私のロジックは次のようなものです: /myapp/test にアクセスすると、TestAction1 がリクエストを処理します。TestAction1 では、次のようにアクション x (構成内の 2 番目のアクション) を「含め」ます。

ResponseImpl myResponse = new ResponseImpl(response);
RequestDispatcher rd = request.getRequestDispatcher("/x.action");
rd.include(request, myResponse); 

そして重要なことは、「x.action」を含めるときにカスタマイズされた ResponseIml を使用していることです。

含めた後、「成功」を返すため、結果はアクション y (構成の 3 番目のアクション) にチェーンされます。
そして最後に、TestAction2 は引き続きリクエストを処理し、成功の結果になり、jsp がレンダリングされるはずですが、空白のページが表示されます。

jsp ファイルは非常に単純です: index.jsp

<h1>Test!</h1>

私の質問/パズルは:

  1. TestAction1 で、ServletActionContext から応答を取得すると、インクルードの前後で異なる応答が返されます。含める前はデフォルトの応答ですが、含めた後、カスタマイズした ResponseImpl のインスタンスを取得しました。私は同じものを得ると期待しています。つまり、デフォルトの応答です。
  2. TestAction2 では、ServletActionContext から応答を取得します。取得したのは、カスタマイズした ResponseIml のインスタンスです。これは私の最も重要なことです。ここでデフォルトの応答インスタンスを取得する必要があると思います。つまり、org.apache.catalina.connector.Response です。
  3. TestAction2 で別の ActionContext を取得しています (TestAction1 で取得した ActionContext と比較して)。

この問題は本当に頭がおかしくなり、何日も費やしました。
アドバイスをいただければ幸いです。
どうもありがとう!!

私のコード:

TestAction1:

public class TestAction1 {
  public String execute() {
    ActionContext ac = ActionContext.getContext();
    System.out.println("Before including: the action context is : " + ac);
    HttpServletRequest request = ServletActionContext.getRequest();
    HttpServletResponse response = ServletActionContext.getResponse();
    System.out.println("Before including: the response is : " + response);

    ResponseImpl myResponse = new ResponseImpl(response);
    RequestDispatcher rd = request.getRequestDispatcher("/x.action");
    try {
      rd.include(request, myResponse); 
      String s = myResponse.getOutput();  
      System.out.println("get from response: " + s);
    }
    catch (Exception e) {
      e.printStackTrace();
    }

    ac = ActionContext.getContext();
    System.out.println("After including : the action context is : " + ac);
    response = ServletActionContext.getResponse();
    System.out.println("After including : the response is : " + response);
    return "success";
  }
}

応答実装:

import java.util.Locale;
import java.io.StringWriter;
import java.io.PrintWriter;
import java.io.OutputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpSession;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpServletResponseWrapper;
import javax.servlet.http.Cookie;
import javax.servlet.jsp.JspWriter;

/**
 * 
 * 
 */
public class ResponseImpl extends HttpServletResponseWrapper  {

  //=========================================================
  // Private fields.
  //=========================================================

  private ServletOutputStream outputStream = null;

  private ByteArrayOutputStream byteArrayOutputStream = null;

  private StringWriter stringWriter = null;

  private PrintWriter printWriter = null;

  private HttpServletResponse _response = null;

  private String contentType= "text/html";

  private String encoding = "UTF-8";

  /**
   *
   */
  class ServletOutputStream extends javax.servlet.ServletOutputStream {

    private OutputStream outputStream = null;

    /**
     *
     */
    ServletOutputStream(ByteArrayOutputStream outputStream) {
      super();
      this.outputStream = outputStream;
    }

    /**
     *
     */
    public void write(int b) throws IOException {
      this.outputStream.write(b);
    }
  }

  //=========================================================
  // Public constructors and methods.
  //=========================================================

  /**
   *
   */
  public ResponseImpl(HttpServletResponse response) {
    super(response);
    this._response = response;
  }

  /**
   *
   */
  public String getOutput() {
    if (this.stringWriter != null) {
      return this.stringWriter.toString();
    }

    if (this.byteArrayOutputStream != null) {
      try {
        return this.byteArrayOutputStream.toString(this.encoding);
      }
      catch (UnsupportedEncodingException e) {
      }
      return this.byteArrayOutputStream.toString();
    }

    return null;
  }

  //=========================================================
  // Implements HttpServletResponse interface.
  //=========================================================

  public void addCookie(Cookie cookie) {
  }

  public void addDateHeader(String name, long date) {
  }

  public void addHeader(String name, String value) {
  }

  public void addIntHeader(String name, int value) {
  }

  public boolean containsHeader(String name) {
    return false;
  }

  public String encodeRedirectURL(String url) {
    if (null != this._response) {
      url = this._response.encodeRedirectURL(url);
    }
    return url;
  }

  public String encodeURL(String url) {
    if (null != this._response) {
      url = this._response.encodeURL(url);
    }
    return url;
  }

  public void sendError(int sc) {
  }

  public void sendError(int sc, String msg) {
  }

  public void sendRedirect(String location) {
  }

  public void setDateHeader(String name, long date) {
  }

  public void setHeader(String name, String value) {
  }

  public void setIntHeader(String name, int value) {
  }

  public void setStatus(int sc) {
  }

  public void resetBuffer() {
  }

  //=========================================================
  // Implements deprecated HttpServletResponse methods.
  //=========================================================

  public void setStatus(int sc, String sm) {
  }

  //=========================================================
  // Implements deprecated HttpServletResponse methods.
  //=========================================================

  public String encodeRedirectUrl(String url) {
    return encodeRedirectURL(url);
  }

  public String encodeUrl(String url) {
    return encodeURL(url);
  }

  //=========================================================
  // Implements ServletResponse interface.
  //=========================================================

  public void flushBuffer() {
  }

  public int getBufferSize() {
    return 0;
  }

  public String getCharacterEncoding() {
    return this.encoding;
  }

  public String getContentType() {
    return this.contentType;
  }

  public Locale getLocale() {
    return null;
  }

  public javax.servlet.ServletOutputStream getOutputStream() {
    if (this.outputStream == null) {
      this.byteArrayOutputStream = new ByteArrayOutputStream();
      this.outputStream =
        new ServletOutputStream(this.byteArrayOutputStream);
    }
    return this.outputStream;
  }

  public PrintWriter getWriter() {
    if (this.printWriter == null) {
      this.stringWriter = new StringWriter();
      this.printWriter = new PrintWriter(this.stringWriter);
    }
    return this.printWriter;
  }

  public boolean isCommitted() {
    return true;
  }

  public void reset() {
  }

  public void setBufferSize(int size) {
  }

  public void setCharacterEncoding(String charset) {
  }

  public void setContentLength(int len) {
  }

  public void setContentType(String type) {
    int needle = type.indexOf(";");
    if (-1 == needle) {
      this.contentType = type;
    }
    else {
      this.contentType = type.substring(0, needle);
      String pattern = "charset=";
      int index = type.indexOf(pattern, needle);
      if (-1 != index) {
        this.encoding = type.substring(index + pattern.length());
      }
    }
  }

  public void setLocale(Locale locale) {
  }
}

TestAction2:

public class TestAction2 {

  public String execute() {
    ActionContext ac = ActionContext.getContext();
    System.out.println("In TestAction 2 : the action context is : " + ac);

    HttpServletResponse response = ServletActionContext.getResponse();
    System.out.println("In TestAction 2 : the response is : " + response);
    return "success";
  }
}

web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app id="WebApp_9" version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">

    <display-name>Struts2 Application</display-name>

     <filter>
        <filter-name>struts2</filter-name>
        <filter-class>
            org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter
        </filter-class>
    </filter>
    <filter-mapping>
        <filter-name>struts2</filter-name>
        <url-pattern>/*</url-pattern>
        <dispatcher>INCLUDE</dispatcher>
        <dispatcher>FORWARD</dispatcher>
        <dispatcher>REQUEST</dispatcher>
    </filter-mapping>
</web-app>

これは私のデバッグ情報です。

  • 含める前: アクション コンテキストは :com.opensymphony.xwork2 です。ActionContext@c639ce
  • 含める前: 応答は次のとおりです: org.apache.catalina.connector.ResponseFacade@8b677f
  • 応答から取得:<h1>Test!</h1>
  • 含めた後: アクション コンテキストは com.opensymphony.xwork2 です。ActionContext@2445d7
  • 含めた後: 応答は次のとおりです: com.bv.test.ResponseImpl@165547d
  • TestAction 2 では、アクション コンテキストは :com.opensymphony.xwork2 です。ActionContext@19478c7
  • TestAction 2 の場合: 応答は次のとおりです: com.bv.test.ResponseImpl@165547d

だから、インクルードの前後に異なる ActionContext インスタンスがあります!!

4

2 に答える 2

0

また、次のことも試すことができます。チェーンを使用する代わりに.. TestAction1 内に元の応答を含む TestAction2 を含めます。戻り値としてアクションから 'none' を返します。

public class TestAction1 {
  public String execute() {
    ActionContext ac = ActionContext.getContext();
    System.out.println("Before including: the action context is : " + ac);
    HttpServletRequest request = ServletActionContext.getRequest();
    HttpServletResponse response = ServletActionContext.getResponse();
    System.out.println("Before including: the response is : " + response);

    ResponseImpl myResponse = new ResponseImpl(response);
    RequestDispatcher rd = request.getRequestDispatcher("/x.action");
    try {
      rd.include(request, myResponse); 
      String s = myResponse.getOutput();  
      System.out.println("get from response: " + s);
    }
    catch (Exception e) {
      e.printStackTrace();
    }



      RequestDispatcher rd = request.getRequestDispatcher("/y.action");
        try {
          rd.include(request, response); 
        }
        catch (Exception e) {
          e.printStackTrace();
        } finally {
          return "none";
        }
      }
    }
于 2013-05-05T06:40:45.933 に答える