struts2でresultの設定をxmlにもアノテーションにも指定しない方法

概要

struts2では基本的にはresultの設定はstruts.xmlに定義します。
(ここでは詳細は省きます)

ただ、最近はconvention-pluginを使ってxml設定せずに画面表示させたり、リダイレクト等が必要なときはアノテーションを使って設定していることが多いと思います。

しかし、struts2のコードを見てみると他の方法も使えることが分かりました。
それは、アクションで"success"のような文字列を返すのではなく直接Resultオブジェクトを返すという方法です。
どういうことか例を示します。

struts2とconvention-pluginの基本的な部分が分かっているという前提で進めます。
まずはコードから。

ResultAction.java
package kamegu.action.fwtest;

import org.apache.struts2.dispatcher.ServletRedirectResult;

import com.opensymphony.xwork2.Action;
import com.opensymphony.xwork2.Result;

public class ResultAction implements Action {

	@Override
	public String execute() throws Exception {
		return SUCCESS;
	}

	public Result jump() {
		ServletRedirectResult result = new ServletRedirectResult();
		result.setLocation("./result");
		return result;
	}
}
result.jsp
<%@page contentType="text/html; charset=UTF-8"%>
<%@ taglib prefix="s" uri="/struts-tags"%>
<%@ taglib prefix="sj" uri="/struts-jquery-tags"%>
<!DOCTYPE HTML>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Insert title here</title>
</head>
<body>
アクションクラス動作確認用
</body>
</html>

今回は次のようなリクエストを行うと、
/myapp/fwtest/result!jump 
次の画面にリダイレクトさせます。
/myapp/fwtest/result
ResultAction.javaのexecute()とjump()にブレークポイントを置くかSystem.out.println("分かりやすいメッセージ")みたいにすればリダイレクトしていることが分かると思います。

この後でフレームワークの説明をします

パーフェクトJava (PERFECT SERIES) (PERFECT SERIES 2)

パーフェクトJava (PERFECT SERIES) (PERFECT SERIES 2)

struts2上の動き

該当部分のみ説明します。

リクエストがあると、com.opensymphony.xwork2.DefaultActionInvocation#invokeAction()から対象のアクションクラスの対象のメソッドが実行され、結果がsaveResultメソッドに渡されます。

で、この結果オブジェクトはStringクラスではなくObjectクラスで、saveResultメソッド内ではこのオブジェクトがcom.opensymphony.xwork2.Resultインターフェースを実装しているかどうかを判断し、実装している場合はexplicitResultフィールドにそのオブジェクトをセットしてnullを返し、実装していない場合は結果オブジェクトをStringにキャストして返します。

この結果を元に処理を行うのがexecuteResultメソッドですが、そこで使用するResultオブジェクトはexplicitResultフィールドが!=nullの場合はその値が使用されます。
explicitResultがnullで文字列がアクションから返されている場合はそれを元に設定からResultインスタンスが導かれます。

つまり

アクションクラスでcom.opensymphony.xwork2.Resultを返せばそのオブジェクトを元に処理が行われ、文字列を返せばそれを元に設定どおりの処理が行われる