Struts2をやってみる (4) - StrutsResultSupportクラスを作る -
前回では書いて無かったけど、
- 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