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を差し替える