Struts2をやってみる (4) - StrutsResultSupportクラスを作る -

2013-09-17T00:00:00+00:00 Java Struts2

前回では書いて無かったけど、で使えるtypeに指定出来るようにするには

  • StrutsResultSupportを継承したクラスを定義する
  • struts.xmlにてで定義したStrutsResultSupportを設定する

というような方式を行う事で独自で作る事も可能な模様。という事でやってみた

src/main/resources/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.devMode" value="true" />

    <package name="sample" extends="struts-default" namespace="/sample">
        <result-types>
            <result-type name="sample" class="sample.dispatcher.SampleResult" />
        </result-types>

        <action name="test1" class="sample.action.IndexAction" method="test1">
            <result type="sample">
                <param name="outputName">o</param>
            </result>
        </action>

    </package>
</struts>

src/main/java/sample/dispatcher/SampleResult.java

要件は上記のstruts.xmlで指定しているoutputNameで作用するゲッターメソッドから値を取得してそれをHttpServletResponseを通じてレスポンスを出すだけ

package sample.dispatcher;

import java.io.PrintWriter;
import javax.servlet.http.HttpServletResponse;
import org.apache.struts2.dispatcher.StrutsResultSupport;
import com.opensymphony.xwork2.ActionInvocation;

public class SampleResult extends StrutsResultSupport {

    private static final long serialVersionUID = 1L;
    protected String outputName = "output";


    @Override
    protected void doExecute(String finalLocation, ActionInvocation invocation)
        throws Exception {

        // ライフサイクル上の?スタックに入ってる参照されるActionSupportから値を取得。取得にはゲッターメソッドが使用される。
        String output = (String)invocation.getStack().findValue(
            conditionalParse(outputName, invocation)
        );

        HttpServletResponse response = (HttpServletResponse)invocation
            .getInvocationContext()
            .get(HTTP_RESPONSE);

        PrintWriter out = response.getWriter();
        out.print(output);
        out.flush();
        out.close();
    }

    public void setOutputName(String outputName) {
        this.outputName = outputName;
    }
}

<param name="outputName">で指定した名前から特定されるゲッターメソッドを通じて値を取得して表示するっていうだけ

んまぁ、なんらかのシリアライザ的な事を利用したレスポンスとかを出したりするっていう場合に使ったりするんじゃないかなと。まぁ大体のはプラグインがありそうですけど

余談: StrutsResultSupportのテストを書くには

package sample.dispatcher;

import org.apache.struts2.ServletActionContext;
import org.apache.struts2.StrutsTestCase;
import org.junit.Test;
import org.springframework.mock.web.MockHttpServletResponse;

import com.opensymphony.xwork2.Action;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.mock.MockActionInvocation;
import com.opensymphony.xwork2.util.ValueStack;

import static org.junit.Assert.*;
import static org.hamcrest.Matchers.*;

public class SampleResultTestCase extends StrutsTestCase {

    private SampleResult result;
    private MockActionInvocation mai;
    private TestAction action;

    @Override
    protected void setUp() throws Exception {
        super.setUp();

        response = new MockHttpServletResponse();
        result = new SampleResult();
        action = new TestAction();

        ActionContext context = ActionContext.getContext();

        ValueStack stack = context.getValueStack();
        stack.push(action);

        mai = new MockActionInvocation();
        mai.setAction(action);
        mai.setStack(stack);
        mai.setInvocationContext(context);

        context.put(ServletActionContext.HTTP_RESPONSE, response);
    }

    @Test
    public void test_doExecute() throws Exception {
        assertThat(action.execute(), is(ActionSupport.SUCCESS));

        // result.setOutputName("o");
        result.doExecute(null, mai);
        assertThat(response.getContentAsString(), is("hoge"));
    }

    protected class TestAction implements Action {

        private String output;

        public String getOutput() {
            return output;
        }

        @Override
        public String execute() throws Exception {
            output = "hoge";
            return SUCCESS;
        }
    }
}

っていう感じでMockActionInvocationを利用してStrutsResultSupport#doExecuteを実行しちゃえば良い。でその際にInvocation内部にはいるスタックとかを自分で入れとかなあかん模様

んまぁ参考としてはソース読めば良いんじゃねーかと https://github.com/apache/struts/blob/develop/core/src/test/java/org/apache/struts2/dispatcher/StreamResultTest.java

Struts2をやってみる (5) - struts.xmlに定義する事なくActionをテストする - Struts2をやってみる (3) - <result>のtypeに関して