Recommended
PDF
PDF
あの日見たMVCを僕たちはまだ知らない for RoR
ODP
PPTX
React Helmet navigates SPA
PPTX
KEY
PDF
PPT
KEY
PDF
PDF
ASP.NET MVC と jQuery で実践する標準志向 Web 開発
PDF
マイクロフレームワークEnkan(とKotowari)ではじめるREPL駆動開発
PDF
[公開用]Netラボ2012年2月勉強会 asp.netmvc4 beta新機能の紹介
PDF
jQuery/Html5/ASP.NET MVC 対応コンポーネントを用いたデバイス対応業務アプリケーション開発
PPTX
PPTX
PDF
PPTX
クライアントサイドMVVMアーキテクチャとVue.jsをまとめたよ
PPTX
PPTX
PDF
PPTX
PDF
はじめよう JavaFX 2.x(第3回 岡山Javaユーザー会)
PDF
そろそろ押さえておきたい AngularJSのセキュリティ
PDF
PDF
JavaFX 2.0 - リッチクライアントのためのUI基盤
PPTX
簡単AngularJS(関西AngularJS勉強会)
PPTX
MVPパターンによる設計アプローチ「あなたのアプリ報連相できてますか」
PPT
PDF
More Related Content
PDF
PDF
あの日見たMVCを僕たちはまだ知らない for RoR
ODP
PPTX
React Helmet navigates SPA
PPTX
KEY
PDF
PPT
What's hot
KEY
PDF
PDF
ASP.NET MVC と jQuery で実践する標準志向 Web 開発
PDF
マイクロフレームワークEnkan(とKotowari)ではじめるREPL駆動開発
PDF
[公開用]Netラボ2012年2月勉強会 asp.netmvc4 beta新機能の紹介
PDF
jQuery/Html5/ASP.NET MVC 対応コンポーネントを用いたデバイス対応業務アプリケーション開発
PPTX
PPTX
PDF
PPTX
クライアントサイドMVVMアーキテクチャとVue.jsをまとめたよ
PPTX
PPTX
PDF
PPTX
PDF
はじめよう JavaFX 2.x(第3回 岡山Javaユーザー会)
PDF
そろそろ押さえておきたい AngularJSのセキュリティ
PDF
PDF
JavaFX 2.0 - リッチクライアントのためのUI基盤
PPTX
簡単AngularJS(関西AngularJS勉強会)
PPTX
MVPパターンによる設計アプローチ「あなたのアプリ報連相できてますか」
Viewers also liked
PPT
PDF
PDF
Application Re-Architecture Technology ~ StrutsからSpring MVCへ ~
PDF
Springを何となく使ってる人が抑えるべきポイント
PDF
PPTX
Spring bootで学ぶ初めてのwebアプリ開発
Similar to Spring mvc
PDF
JavaOne 2015 報告会 @ 東京 「About MVC 1.0 & JSON-P」
PDF
【Spring fest 2019】徹底解剖Spring MVCアーキテクチャー
ODP
PDF
Spring Framework ふりかえりと4.3新機能
PDF
Spring Frameworkの今 (2013年版) #jjug_ccc #ccc_r17 #springframework
PDF
Introduction for Browser Side MVC
PPTX
今こそ知りたいSpring Web(Spring Fest 2020講演資料)
PPTX
PDF
PDF
PDF
PDF
REST with Spring Boot #jqfk
PDF
Javaで1から10まで書いた話(sanitized)
PDF
PPTX
PDF
PDF
PPTX
PDF
Jsug2015 summer spring適用におけるバッドノウハウとベタープラクティス
PDF
Spring mvc 1. 2. Spring MVC の存在価値 「 車輪の再発明は無駄 」が Spring の基本思想 それにもかかわらず、初期のバージョンから独自の MVC フレームワークを提供しているのは、作者の Rod Johnson が 既存のどの Web フレームワークにも満足できなかった から DI コンテナとしての中核機能の中に埋もれてしまっているところがあるが、実は MVC フレームワークは最も慎重に設計された Spring Framework のサブコンポーネントの一つである 3. Spring MVC の特徴 伝統的なリクエストベースフレームワーク ⇒既存のフレームワークのよいところは取り入れつつ、問題点を克服 基本的には Struts1 と同様、開発者に既に広く受けいられている、サーブレット HTTP リクエストベースの MVC フレームワークである Web リクエストを抽象化するなど、他にも特徴的な Web フレームワークも存在するが、必ずしも一般に広く受け入れられていないのが実情 イベントベース ( JSF 、 Tapestry ) コマンドベース ( WebWork2 、 Struts2 ) Struts1 や WebWork2 の持つ設計上の欠陥の多くを解決 OOP 原則の徹底 ⇒「 インタフェースに対してプログラミング 」 「 開放/閉鎖原則 」「 制御の反転( IoC ) 」という OOP の原則が徹底して実践されている モデル 、 ビュー 、 コントローラ の間で真の 責務の分離 Strategy インタフェース による多数の 拡張ポイント アジャイル開発 ⇒ Spring 2.5 以降 (2008 年以降)登場した通称 @MVC と呼ばれる新しいプログラミングモデルにより、設定ファイルフリーの、より軽量な開発が可能に 4. Spring MVC の特徴(2) 全レイヤにおける設計の一貫性 ⇒サービス層を含めたアプリケーションの全レイヤが共通の設計思想に基づいたものになる 同様の方式で、バリデーションロジックを任意のレイヤで実装できる DI や AOP の機能を Web 層でも同様に利用できる 設定ファイルの形式が全レイヤで一貫して共通化される 他の FW との連携のための拡張性 JSP 以外に PDF や Excel 、 Velocity などさまざまなビュー FW と連携可能 Struts1 、 Struts2 、 JSF など別の MVC フレームワークと連携可能 HTML ・ JSP 開発に対する非侵略性 独自 Tag ライブラリの個数は Struts1 、 Struts2 に比べるとごく少ない 大部分は標準の JSTL を利用(⇒車輪の再発明はしない) HTML タグ自体をほとんどブラックボックス化しない Web サービスへの対応 SOAP Web サービス、 REST Web サービス、 HTTP Invoker 、 Hessian など Web アプリケーション以外でも HTTP を使う処理は DispatcherServlet の共通のしくみを利用 ドキュメントが非常に充実(ただし大部分英語) 詳細な Java DOC 記述 リファレンスマニュアルや多数の書籍が利用可能 5. 6. サービス層の Bean 定義を含んだ親 DI コンテナ 特定の DispatcherServlet 専用の子 DI コンテナ (個々のコントローラ、各種 Strategy の実装が格納される) フロントコントローラとしての DispatcherServlet 7. Controller インタフェース public interface Controller { ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception; } Struts のアクションに相当し、 HTTP リクエストを処理して結果をビューに転送する責務を持つ ModelAndView クラスは、転送先のビューの論理名とビューに与えるモデルデータのマップをカプセル化 通常は Controller の実装を直接作成する必要はなく、目的に応じて抽象ベースクラスを継承して作成すればよい フォームを表示して POST バックする単純なフローの場合 SimpleFormController 単純に Controller を実装する場合 AbstractController 単一のコントローラクラスで複数のメソッドを実装したい場合 MultiActionController 順次ページをめくる複数画面から構成される画面フローの場合 AbstractWizardController 利用するケース ベースクラス名 8. 9. 「 Command 」オブジェクト Spring MVC では伝統的にフォーム Bean に相当するオブジェクトのことを 「 Command 」オブジェクト と呼ぶ この奇妙な命名の由来は、おそらく( Struts2 の前身の) WebWork を意識し過ぎたことによる誤用と考えられる WebWork のようにリクエストごとにインスタンスが生成されて、パラメータがフィールドにバインドされることによると思われるが、 execute() に相当するメソッドが通常はないため、 Command パターンではない! WebWork ( Struts2) と同様、 任意の POJO クラス をコマンドオブジェクトとして利用可能 一方、 Struts1 では ActionForm という特定のベースクラスを継承する必要がある 型チェックエラーとなると実行時例外となり、上手く回復できないので、入力項目は実質的に String 以外のフィールドにバインドできない Date 、 Enum 、 BigDecimal 、 Money などの「 ValueObject 」に直接パラメータをバインドできない! サービス層にデータを渡すために別の DTO に対してわざわざデータの詰め替えを行う必要がある 通常はフォーム Bean⇒DTO⇒ エンティティと 2 回の詰め替えが必要 !! 10. Command オブジェクトの実装例 public class AccountForm { private Account account ; private boolean newAccount ; private String repeatedPassword ; public AccountForm(Account account) { this . account = account; this . newAccount = false ; } public AccountForm() { this . account = new Account(); this . newAccount = true ; } public Account getAccount() { return account ; } public boolean isNewAccount() { return newAccount ; } public void setRepeatedPassword(String repeatedPassword) { this . repeatedPassword = repeatedPassword; } public String getRepeatedPassword() { return repeatedPassword ; } } 特定のクラスを継承する必要はない エンティティ自身をコマンドにすることもできるが、このようにエンティティを入れ子フィールドとしてラップすることで、画面固有のフィールドを追加できる コマンドという名前が連想させるように Strtus2 のアクションと同様 HTTP パラメータがバインドされてくる。ただし、通常はデータ Bean であり、 execute() に相当するメソッドはない String 以外の任意の型に直接バインド可能 11. SimpleFormController の実装例 public class AccountFormController extends SimpleFormController { private PetStoreFacade petStore; ・・・ public void setPetStore(PetStoreFacade petStore) { this .petStore = petStore; } ・・・ protected Map referenceData(HttpServletRequest request) throws Exception { Map model = new HashMap(); model.put( "languages" , LANGUAGES); model.put( "categories" , petStore.getCategoryList()); return model; } protected void onSubmit(Object command) throws Exception { AccountForm accountForm = (AccountForm) command; if (accountForm.isNewAccount()) { petStore.insertAccount(accountForm.getAccount()); } else { petStore.updateAccount(accountForm.getAccount()); } } 親クラスで Template メソッドが提供されるので、特定のフックメソッドをオーバーライド Comand クラス以外の参照データをモデルに追加して画面から参照する場合オーバーライド フォームの POST バック時の処理を実装 値を詰め替えずに直接サービス層にデータを渡すことが可能 12. 無駄なデータつめかえの弊害 余分な詰め替えロジックによる 偶発的複雑性 の増加 変更の分散コーディングスメル による メンテナンスコスト増大 特に、 Hibernate や JPA を使う場合、詰め替えはアーキテクチャ上、致命的は欠陥をもたらす JPA では「 アプリケーショントランザクション 」の継続中、エンティティを POJO として直接 Web 層で保持するモデルを推奨(というかこれがほとんど前提のアーキテクチャ?) エンティティを保持する( Detach-Merge パターンか Extended PersistenceContext パターンのどちらかの処理パターン)ことにより 、楽観ロックチェックを含めてほとんどコーディングなしで、 DB 更新処理を自動的に実現できる 詰め替えを行った場合、通常の DAO を利用した場合とほとんど同じような面倒なコーディングが必要になり、 JPA 本来のメリットがほとんど失われてしまう! Struts1 と JPA との相性が悪いことが Seasar で JPA が S2Dao に比べて人気がない原因か? 13. 複雑なクラス階層の利点と欠点 Controller のクラス階層を適切に継承することで、 TemplateMethod パターン による 差分プログラミング が実現される 特にウィザードのように画面遷移パターンが決まっている場合は、 Template Method による穴埋め問題化はメリットが非常に大きい ただし、 TemplateMethod は、静的なクラス階層に依存し、処理の流れを理解するためにある程度親クラスの実装を理解する必要があり(いわゆる グレーボックス継承 )、特に、 OOP の初心者にとってはどの親クラスを継承したらよいか判断にまようなど、敷居が高いという欠点がある Spring 2.5 以降では @MVC というまったく別のコントローラ作成方式が提供されている @MVC では従来のコントローラクラス階層を一切使用しない!(コントローラクラスは JUnit4 と同様、親クラスを継承する必要すらなくなった) 通常、 Spring2.5 以降では、 8 割~ 9 割の大部分のコントローラを新方式で作成し、パターン化が有効な少数の画面にのみ伝統的な TemplateMethod 方式を併用すればよい( @MVC については後述) 14. ModelMap クラス Spring MVC ではモデルに相当するデータは Map に格納してビューに渡す 特定のインタフェースを使って型を特定していないのは、ビューが Java コードとは限らず、最大限の柔軟性を持たせたいから( Variable State 実装パターン の応用) 対照的に Struts1 ではモデルデータが HttpServletRequest や HttpSession などの属性として格納される前提となっているため、そのままでは JSP 以外から簡単にアクセスすることができないことに! その結果 PDF ダウンロードを本来コントローラであるはずの Action クラスの中で直接実装することになってしまい、ビューとコントローラの分離が曖昧になってしまう Struts2 では ValueStack という考えの元で、モデルデータをサーブレット API から切り離しているので、 Struts1 のこの問題はない 15. View インタフェース Spring MVC ではサーブレットの出力を生成するロジックを View というインタフェースとして抽象化している View は JSP 画面に限定されない! Struts1 では View に相当する概念は存在しない Struts2 では Result が View に近い概念 以下の単純なインタフェースさえ実装すれば、 PDF 、 Excel 、 Csv ファイルなど任意の出力を生成させることが可能 public interface View { String getContentType(); void render(Map model, HttpServletRequest request, HttpServletResponse response) throws Exception; } ( VariableState 実装パターンを使って) Map に格納された任意のデータを使って、出力を行えばよい 16. ViewResolver インタフェース コントローラから渡された ModelAndView に含まれる「論理ビュー名」を元に View のインスタンスを取得するロジックをカプセル化する public interface ViewResolver { View resolveViewName(String viewName, Locale locale) throws Exception; } DispatcherServlet の DI コンテナ上には複数の ViewResolver の実装を格納できる 複数の ViewResolver が格納されていた場合、 Order インタフェースの返す数値が示す優先順位にしたがって、ビューが順次解決される Struts では( Global フォワードを除き)わざわざリクエストごとにフォワード名と JSP を設定でマップする必要があるのに比べてスマート 典型的な ViewReso l ver の設定例 < bean class = "org.springframework.web.servlet.view.XmlViewResolver" > < property name = "order" value = "1" /> < property name = "location" value = " /WEB-INF/views.xml" /> </ bean > < bean class = "org.springframework.web.servlet.view.InternalResourceViewResolver" > < property name = "order" value = "2" /> < property name = "prefix" value = "/WEB-INF/jsp/ " /> < property name = "suffix" value = ".jsp" /> </ bean > 論理名に相当するビューが views.xml に定義されていたらそれを優先的使う views.xml で解決できない場合は、論理名に prefix 、 suffix を付加したパスを元に、 JSP ファイルをビューとして使う 17. 18. Strategy による多数の拡張点 ViewResolver 以外にも、 Dispatcher サーブレットの動作をカスタマイズする多数の Strategy インタフェースの実装を DI コンテナ上に定義できる ハンドラを特定のインタフェースに適合させる HandlerAdapter ビューの論理名からビューの実体を検索する ViewResolver HTTP リクエストから該当するハンドラを解決する HandlerMapping ハンドラの呼び出し前後でフィルタ処理を実装する HandlerInterceptor 国際化のためのロケールを決定する LocaleResolver Strategy が実装すべき拡張ポイントの内容 インタフェース名 ハンドラの発生させた例外を処理する HandlerExceptionResolver アップロードファイルを解決する MartipartFileResolver スキンなどのテーマを決定する ThemeResolver 19. HandlerMapping インタフェースと HandlerExecutionChain クラス public interface HandlerMapping { HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception; } HttpRequest の内容( URL パターンやパラメタなどどんな実装も可)に基づいてリクエスト処理を行うハンドラを解決する public class HandlerExecutionChain { private final Object handler; private HandlerInterceptor[] interceptors; } ハンドラ呼び出し前後の処理をいくつでも追加できる Controller 型でなく Object 型になっている点に注目! 実は、正確には DispatcherServlet は Controller インタフェースに非依存 Convention Over Configuration により、設定ファイルなしで URL とコントローラのクラス名を自動的に対応させる( Spring2 以降ではおすすめ) ControllerClassNameHandlerMapping DI 設定 XML ファイルで URL と Bean との対応を指定 SimpleUrlHandlerMapping URL を DI コンテナ中の Bean 名にとみなす BeanNameUrlHandlerMapping ロジックの概要 実装クラス名 20. HandlerAdapter インタフェース 実は、 Spring MVC ではリクエストを行うハンドラは必ずしも Controller インタフェースを実装している必要がない HandlerAdapter によって、任意のオブジェクトを「リクエストハンドラ」として利用できる このしくみにより、たとえば、 Struts の Action を直接 DispatcherServlet から呼び出したり、後述の @MVC のように、任意の POJO をコントローラとして呼び出したりすることが可能になる public interface HandlerAdapter { boolean supports(Object handler); ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception; long getLastModified(HttpServletRequest request, Object handler); } HandlerAdapter 経由で呼び出すことで、 Controller などの特定のインタフェースを実装する必要がなくなり、任意のクラスをリクエストハンドラとして利用できる @MVC を実現するために、特定のアノテーションを付けられたメソッドをハンドラとしてリフレクション経由で呼び出す AnnotationMethodHanderAdapter Controller インタフェースを実装したクラスを単に呼び出す SimpleControllerHandlerAdapter Struts2 のようにリクエストごとに新規のハンドラインスを生成(コマンドパターン)してリクエストを処理を行う ThrowawayControllerHandlerAdapter ロジックの概要 実装クラス名 21. 22. @MVC による 新プログラミングモデル 2008 年春に登場した Spring2.5 以降、アノテーションを利用したまったく新しいコントローラ作成方法が登場 中身の仕組みは従来と変わっていないが、(エンドユーザとしての)プログラマの目に触れるプログラミングインタフェース上はまったく別の FW のように見える 設定ファイルの項目を単にアノテーション化したのではない Convention Over Configuration 機能と組み合わせることで、ほとんど XML の設定ファイルを書くことなく、非常に簡単にリクエスト処理メソッドを追加できる @MVC を上手に使うことで、 Ruby on Rails や SAStruts とほぼ同等のアジャイルな開発が Spring MVC 上で可能に ウィザードなど明らかにフローが決まっている場合は、従来の Controller クラス階層を継承する方法も併用できる(ただし、 MultiActionController はほとんど不要に!) 23. @MVC を使ったコントローラの例 @Controller public class ClinicController { @Autowired ClinicService clinicService; @Autowired OwnerValidator ownerValidator; @RequestMapping public void openWelcome() {} @RequestMapping public List<Owner> findOwners() { return clinicService .findAllOwners()); } @RequestMapping public Owner selectOwner( @RequestParam ( "ownerId" ) int ownerId) { return clinicService .loadOwner(ownerId); } @RequestMapping public String updateOwner( @ModelAttribute Owner owner, BindingResult bindingResult) { ValidationUtils.invokeValidator(owner, bindingResult) if (bindingResult.hasErrors()) { return "selectOwner" ; } else { clinicService .storeOwner(owner); return "ownerStored" ; } } } 特定の親クラスを継承することは不要 コントローラクラスに複数のリクエスト処理メソッドを自由に定義できる デフォルトでは規約により URL 文字列とメソッドが対応 ハンドラの戻り値が ModelAndView や文字列以外だったら、ハンドラメソッド名が論理ビュー名になる。この場合 /WEB-INF/jsp/clinic/findOwners.jsp が表示されることに わざわざコマンドにバインドする必要がない場合は単一のパラメータとして引数に渡すことが可能 コマンドオブジェクトはそのまま引数で指定すれば自動的にバインドされてくる。バインド結果のエラーリストもパラメタに指定可能 ハンドラメソッドの戻り値が文字列だったら、これがビュー名になる 24. 25.