読者です 読者をやめる 読者になる 読者になる

Jの衝動書き日記

さらりーまんSEの日記でございます。

いまさら聞けないStruts1.x

Strutsを導入する目的~何のために使うのか?

Strutsとは何かというと、JavaのWebアプリケーション構築用フレームワークである。Strutsのルールに従ったクラスと設定ファイルを作成することでアプリケーション構造の統一化がはかれる。ようするに人によって実装方法がバラバラになったりすることを避けれる(大枠から外れるのを避ける)。

何のための使うのか。統一化以外の目的としては以下にあげられる。

  • 面倒な処理を肩代わりしてもらいたい
  • 類似した処理の実装の重複を避けたい
  • jspの定義を簡素化したい

Webアプリケーションを構築する上での面倒な処理や類似した処理とは、GET/POSTしたパラメータのクラス化(getParameterでパラメータを取得して定義したクラスに突っ込むなど)や、GET/POSTのパラメータの入力チェックや、入力チェックエラー時の返却処理などである。

   jspに関しては、Strutsにはjspで使用可能な便利なタグが多く定義されているため、それらを使用してjspの記述をレイアウト定義に集中するなどが目的となる。

Strutsで出来ること

大きく分類すると以下のことがStruts1.xを利用することで可能となる。

GET/POSTパラメータのクラス化

ActionFormという形でGET/POSTのパラメータをクラス定義することで、リクエストを処理するクラスではActionFormという形でパラメータを受け取れる。このActionFormは自動的にnewされ、getParameterでパラメータを受け取って値を詰め込んだ後、渡される。

また、ActionFormはそのままjspに自動的に渡されるため、特に意識することなくjspで参照可能となる(jspに渡す時の名称どうしようとか考えなくて良い)。

GET/POSTパラメータの入力チェック

validationを使うことで、パラメータのチェックは自動化可能となる。つまり、リクエストを処理するクラスが受け取るActionFormの内容は入力チェックが通ったものとなるため、単純な入力チェックの記述は不要となる(かわりに設定ファイルに記述が必要)。

便利なタグの利用

  • tilesタグを利用した、jspのレイアウトの統一化
  • errorsタグを利用した、入力エラーメッセージの自動設定
  • html系タグを利用した、入力エラー時の入力画面へのパラメータの差し戻し
  • logic系タグを用いた、繰り返し要素の記述や、条件下の記述の簡素化

html系のタグに関しては、  入力エラーとなった時入力画面のjspへリダイレクトすると思うが、この時何もしないと入力した項目はすべてクリアされた状態で表示されてしまう。そのため、通常は入力済の内容を設定した上で入力画面を返す必要があるのだが、html系のタグを記述しておけば、それは自動でやってくれる。

logic系のタグに関しては、画面中に表などがある場合、for文をjspに直接書く必要があるが、処理の記述とレイアウトの記述が混ざり読みづらい。logic系のタグを使えば、タグのみの記述となるため記述がスッキリする。

その他

以下のものはメリットとしてはやや微妙だが(Strutsでなくても出来るため)一応あげておく。

  • 画面遷移先定義の設定ファイル化
    • 画面遷移先のパスが変更になった場合も、コンパイルなしで反映が可能
  • 表示メッセージの多言語化
    • jspからはタグでkeyを指定すると、それに対応した文字列が言語毎のメッセージファイルから取得可能

Strutsを使ったWebアプリケーション構築手順の流れ(超ざっくり)

簡単にいうと開発者が作成するものは以下のものである。

  • ActionForm継承クラス
  • Action継承クラス+サービスを処理するためのクラス
  • struts-config.xml
  • validation.xml
  • メッセージファイル
  • jsp

以下、超ざっくりした流れである。

  1. 入力画面と出力画面の画面レイアウトを作成する
    • ※最終的にはjspにするが、HTMLでも可
  2. 入力画面からはGET/POSTのパラメータを、出力画面からは渡す必要があるパラメータを洗い出す
  3. 入力画面を表示するためのURLと、入力画面画面から送信するGET/POSTのURL(アクション名)を決定する
    • 入力画面を表示するためのURLは、jspのものでも可
  4. 2と3の情報を元にActionFormクラス(Struts提供クラスを継承)を作成する
    • ※入力画面と出力画面の各項目がほぼ同じである場合は、ActionFormをまとめてもよい
  5. 3のアクションの振る舞いを検討する
    • 入力チェックの内容と入力エラー時に表示する画面
    • アクションを実行した結果、次に遷移する画面(通常、1で検討した出力画面となる)
  6. 3,4,5で検討した内容を元にStruts-config.xmlのaction-mappingsの内容を設定する
    • Struts-config.xmlのaction-mappingsには以下の設定が必要となる
      • 受け付けるurl(アクション名)→実際のアクセス時にはhoge.doのように.doが付く
      • 対応するアクションクラス
      • パラメータチェックの有無
      • パラメータチェックNG時の遷移先画面
      • アクションを実行した時の遷移先一覧(jspの配置場所を指定)
  7. GET/POSTを処理するActionクラス(Struts提供クラスを継承)を作成する
    • Actionクラスは、GET/POSTのパラメータをActionFormの形で受け取る
    • 作成するActionクラスの返り値は、実行した結果次に移る画面を指定する
    • その際、jspのパスそのものではなく、Struts-config.xmlで設定した遷移先一覧の名称を指定する
    • Actionの役割をざっくりいうと、アクションを実行した結果の次の画面の遷移先の提示と、その画面に渡すためのデータを作成、設定することにある
  8. 入力画面と出力画面をjspで作成する
    • Strutsのタグを極力利用して作成すること(入力エラー時の、パラメータ差し戻しが使えないため)
    • アクション名の指定はStruts-config.xmlのものと合わせること
    • Strutsのタグを利用すれば、アクション名.doの形でGET/POSTされるように画面を生成する
  9. メッセージ定義などを行う

