はじめに
StrutsとSpringの連携とかがあるようです。
struts-config.xml
<action path="/AB001S"
type ="org.springframework.web.struts.Delegating Action Orixy"
name= "AB001SForm"
parameter="display,create,register,back"
validate="false"
scope="request">
<forward name="display" path="/ikusaki/AB001S.jsp">
<forward name="AZ0020A" path="/AZ0020S.do?display="back">
</action>
struts-config.xml
ファイルの記載に関する説明をします。
まず、struts-config.xml
は、Struts フレームワークの設定ファイルで、リクエストに対するアクションやビューへのフォワードを管理しています。この記述では、Spring と Struts が連携している部分も見られます。詳細に説明します。
<action>
タグの説明
<action path="/AB001S"
type="org.springframework.web.struts.Delegating Action Proxy"
name="AB001SForm"
parameter="display,create,register,back"
validate="false"
scope="request">
-
path="/AB001S"
:- このアクションが処理するリクエストパスを指定します。
/AB001S
に対するリクエストがこのアクションにルーティングされます。
- このアクションが処理するリクエストパスを指定します。
-
type="org.springframework.web.struts.Delegating Action Proxy"
:- ここでは、Struts が Spring の
DelegatingActionProxy
クラスを使って Spring にアクションの処理を委譲しています。このクラスは、Struts のアクション処理を Spring のビジネスロジックに結び付けます。Spring と Struts を連携させる設定です。
- ここでは、Struts が Spring の
-
name="AB001SForm"
:- このアクションが操作するフォーム Bean の名前を指定しています。
AB001SForm
という名前のフォームオブジェクトが使用されることを示しています。
- このアクションが操作するフォーム Bean の名前を指定しています。
-
parameter="display,create,register,back"
:- このパラメータは、異なる操作に対応するアクションメソッドやパスを指定しています。例えば、
display
やcreate
、register
、back
といったアクションがリクエストに応じて異なる処理を実行することができます。
- このパラメータは、異なる操作に対応するアクションメソッドやパスを指定しています。例えば、
-
validate="false"
:- このアクションに対して、フォームのバリデーションを行わない設定です。
false
に設定されているので、フォーム送信時にデフォルトのバリデーションは実行されません。
- このアクションに対して、フォームのバリデーションを行わない設定です。
-
scope="request"
:- このアクションに関連付けられているフォーム Bean のスコープを指定しています。
request
スコープは、リクエスト単位でフォームオブジェクトが生成され、次のリクエストではリセットされることを意味します。
- このアクションに関連付けられているフォーム Bean のスコープを指定しています。
<forward>
タグの説明
アクションが完了した後、どのビューや次のアクションにフォワードするかを指定しています。
<forward name="display" path="/ikusaki/AB001S.jsp">
-
name="display"
:- この名前でアクションの結果が「display」の場合にフォワードされます。
-
path="/ikusaki/AB001S.jsp"
:- 具体的な JSP ページへのパスです。この場合は、
/ikusaki/AB001S.jsp
という JSP ページにリクエストがフォワードされ、そこで HTML を生成します。
- 具体的な JSP ページへのパスです。この場合は、
<forward name="AZ0020A" path="/AZ0020S.do?display=back">
-
name="AZ0020A"
:- アクション結果が「AZ0020A」の場合にフォワードされる。
-
path="/AZ0020S.do?display=back"
:- この場合、
/AZ0020S.do
という別のアクションにフォワードされます。この際、クエリパラメータとしてdisplay=back
が付与されています。次のアクションがこのパラメータを基に処理を行います。
- この場合、
まとめ
- このアクションでは、Spring と Struts の連携を実現するために
DelegatingActionProxy
を使っているため、リクエスト処理は Spring のコンテキストで行われます。 - 複数のパラメータを持つアクションで、結果に応じて JSP ページや別のアクションにフォワードしています。
- この設定は、複数の操作に対応するアクションを一つのエントリポイントに集約するためのものです。
○○Action.java の findForward() メソッドで返された値
<forward name="display" path="/ikusaki/AB001S.jsp">
で指定された name="display"
という値は、○○Action.java
の findForward()
メソッドで返された値に対応しています。
具体的には、Strutsの Action
クラスの execute()
メソッド内でビジネスロジックが処理され、その結果に応じて mapping.findForward("display")
が呼ばれます。このとき、findForward("display")
は、struts-config.xml
に定義されている forward
の name
属性と一致するビューやアクションにフォワードします。
例: ○○Action.java
内での findForward()
の使用
例えば、以下のように ○○Action.java
で findForward()
を使用しているとします。
public class AB001SAction extends Action {
public ActionForward execute(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response) throws Exception {
// 何らかのビジネスロジックを実行
// 例えば、リクエストから取得した値をもとに処理
// "display" に基づいてビューを返す
return mapping.findForward("display");
}
}
struts-config.xml
内での forward
設定
<action path="/AB001S"
type="com.example.AB001SAction"
name="AB001SForm"
scope="request"
validate="false">
<forward name="display" path="/ikusaki/AB001S.jsp" />
</action>
この場合、AB001SAction.java
の execute()
メソッド内で mapping.findForward("display")
を呼び出すと、struts-config.xml
内の <forward name="display" path="/ikusaki/AB001S.jsp">
に定義されている path="/ikusaki/AB001S.jsp"
へリクエストがフォワードされます。
まとめ
-
findForward("display")
の値 は、struts-config.xml
の<forward name="display">
で定義されたname="display"
と一致します。 -
findForward("display")
が返すActionForward
オブジェクトは、struts-config.xml
に記載されたpath="/ikusaki/AB001S.jsp"
にリクエストをフォワードし、そのJSPを表示します。
したがって、○○Action.java
内で findForward("display")
を呼び出した結果が、struts-config.xml
内の name="display"
と一致し、その結果として /ikusaki/AB001S.jsp
が表示されることになります。
StrutsとSpringが連携
StrutsとSpringが連携して動作している場合、まずStrutsのアクションが起動されるか、Springのコンテキストで処理が開始されるかの理解について説明します。
この場合、struts-config.xml
で指定されている DelegatingActionProxy
は、StrutsからSpringへアクション処理を委譲するための機能です。具体的な流れを整理すると以下のようになります。
StrutsとSpringの連携の流れ
-
Strutsがリクエストを受け取る:
- まず、Strutsが
struts-config.xml
に基づいてリクエストをルーティングします。この際、指定されたURLパターン(例えば/AB001S
)に一致するアクションを探します。
- まず、Strutsが
-
DelegatingActionProxy
の呼び出し:-
struts-config.xml
で指定されているtype="org.springframework.web.struts.DelegatingActionProxy"
は、リクエストが来た時に Struts のアクションではなく、Spring のコンテキストに委譲するプロキシクラスです。 - これにより、Strutsはリクエスト処理を
DelegatingActionProxy
に委譲します。このプロキシはSpringの設定ファイル(通常はapplicationContext.xml
)内に定義されているSpringのビーン(Springのアクションクラス)を探して処理します。
-
-
Springのアクションが呼び出される:
- Springのコンテキストがロードされ、StrutsのアクションはSpringのビーンとして定義されたアクション(例えば
AB001SAction.java
)に処理を委譲します。 - このSpringビーンがビジネスロジックを実行します。
- Springのコンテキストがロードされ、StrutsのアクションはSpringのビーンとして定義されたアクション(例えば
-
結果を返してJSPにフォワードする:
- Springのアクションが処理を終えると、
struts-config.xml
に定義されているforward
設定に基づいて、JSPや次のアクションにフォワードします。JSPは通常通り、サーバサイドのJSPコンテナでレンダリングされます。
- Springのアクションが処理を終えると、
基本的に以下の考え方が正しいです:
-
Strutsがリクエストを受け、Springのコンテキストに委譲:
最初にStrutsがリクエストを受け取り、そのリクエストをDelegatingActionProxy
を介してSpringに委譲します。ですので、AB001SAction.java
のようなアクションが起動される時、実際にはSpringのコンテキスト内でそのアクションが管理されています。 -
JSPの処理とSpringの関係:
Strutsがフォワード先のJSPページにリクエストを渡す部分は、Strutsの機能で行われます。JSPの処理自体は通常のJSPコンテナで行われ、直接Springのコンテキストを利用することはありません。ただし、JSPページでSpringのタグライブラリを利用することによって、Springのコンポーネントにアクセスすることが可能です。
まとめると、リクエストの流れは最初にStrutsが受け取り、アクション処理はSpringに委譲され、その後JSPにフォワードされる という形になります。
StrutsとSpringが連携時の境目
StrutsとSpringを組み合わせて使う場合、特にDelegatingActionProxy
などを介してリクエスト処理がSpringに委譲されるケースでは、両者の役割分担がわかりにくくなることがあります。確かに、フレームワーク間の境界が曖昧になると、運用面でのトラブルが心配になることは理解できます。ここでは、StrutsとSpringの役割を明確にし、運用の自由度を管理する方法について解説します。
StrutsとSpringの役割分担
-
Strutsの主な役割:
- リクエストのルーティング:StrutsはリクエストURLに基づいて適切なアクションを選択します。
- フォワーディング:処理結果に応じてJSPや他のアクションにフォワードする役割を担います。
-
Action
クラスは、リクエストのハンドリングのエントリポイントとして機能し、struts-config.xml
に基づいて動作します。
-
Springの主な役割:
- ビジネスロジックの処理:SpringはDI(依存性注入)とAOP(アスペクト指向プログラミング)を利用し、ビジネスロジックを効率的に管理します。
- サービス層とデータアクセス層:Springのサービス層やリポジトリ層は、ビジネスロジックやデータベースとのやり取りを担当します。
- Strutsがアクションを処理する際に、実際のビジネスロジックをSpringに委譲することで、Separation of Concerns(関心の分離)を達成します。
典型的な分け方
- Strutsの役割: 基本的にユーザーからのリクエストを受け取り、そのリクエストをSpringに渡すための窓口として機能します。リクエストのルーティングや、処理結果に基づくJSPや次のアクションへのフォワードを担当します。
-
Springの役割: 具体的なビジネスロジックや、データベースとのやり取りなど、リクエストを処理する本質的な部分を担当します。
ServiceImpl
やRepository
クラスを用いて、ビジネスロジックを実行します。
境界を明確にする方法
-
役割を明確に定義する:
- Strutsは基本的に「リクエストの受け取りとレスポンスの返却(フォワーディング)」を行い、ビジネスロジックやデータ処理はSpringのサービス層に完全に委譲する形にします。
- 例えば、Strutsの
Action
クラス内でビジネスロジックを実装するのではなく、SpringのService
に委譲するような明確な方針を持つことが重要です。
-
統一された設定とドキュメントの整備:
-
struts-config.xml
や Spring の設定ファイル(applicationContext.xml
など)で役割を明確に分け、それぞれの責任範囲をドキュメント化します。設定ファイルに適切なコメントを入れることも有効です。 - 開発チーム全体で、どこまでがStrutsの責任でどこからがSpringの責任かを共通理解にしておくと、メンテナンス性が向上します。
-
-
アクションとサービスの依存関係を最小限にする:
- Strutsの
Action
クラスはできるだけ薄く保ち、具体的なビジネスロジックはすべてSpringのService
クラスに任せるようにします。これにより、どの部分がStrutsで、どの部分がSpringかが明確になります。
- Strutsの
-
適切なエラーハンドリングとトランザクション管理:
- StrutsとSpringが混在するシステムでは、エラーハンドリングやトランザクション管理が複雑になる可能性があります。SpringのAOPやトランザクション管理を活用し、ビジネスロジックを処理する際のエラーハンドリングやトランザクション管理を統一することで、運用の自由度が保たれます。
運用面でのアドバイス
-
テストを徹底する: StrutsとSpringが連携するシステムでは、両者の境界が曖昧になる可能性があるため、ユニットテストや統合テストをしっかりと実施することが重要です。StrutsのアクションとSpringのサービスが適切に連携しているかを確認します。
-
ログ管理の強化: 両フレームワーク間の処理がどこで行われているかを明確に把握できるように、適切なログ出力を行うことも運用面で重要です。特にエラーが発生した場合にどのレイヤーで起こったかを特定しやすくするためです。
-
トレーニングとガイドライン: 開発者全員がStrutsとSpringの両方の役割と機能を理解していることが大切です。ガイドラインやコーディング規約を定め、適切な運用ができるようにしておくと良いでしょう。
結論
StrutsとSpringを併用する際の運用は、役割分担とその境界がわかりにくくなることがありますが、各フレームワークの責任範囲を明確にし、Strutsはリクエスト管理とフォワーディング、Springはビジネスロジックを担当するという方針で進めると管理しやすくなります。また、適切なドキュメンテーションとガイドラインを作成し、運用を統制することが成功の鍵となります。
現状
現状では Strutsはあまり使われていない 傾向にあり、代わりに Spring(特にSpring MVCやSpring Boot) が主流になっています。現在の主流は、XMLベースの設定をほとんど使わずに、アノテーション を使ってルーティングや他の設定を行う形に移行しています。
Springの現状について
-
Springアノテーションによるルーティング:
Springでは、以前はapplicationContext.xml
などのXMLファイルを使用してルーティングや依存性注入の設定を行っていましたが、現在ではアノテーションを用いた設定が一般的です。Spring MVCやSpring Bootでは、コントローラクラスで直接アノテーションを使ってルーティングを定義します。例えば、次のように
@RequestMapping
などのアノテーションを使ってルーティングを簡単に設定できます。@RestController @RequestMapping("/example") public class ExampleController { @GetMapping("/hello") public String sayHello() { return "Hello, World!"; } @PostMapping("/submit") public String handleSubmit(@RequestBody FormData formData) { // ビジネスロジック return "Data submitted"; } }
このように、
@RequestMapping
や@GetMapping
、@PostMapping
を使うことで、URLに対するルーティングを簡単に定義できます。XMLを使わずに完全にアノテーションベースでルーティングや設定を行うことができます。
Spring Bootの登場でさらに簡略化
-
Spring Boot は、Springアプリケーションをより簡潔に、設定を最小限にして開発できるようにしたフレームワークです。Spring Bootでは、必要な設定や依存性が自動的に解決され、XMLファイルや複雑な設定ファイルをほとんど使わずに開発できるのが特徴です。
- 例えば、Spring Bootでは、
application.properties
やapplication.yml
ファイルで最小限の設定を行うだけで、依存性の設定やルーティング、ビジネスロジックの構築が可能です。
- 例えば、Spring Bootでは、
Spring一択の理由
-
モダンな開発: Springは、最新のアプリケーション開発の要件に合致しており、マイクロサービスやクラウドネイティブアーキテクチャに対応しています。Spring Bootを使えば、REST API、データベース接続、セキュリティなどの機能がすぐに利用できる状態で提供されます。
-
アノテーションによる簡潔さ: アノテーションベースの設定により、コード内でロジックと設定をシンプルに管理できます。たとえば、コントローラークラスに
@RestController
を付けるだけで、そのクラスがREST APIとして動作するようになります。 -
テストの容易さ: Springはテストも強力にサポートしており、アノテーションによって設定が簡単になっているため、ユニットテストや統合テストの環境を簡単にセットアップできます。
まとめ
現在のトレンドは Spring一択 と言ってもよいほどにSpringが主流です。Strutsのようなフレームワークはほとんど使われなくなり、Springでは アノテーション を使ってルーティングや依存性の注入などを管理する形が一般的です。また、Spring Bootの登場により、XMLを使わずに、より簡潔に設定が可能になっています。
そのため、現代のJavaアプリケーション開発では、XMLを使わず、アノテーションでルーティングを行うのが標準的なやり方と考えて良いでしょう。
StrutsのServiceクラスについて
Strutsには、Springのような「Serviceクラス」という公式な概念はありません。Strutsは、主にMVC(Model-View-Controller)アーキテクチャの「コントローラ」部分に焦点を当てたフレームワークです。つまり、リクエストを受け取って、適切なビューにフォワードすることが主な役割です。ビジネスロジックを含む部分は、Struts自体が強制的にどこに置くかを定めているわけではありません。
そのため、Strutsには以下のような特徴があります。
Strutsの役割
- Actionクラス: リクエストを処理するためのコントローラー役割を果たすクラスです。リクエストパラメータを処理し、ビュー(JSPなど)にフォワードします。
- Formクラス: リクエストで送信されたデータを受け取るためのクラスで、フォームのデータを保持し、必要に応じてバリデーションを行います。
- struts-config.xml: リクエストとアクション、ビューのルーティングを設定するためのXMLファイルです。
ただし、Strutsにはビジネスロジックを処理する明確な場所は定義されていません。つまり、Struts自体はビジネスロジックの設計には関与しておらず、他のレイヤー(例えばサービス層)を独自に実装する必要があるのです。
Springとの違い
Springの場合、ビジネスロジックを処理する層として**サービスクラス(@Service
)**があり、ビジネスロジックとコントローラ層を分離するための明確な役割分担が設けられています。
一方、Strutsでは、そのような設計は強制されていません。そのため、Strutsアプリケーションの開発者は、ビジネスロジックの管理方法を独自に決める必要があります。
-
ビジネスロジックの配置: Strutsでは、ビジネスロジックを
Action
クラスに直接書くこともできますが、これではコードが肥大化し、再利用性やテストのしやすさが損なわれます。よって、多くのプロジェクトでは、サービスクラスのような層を独自に作成し、ビジネスロジックをそちらに委譲します。- 例えば、
UserService
というクラスを独自に作成し、その中にユーザーに関するビジネスロジックを実装し、StrutsのAction
クラスではUserService
を呼び出すような形に設計されることが一般的です。
- 例えば、
Strutsでのサービス層の設計例
たとえば、StrutsアプリケーションでSpringのようなサービス層を自作する場合、次のように実装します。
-
サービスクラスの作成:
- ビジネスロジックを処理する
UserService
クラスを作成します。
public class UserService { public void registerUser(User user) { // ユーザー登録のビジネスロジック } }
- ビジネスロジックを処理する
-
Actionクラスでサービスを呼び出す:
-
Action
クラス内で、サービスを利用します。
public class UserAction extends Action { private UserService userService = new UserService(); public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) { UserForm userForm = (UserForm) form; User user = new User(userForm.getName(), userForm.getEmail()); // サービスクラスを利用してビジネスロジックを処理 userService.registerUser(user); return mapping.findForward("success"); } }
-
このように、Strutsアプリケーションにおいては、サービスクラスやその他のビジネスロジックを分離した層は開発者が独自に設計することが一般的です。公式に定められた「Serviceクラス」のような構成はありませんが、設計の一環として取り入れることが推奨されています。
まとめ
- Strutsには公式な「Serviceクラス」の概念はないため、ビジネスロジックをどのように分離するかは開発者に委ねられています。
- ただし、サービス層を独自に実装することで、StrutsアプリケーションでもSpringと同様にビジネスロジックを明確に分離し、テストや保守性を向上させることができます。
- 現代のフレームワークであるSpringでは、この役割が標準的に定義されているため、設計がよりスムーズに進められることが特徴です。