Struts2の構造
1.なぜフレームワークを使用するのですか?
(1)フレームワークは、多くの些細なタスクを自動的に完了します
Struts2の場合、データ型の変換、データ検証、国際化などを簡単に完了するのに役立ちます。
Web開発における一般的なタスク。また、春に広く使用されているテンプレートモードもあります。これらはすべて、開発プロセスをより自動化してインテリジェントにしています。フレームワークを使用することは、ホイールの再発明を避け、これらのテンプレートコードを再コピーすることです。
フレームワークにより、一般的なワークフローや基本的なタスクよりも、高レベルの問題に焦点を当てることができます。
(2)フレームワークの使用とは、フレームワークの背後にあるアーキテクチャを優雅に継承することを意味します
フレームワークの背後にあるアーキテクチャは、通常、一連のワークフローを定義します。私たちがする必要があるのは、特定のアプリケーションのコードをこのプロセスに添付することです。そうすれば、フレームワークによってもたらされるさまざまな利点を享受できるようにします。また、フレームワークのアーキテクチャルールに抵抗することもありますが、フレームワークは通常、拒否が困難な方法でアーキテクチャを提供します。優れたアーキテクチャを優雅に継承できるので、それは無料です。
(3)フレームワークを使用してよく訓練された人々を見つける方が簡単です
以前に会社のプロジェクト全体でフレームワークを使用したことはほとんどありませんでした。
ログ印刷(log4jに類似)、次にデータベース接続プール(DBCPと同様)に、それらはすべて内部担当者自身によって実装されます。第一に、それはプロジェクトが比較的古く、当時使用するためのオープンソースのフレームワークがない可能性があるためです。第二に、それは会社の保守的な戦略のためであり、不安定なオープンソースフレームワークを使用することでプロジェクトにリスクをもたらす可能性があることが心配です。これは当時の環境でも当てはまる可能性があり、会社の上級管理職は、より大きな観点からプロジェクト全体を自然に考慮します。
ただし、プロジェクトが徐々に大きくなり、世界にますます優れたオープンソースフレームワークがある場合、成熟したオープンソースフレームワークを時間内にリファクタリングして導入できない場合、最終結果は、新たに採用された開発者がこの複雑なシステムをゼロから学習する必要があり(すべての内部システムを学習し、インターネット上で助けがない)、内部フレームワークのさまざまなバグに注意してください。
コストは本当に高すぎます。
(4)内部フレームワークは業界の発展に追いつくことができません
前述の内部フレームワークのバグ。オープンソースフレームワークには、フレームワークの創設者、多数のオープンソース愛好家のチームがいる場合があります。
それをサポートするためのオープンソースコミュニティ。人々の力は無限であり、バグ修復の速度を想像することができます。これは最近のオープンソースからです
テキストメイトのバグ修正プロセスを見ることができます。長い間棚上げされてきた多くのバグは、オープンソースの後に愛好家によってすぐに解決されましたが、内部フレームワークはどうですか?彼を育てた人々が会社を去った後、誰も大きなバグなしで彼のソースコードを読むことさえしませんでした。ギャップは明らかです!
(5)もちろん、フレームワークを使用することは大きな利益ではありません。
前述のように、未熟なフレームワークを使用することは危険であり、それほど急進的ではないプロジェクトのために保守的であることをお勧めします。
(これが自分の裁量でどのフレームワークを使用するかを決定できる無料で抑制されていない技術狂信者のグループでない限り、それは本当に祝福です)
Sequioaと同様に、私が以前に使用したJava ha High Availabilityサービスと同じように、このフレームワークは開発会社によってサポートされなくなり、リスクはさらに大きくなります。
さらに、いくつかの珍しいフレームワークを使用する場合、フレームワークソースコードライセンスプロトコルにも注意を払う必要があり、プロジェクトで自由に参照しないでください。
不必要な法的紛争を避けるために、フレームワークのソースコードを変更します。
2。Struts2の背後にあるアーキテクチャ
以前にフレームワークの多くの利点を分析したことがあるので、当然、Struts2の使用を学び始めます。ただし、Struts2を使用しています
どのようなエレガントなアーキテクチャが継承されますか?実際、より高いレベルの抽象化から、それは私たちがよく知っているMVCモデルです。
前のHelloworldの例によると、コントローラーC(filterdispatcher)はweb.xmlで宣言したものです
struts2コアクラス。モデルMは私たちのニュースアクションアクションクラスです。 View Vは自然にnews.jspです。モデルの概念は少し曖昧に見えます。モデルとは何ですか?実際、非常に名詞のように聞こえるこの概念には、Webフロントエンドから静的に送信されたビジネスデータとビジネスロジックの実装の両方が含まれています。
このアーキテクチャは新しいものではないと言う人もいるかもしれません。多くのMVCフレームワークがあり、このフレームワークと他のフレームワークの違いは何ですか? Struts2をより低いレベルの抽象化で分析し、それをユニークなものにしましょう。
一見すると、非常に複雑に見えます。ユーザーの観点からのみ見ている場合、開発中に黄色の部分を実装するだけです。つまり、私たちは
struts.xml、Newsaction and news.jsp Helloworldインスタンス。これは私たちがしなければならないすべてです。前述のように、私たちは非常に小さなことをする必要があり、この優れたアーキテクチャの一部になります。
次に、他の部分を見てください。 filterdispatcherは、web.xmlで構成するサーブレットフィルターであり、struts2です
すべてのStruts2 Webアプリケーションは、このように構成する必要があります。次に、青と緑の部分はStruts2の中核です。これらのクラスは、Struts2の開発者によって慎重に設計されていると言えます。
(1)クライアントはリクエストを送信し、J2EEコンテナはHTTPパケットを解析し、それをHTTPSERVLETREQUESTにカプセル化します。
(2)FilterDispatcherはこの要求を傍受し、要求パスに基づいてActionMapperを検索して、どのアクションを呼び出すかを決定します。
(3)ActionMapperの返された結果によると、FilterDispatcherはActionProxyにstruts.xmlでこのアクションを見つけるように委託します。
(4)ActionProxyはActionInvocationを作成し、インターセプターとアクションへの再帰的な呼び出しを開始します。
(5)各インターセプターは独自のタスクを完了します
(6)実際の行動呼びかけは結果パスを返します
(7)結果オブジェクトは、戻りデータをストリームに出力します
(8)httpservletResponseをJ2EEコンテナに返し、コンテナはHTTPパケットをクライアントに送信します。
これがStruts2の実行プロセスです。コアオブジェクトは、ActionInvocationとInterceptor、およびまだ導入されていないActionContextです。
ActionInvocationは、プロセス全体の合計スケジューリングであり、Spring AOPの呼び出しオブジェクトに非常に似ています。多くのインターセプターがstruts2に組み込まれています。最も重要なことは、リクエストパラメーターを保存し、フォアグラウンドデータをアクションメンバー変数に渡すことです。
ActionContextは、これらのデータを保存するグローバルコンテキストオブジェクトであり、最も重要なことは、アクションインスタンスを保存するために使用されるValuestackです。
いわゆるグローバルは、ActionContextにアクションと結果にアクセスできることを意味しますが、実際にはthreadlocalタイプです。各リクエストスレッドには、アクションとActionContextの独自のインスタンスがあります。
Struts2の学習は主に学習に関するものであると言えます。
(1)インターセプターとアクションを協力して、タスクを完了させます。
(2)フォアグラウンドデータをアクションに保存します。
(3)結果は、valuestackを介してアクションから返品データを取得します。
3。Struts2とStruts1の違い
上記の実行プロセスから、Struts1と2の大きな違いをすでに確認できます。
(1)ActionFormはどこに行きましたか?アクションはまだ同じアクションですか?
最も明白なことは、プロセス全体でActionFormオブジェクトを表示できないことです。アクションはまだこの名前と呼ばれていますが、Struts1のアクションとはまったく異なるようです。
まず第一に、ActionFormは放棄され、フロントデスクから送信されたデータはPojoに保存される可能性があります。最初にActionFormを保存してからDTOオブジェクトにコピーする日は終わりました。第二に、このpojoは実際にはアクションオブジェクトのメンバー変数です。これはstruts1です
この場合、すべての要求に対してアクションインスタンスを共有することは不可能です。 Struts2は、各リクエストのアクションインスタンスを作成するため、これは機能します。第三に、これは実行可能ですが、MVCのモデルMとしてのアクションはデータを保存し、ビジネスロジックを含むようです。これは悪いデザインですか?実際、慎重に考えると、このデザインは非常に便利です。すでにデータを取得しています。
サービスレイヤーを直接操作できます。行動はあまりにも多くの責任を負っているようですが、多くはありません。
(2)フロントエンドサーブレットはどのようにしてフィルターになりましたか?
Struts1とSpring MVCは、どちらもフロントエンドサーブレットを介した入り口として使用されていることがわかっています。 Struts2がサーブレットフィルターを使用するのはなぜですか?
Struts2はWebwork Coreに基づいているため、Struts1とはまったく異なります。 Webワークは、アプリケーションとJ2EEを削減すると言えます
ServletのフィルターへのActionServletの変更や、httpservletrequest/Responseへの直接アクセスなどのAPIカップリング。
たとえば、PojoはActionFormとして機能し、任意のクラスはアクションインターフェイスなどを実装せずにアクションとして使用できます。
したがって、Struts2はこの優れた非侵襲的設計も継承します。
これは、Springのデザインのアイデアに多少似ています。たとえば、アプリケーションコードとフレームワーク間の結合を最小限に抑えるために、これらのウェアインターフェイスを実装する必要はありません。侵略性は、フレームワークを設計する際に考慮すべき重要な要素です。
(3)フィルター、アクション、および結果の間のOGNL
次の図は、OGNLがStruts2フレームワークにどのように統合されているかを明確に示すことができます。
入力ページinputform.htmlのstruts2タグを使用して、動作中のデータにアクセスし、page resultpage.jspに戻るのはとても便利です。
OGNLは、ValueStack独自のプロパティにアクセスするのと同じくらい便利なValueStackで保存されているアクションのプロパティにアクセスできます。
OGNLの広範な使用は、Struts2の主要な機能です。前景タグの渡し値をアクションに含める、結果をアクションから取得する結果は、OGNLを大量に使用します。ただし、OGNLでは反射がよく使用されています。これがStruts2がStruts1ほど良くない理由の1つだと思います。結局のところ、柔軟で低カップルのアーキテクチャを取得するには、一定の価格が必要です。
(4)インターセプターの強度は無敵です
Struts2のもう1つの強力な機能は、インターセプターインターセプターです。 Struts2には多数のインターセプターが組み込まれているため、大量のコードを再利用できるようになり、以前は些細なタスクと呼ばれるものを自動化するため、Struts2が高レベルの注意を払うことができます。これは、フレームワークでAOPのアイデアを適用するためのモデルです!
Struts2 3つのデータ転送方法
Struts2は、HTTP要求にパラメーターを保存する3つの方法を提供します:Javabean属性、Javabeanオブジェクト、およびモデル駆動型オブジェクト。最も一般的なログイン例を使用して、これら3つのデータ転送方法を見てみましょう。ページコードは非常に簡単です。提出フォームには、ユーザー名とパスワードが含まれています。これらの2つのパラメーターをアクションで取得して、ユーザーが正常にログインするかどうかを確認できます。
1。JavabeanProperties
<%@ page contentType = "text/html; charset = utf-8"%> <html> <head> </head> <body> <h1> login page </h1> <form action = "/cdai/login" method "method" post> <div> <label for = "username"> "username"/label> <input id = "username" </div> <div> <label for = "password"> password:</label> <input id = "password" name "name =" password "type =" password "/> </div> <div> <label for =" rememberme "> <input id =" rememberme "name =" rememberme "type ="チェックボックス "/>> remember> </html>
パッケージcom.cdai.web.ssh.action; com.cdai.web.ssh.request.loginrequestをインポートします。 com.cdai.web.ssh.service.userserviceをインポートします。 com.opensymphony.xwork2.actionをインポートします。 com.opensymphony.xwork2.modeldrivenをインポートします。パブリッククラスのログニクションはアクションを実装します{private string username;プライベート文字列パスワード。プライベートユーザーサービスユーザーサービス。 @Override public String execute(){system.out.println( "login action-" + request);成功を返す; } public string getUsername(){return request; } public void setUsername(string username){this.username = username; } public string getPassWord(){return request; } public void setPassword(string password){this.password = password; }}この方法は比較的単純で、形式のパラメーターをアクションのプロパティに直接保存します。検証する場合、アクションは、ユーザー名とパスワードをDTOにカプセル化して、検証のためにサービスレイヤーに渡す必要がある場合があります。さらに、さらに一歩進んで、ユーザー名とパスワードをDTOに直接保存してみませんか。
2。Javabeanオブジェクト
<%@ page contentType = "text/html; charset = utf-8"%> <html> <head> </head> <body> <h1> login page </h1> <form action = "/cdai/login" method "method" post> <div> <label for = "username"> </div> <div> <label for = "password"> password:</label> <input id = "password" name = "request =" password "/> </div> <div> <div> <label for =" rememberme "> <input id =" rememberme "type =" checkbox "/> remember </body> </html>
パッケージcom.cdai.web.ssh.action; com.cdai.web.ssh.request.loginrequestをインポートします。 com.cdai.web.ssh.service.userserviceをインポートします。 com.opensymphony.xwork2.actionをインポートします。 com.opensymphony.xwork2.modeldrivenをインポートします。パブリッククラスのログニクションはアクションを実装します{private loginrequest request;プライベートユーザーサービスユーザーサービス。 @Override public String execute(){system.out.println( "login action-" + request);成功を返す; } public loginrequest getRequest(){return request; } public void setRequest(loginrequest request){this.request = request; }}これにより、サービスレイヤーを直接呼び出すことができます。ただし、これによりページパラメーター名の深さを深め、パラメーター名にリクエストを追加するだけであるという小さな欠点があります。
プレフィックス(アクションの属性名)により、Struts2はフォームのパラメーターをOGNLを介して要求オブジェクトに正しく保存できます。
3。モデル駆動型オブジェクト
<%@ page contentType = "text/html; charset = utf-8"%> <html> <head> </head> <body> <h1> login page </h1> <form action = "/cdai/login" method "method" post> <div> <label for = "username"> "username"/label> <input id = "username" </div> <div> <label for = "password"> password:</label> <input id = "password" name "name =" password "type =" password "/> </div> <div> <label for =" rememberme "> <input id =" rememberme "name =" rememberme "type ="チェックボックス "/>> remember> </html>
パッケージcom.cdai.web.ssh.action; com.cdai.web.ssh.request.loginrequestをインポートします。 com.cdai.web.ssh.service.userserviceをインポートします。 com.opensymphony.xwork2.actionをインポートします。 com.opensymphony.xwork2.modeldrivenをインポートします。パブリッククラスのログニクションはアクションを実装し、ModelDriven <LoginRequest> {private loginrequest = new loginrequest();プライベートユーザーサービスユーザーサービス。 @Override public String execute(){system.out.println( "login action-" + request);成功を返す; } @Override public loginrequest getModel(){return request; }}このようにして、もう1つのモデル駆動型インターフェイスが必要であり、モデル駆動型によって提供されるオブジェクトはValueStackに保存されているため、前景ページを直接渡すことができます。
ユーザー名とパスワード属性名は、フォームのパラメーター名を定義します。
3つの方法のうち、一般化すべきではないものはどれですか?それはプロジェクトの特定のニーズに依存し、それを自分で決定します!