本来はチュートリアルを書くところだが、面倒なので割愛する。

以下に丸投げ のものが参考になる。

Java初心者のストラッツ入門

Webアプリケーション構築の準備 - 株式会社アークシステム(infoARK)

Strutsとの役割分担について

開発者は何をすればいいのか。Strutsの話のまえにまずはServletの話から。

Servletの場合

Servletの役割はざっくり言うと、クライアント(主にブラウザ)からのHTTP GET/POSTの応答を返すことにある。
GET/POSTの送受信処理はJ2EEアプリケーションサーバ(tomcat)がやってくれるため、開発者の役割としては応答内容を作成することにある。
応答内容が画面、つまりHTMLである場合は以下のような形になる。

  1. HTTP GET/POSTリクエストの受信、加工(アプリケーション側で使いやすい形にする) :J2EEアプリケーションサーバ(tomcat等)
  2. リクエストパラメータの取得とチェック : 開発者
  3. 応答結果用のデータ取得・作成 : 開発者
  4. データを元に応答結果用の画面出力 HttpServletResponseに設定する : 開発者
  5. HTTP GET/POSTレスポンスの送信 : J2EEアプリケーションサーバ

特に4の処理が非常にめんどくさい。ソース上でひたすらprintfを使ってHTMLをガシガシ出力しなければならないため、レイアウトがイメージしづらい。

なお、 4の内容はリクエストの内容によってやることは異なる。例えば、イメージを応答結果として返す場合は、イメージを作成して出力したりする。

Servlet + JSPの場合

Servletの4で行っていたことをjspとして定義することでサーブレット内の記述は不要となる。jspの形にすることでレイアウトをイメージしやすくなった。

また、Servletのお仕事は、jspが画面に表示するための値を作成し、それをjspに渡すということになった。

  1. HTTP GET/POSTリクエストの受信、加工(アプリケーション側で使いやすい形にする) :J2EEアプリケーションサーバ(tomcat等)
  2. リクエストパラメータの取得とチェック : 開発者
  3. 応答結果用のデータ取得・作成 : 開発者
  4. 返却データをjspに渡すための設定と応答結果として返すjspの指定:開発者
  5. 応答用画面の作成 : J2EEアプリケーションサーバ(tomcat等)
  6. HTTP GET/POSTレスポンスの送信 : J2EEアプリケーションサーバ

jsp自体の定義はもちろん開発者のお仕事ではあるが、HTMLの出力処理そのものは意識しなくてもよくなった。

だが、2のパラメータの取得やチェックが相変わらず面倒。またjspにデータを渡す処理が面倒。特に入力チェックがエラーであった場合の表示処理が面倒。

また、jspは繰り返し要素や、条件要素が必要な場合、jsp上に処理を入れる必要があるため、jspが読みづらくなる。

Strutsの場合

Servletとしては実装することはなくなり、Strutsのクラスを継承して実装するスタイルとなる。アクションを実行した結果、次にどの画面に遷移するかということを強く意識する必要がある。

  1. HTTP GET/POSTリクエストの受信、加工(アプリケーション側で使いやすい形にする) :J2EEアプリケーションサーバ(tomcat等)
  2. リクエストパラメータの取得とチェック : Struts
  3. 応答結果用のデータ取得・作成 : 開発者
  4. 返却データをjspに渡すための設定と応答結果として返すjspの指定:開発者/Struts(※開発者は返却先の画面を示すのみ)
  5. 5. 応答用画面の作成 : J2EEアプリケーションサーバ(tomcat等)
  6. 6. HTTP GET/POSTレスポンスの送信 : J2EEアプリケーションサーバ

 応答結果としてHTMLを返すアプリケーションでは何を実装すればいいのかフレームワークで指定されるため作りやすくなる。

ただし、設定ファイルを書くのが非常に面倒い、というかしんどい。

また、応答結果としてHTMLを返さないようなWebアプリケーションの場合は、Strutsを使う効果は薄い。

Struts2との違いについて

Struts1.x自体は既に開発を終了しており、今はStruts2となっている。
フレームワークとしての役割自体は変わっていないが、ルールが大幅に変わっているため互換性はない(つまりStruts1.xのコードはStruts2上では動作しない)。もう別物と考えたほうがいい。
大きく変わった点は以下である。

  • ActionFormがなくなった → ActionクラスがActionFormとしての役割も持つようになった
  • ActionクラスはPOJOでOKとなった→代わりにexecute()の実装が必要だが、設定によりactionに対応するメソッドを変えることも可能
  • 各設定ファイルがなくてもOK→代わりに命名ルールに従った実装をする必要がある
  • タグ定義→prefixの一本化と一部タグの廃止

Struts1.xベースのものをStruts2にするのであれば、Actionとjspの部分はほぼ作り直しとなる。
個人的には、ActionがActionFormとしての役割も持ってしまったのが非常に気持ち悪い。データはデータとして簡素にまとめておきたいところ(と、ここまで書いたところでModelDrivenとやらを使えば分離できるっぽいが知ったが・・・)。
あとStruts2自体は、SAStrutsに似ている(正確には、SAStrutsがStrtus2に似せている?)のがわかったため、これ以上の勉強はとりあえず辞めておく。
元々、お仕事でSAStrutsを使っており、そもそもStrutsってなんだっけ? で始めたエントリなのだ。