Struts+SpringでSpringをそれらしく使う
試行錯誤して、ある日ふと閃いた方法。というかはよ気がつけよ、と思ったのも事実だが・・・。
お約束の層分け
・web層 ・・・ActionクラスとかStrutsまわり
・app層 ・・・POJOによるビジネスロジック
・domain層 ・・・DBアクセスを管理
目的
「web-app層間、app-domain層間の関係を断ち切ることにより、Mockを用いたapp層のユニットテストを可能にする」
というわけでStrutsとSpringを連携させる下準備
■Struts側の修正
struts-config.xmlにplug-inの記述を追加
Action定義の変更
※Spring Days*1だと"org.springframework.web.struts.DelegatingRequestProcessor"を使う意見が多いようだけど、これを使うとTilesのRequestProcessorが使えない?っぽいので"org.springframework.web.struts.DelegatingActionProxy"を使うことにする。
=>誰か教えてplz【助けて!】【いたわる】
※"org.springframework.web.struts.DelegatingActionProxy"についてはJavaWorldの記事を参照
<=Tilesに飛ばしている
これで"/myTestInit"へのリクエストは"org.springframework.web.struts.DelegatingActionProxy"によってプロキシされる。
プロキシの設定("/WEB-INF/strutsContext.xml")
■Springの設定ファイル
"/WEB-INF/beans/appbeans.xml"にはapp層のBean定義を書いておく
"/WEB-INF/beans/domainbeans.xml"にdomain層のBean定義を書いておく(Hibernateを利用するための設定etc)
※ここから先のDBアクセスはまた別の機会に
■ソース側の修正
"sample.web.action.MyTestAction"
public class MyTestAction extends AbstractBaseAction
{
private MyTestAppInterface app;public ActionForward execute(ActionMapping mapping,
ActionForm form,
HttpServletRequest request,
HttpServletResponse response){//Beanからメッセージを取得して画面に表示するだけ
String msg = _app.getMessage();ActionMessage message = new ActionMessage("application.BeanName", msg);
ActionMessages messages = new ActionMessages();
messages.add(ActionMessages.GLOBAL_MESSAGE,message);
saveMessages(session,messages);return mapping.findForward("success");
}//"/WEB-INF/strutsContext.xml"に記述されたpropertyによりセットされる
public void setMyTestApp(MyTestAppInterface _myTestApp){
this.myTestApp = _myTestApp;
}
}
"sample.web.app.MyTestAppInterface"
public interface MyTestAppInterface {
public String getMessage();
}
"sample.web.app.MyTestAppBean"
public class MyTestAppBean implements MyTestAppInterface {
private MyTestDomainInterface domain;
//"/WEB-INF/beans/appbeans.xml"に記述されたpropertyによりセットされる
public void setMyTestDomain(MyTestDomainInterface _domain) {
this.domain = _domain;
}public String getMessagee() {
return domain.getMessage();
}
}
domain層でも同様にpropertyの値がセットされる。
こうしておけば各層は「自分がどこからコールされるのか関知しないし、誰を呼び出すのかはInterfaceのみ知っている」とDIっぽくなっているんじゃないかな?
テストをする時にはテストクラスからMockのクラスをセットしておけばとっても楽ちん。
課題
・"org.springframework.web.struts.DelegatingActionProxy"を利用すると"org.apache.struts.actions.MappingDispatchAction"が使えない?
・Springの設定ファイル間の依存関係(ref)が増える
・「クラスの依存があるのでユニットテストができません」と言い訳できなくなる