SAStruts

主な特徴

アノテーションの活用により設定ファイルの記述がほとんど不要

ActionやActionFormをPOJOとして、テストが容易

アプリケーションの共通処理

・フィルタを適用

・スーパークラスやユーティリティクラスのメソッドを呼び出す

・アクション・サービスにAOPを適用

・リクエストプロセッサを拡張

SAStrutsの処理の流れ

★ActionからJSPへの値の受け渡し

<bean:write name="sampleForm" property="message" /> Strutsタグ

<c:out value="${sampleForm.message}" /> JSTLタグ

${f:h(sampleForm.message)} EL

★ActionとService

public abstract class AbstractAction {

@Resource

protected HttpServletRequest httpServletRequest;


@Resource

protected HttpServletResponse httpServletResponse;


...

}

public abstract class AbstractService {

@Resource

protected JdbcManager jdbcManager;


@Resource

protected S2CSVCtrlFactory csvCtrlFactory;


...

}

public class MyAction extends AbstractAction {

@Resource

@ActionForm

protected MyForm myForm;

@Resource

protected MyService myService;

@Resource

protected MySessionDto mySessionDto;

@Execute(validator=false)

@RemoveSession(name="xxx_mySessionDto")

public String back() {

return "main.jsp";

}

...

}

public class MyService extends AbstractService {

@Resource

protected MyLogic myLogic;

@TransactionAttribute(TransactionAttributeType.NEVER)

public void execute() {

...

}

...

}

@Component(instance=InstanceType.SESSION)

public class MySessionDto implements Serializable {

...

}

public class MyForm {

// targetは入力チェックを有効にするActionの実行メソッドを指定

@Required(arg0=@Arg(key="お名前", resource=false), target="submit")

public String name;

...

}

★エラーメッセージ

import org.apache.struts.action.ActionMessage;

import org.apache.struts.action.ActionMessages;

import org.seasar.struts.util.ActionMessagesUtil;

import org.seasar.struts.exception.ActionMessageException;

//@Execute(validator=true, input="xxx.jsp")

//@Execute(validator=true, input="/xxx")

@Execute(validator=true, validate="validate", input="afterValidate", stopOnValidationError=false)

public String excute() {

// 書き方1

if (...) {

String errMsg = ...;

throw new ActionMessagesException(errMsg, false);

}


// 書き方2

if ( !actionMessages.isEmpty() ) {

ActionMessagesUtil.addErrors(httpServletRequest, actionMessages);

}


return "xxx.jsp";

}

public ActionMessages validate() {

ActionMessages errors = new ActionMessages();


if (...) {

errors.add("xxx", new ActionMessage(msg, false));


ActionMessage message = new ActionMessage(msgId, param);

errors.add(ActionMessages.GLOBAL_MESSAGE, message);

}


return errors;

}

@Execute(validator=false)

public String afterValidate() {

return "xxx.jsp";

}

JSP側:<html:errors />

★RequestDumpFilterについて

出力ログの制限方法

開発中のデバッグに便利だが、運用時は無効する。

<filter>

<filter-name>requestDumpFilter</filter-name>

<filter-class>org.seasar.extension.filter.RequestDumpFilter</filter-class>

<init-param>

<param-name>下記の種類</param-name>

<param-value>false</param-value>

</init-param>

</filter>

beforeRequestParameter

afterRequestParameter

beforeRequestAttribute

afterRequestAttribute

beforeCookies

afterCookies

beforeRequestHeader

afterRequestHeader

beforeSessionAttribute

afterSessionAttribute

beforeContextAttribute

afterContextAttribute

afterResponse

★セレクトボックス

JSP側

<html:select property="type">

<html:options collection="typeList" property="value" labelProperty="name" />

</html:select>

Action側

myForm.typeList = this.getOptionList();

private List<OptionDto> getOptionList() {

List<OptionDto> list = jdbcManager.selectBySqlFile(

OptionDto.class, "sample/option.sql", new Object()).getResultList();

if (list == null || list.size() == 0) {

throw new MyException("xxx");

}

list.add(0, new OptionDto("", ""));

list.add(0, new OptionDto("xxx", "yyy"));

return list;

}

★画面に情報出力

JSP側

<input type="hidden" id="msg" value="${f:h(msg)}" />

data="${listData}"

<p>${requestScope.msg}</p>

ロジック側

方法1 Action内

public String msg = ...;

public List<String> listData = ...;

方法2 ActionForm内(値はAction中に設定)

public String msg;

public List<String> listData;

方法3

httpServletRequest.setAttribute("msg", str);

※補足

httpServletRequest.getParameter("key"); // GET

httpServletRequest.getAttribute("key"); // POST

★共通の前処理・後処理

Filter

メリット:Formの入力チェックよりも前に実行、JSPよりも後に実行

デメリット:リクエスト全体に対する処理

RequestProcessor

メリット:Formの入力チェックよりも前に実行、FormやActionのアノテーションを読み取った処理、メソッド個別の処理

デメリット:Struts(SAStruts)の標準機能を拡張

public class MyRequestProcessor extends S2RequestProcessor {

@Override

protected boolean processRoles(

HttpServletRequest request, HttpServletResponse response,

ActionMapping mapping) throws IOException, ServletException {

...

}

}

struts-config.xml

<controller

maxFileSize="5M"

bufferSize="1024"

processorClass="jp.co.xxx..MyRequestProcessor"

multipartClass="org.seasar.struts.upload.S2MultipartRequestHandler"

/>

Interceptor

メリット:Actionのアノテーションを読み取った処理、メソッド個別の処理

デメリット:Formの入力チェックの後に実行

public class MyInterceptor extends AbstractInterceptor {

@Override

public Object invoke(MethodInvocation invocation) throws Throwable {

// 前処理

ret = invocation.proceed();

// 後処理

return ret;

}

}

app.dicon

<components>

・・・

<component name="myInterceptor" class="jp.co.xxx.interceptor.MyInterceptor"/>

・・・

</components>

customizer.dicon

<components>

・・・

<component name="actionCustomizer" class="org.seasar.framework.container.customizer.CustomizerChain">

<initMethod name="addAspectCustomizer">

<arg>"myInterceptor"</arg>

</initMethod>

</component>

・・・

</components>

応用例

ログイン認証チェック FilterかRequestProcessor

ログイン時にユーザ情報をセッションへ保持しておき、セッションの存在有無をチェック

権限チェック FilterかRequestProcessor

Actionのメソッドにアノテーションを付与して、ユーザがその権限を保持しているかをチェック

Actionのメソッド別に制御する場合、RequestProcessorが良い

ログ出力 FilterかInterceptor

ログ出力Intercepotrを使用して、aop.traceInterceptorを差し替える