Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Jsug 20160422 slides

3,387 views

Published on

2016年 Spring勉強会その3

Published in: Software
  • 発表者の池谷です。当日の発表後の個別の質疑で、Spring SecurityでURLの一部(Path Variable)の情報とDB情報を突き合わせて認可制御をしたい場合について質問をいただいた件についてUpdateがあります。5月にリリースされたSpring Security 4.1.0の以下の新機能を用いると容易に実現できると思います。http://docs.spring.io/spring-security/site/docs/4.1.x/reference/htmlsingle/#el-access-web-path-variables
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here

Jsug 20160422 slides

  1. 1. Copyright © 2016 NTT DATA Corporation. Springを用いたWebアプリケーション開発入門 2016/04/22 JSUG勉強会 2016年その3
  2. 2. 2Copyright © 2016 NTT DATA Corporation. アジェンダ 時間 セッション 内容 発表者 19:00 | 19:50 Springを用いたWeb アプリケーション開発 入門 前半 Spring/Spring MVC /Spring Security の基礎および実装デモ 池谷 熊谷 休憩時間(約10分) 20:00 | 20:50 Springを用いたWeb アプリケーション開発 入門 後半 前半の基礎を踏まえた上 での、実際の開発現場で 行われる実践的な工夫の 紹介 倉元
  3. 3. 3Copyright © 2016 NTT DATA Corporation. はじめに  本勉強会の目的 Spring MVCやSpring Securityを用いてWebアプリケーションを 開発する際に最低限必要な基礎知識を習得すること。 あえてSpring Boot無しで。 上記開発を始めるためのキッカケになること。  本勉強会の前提・対象者  Java、Servlet/JSP、HTML、 Eclipseを知っていること。  SpringでのWeb開発経験はほとんどない(入門者向け)。  本勉強会の形式 本勉強会はハンズオン形式ではありませんが、コードレベルで の解説を時間をかけて行い、理解を深められるようにしたいと 考えています。
  4. 4. Copyright © 2016 NTT DATA Corporation. Springを用いたWebアプリケーション開発入門 前半
  5. 5. 5Copyright © 2016 NTT DATA Corporation. 代表的なSpring Projects  Spring Frameworkと代表的なそのサブプロジェクトのおさらい Project Module 説明 Spring Framework core aop jdbc... • DIコンテナを提供するフレームワーク • DIコンテナを活かしたAOPやデータアクセス 層の抽象化などを実現するフレームワーク webmvc • MVCベースのWebアプリケーションフレーム ワーク Spring Security core web... • 認証・認可を実現するサーブレットフィルタ ベースのフレームワーク Spring Boot • おなじみのため略 Spring Data * commons jpa redis... • JPAやRedis、MongoDBといった異なる アーキテクチャのデータアクセス層を抽象 化、API共通化するフレームワーク Spring Cloud * netflix-eureka ... • 分散システムでよくある共通的なパターン を機能として提供するフレームワーク etc... • Spring Batch, Spring Integrationなど 他多数 https://spring.io/projects 本日の メインスコープ
  6. 6. 6Copyright © 2016 NTT DATA Corporation. SpringによるWebアプリケーションの一般的な構成例 フロント部分にSpring MVCやSpring Securityを使用 SpringのDIの上で実現→SpringのDIの最低限知識をキャッチアップ! アプリケーション層 ドメイン層 インフラストラクチャ層 Spring MVC JSP/Tiles Bean Validation POJO Spring Security セキュリティ層 Web ブラウザ 3rd-party ユーティリティ群 SLF4J Dozer Jackson Apache Commons moremore ・・・ Spring Boot データ ベース Spring Data MyBatis Spring Framework (DI, AOP ...)
  7. 7. 7Copyright © 2016 NTT DATA Corporation. 前半の流れ SpringのDIの紹介 Spring MVCの紹介 Spring MVCのデモ Spring Securityの紹介 Spring Securityのデモ
  8. 8. Copyright © 2016 NTT DATA Corporation. 8 SpringのDIの紹介
  9. 9. 9Copyright © 2016 NTT DATA Corporation. Springの技術要素 DI概要 1/3  DI (Dependency Injection:「依存性の注入」)とは? インスタンス間の依存関係の定義を、対象のクラスの外部に持たせることにより、 各クラスとその依存関係を分離する思想  DIの効果  再利用性、テスト容易性が向上する  環境依存が排除できる、など  DIの利用イメージを以下に示す 従来のアプリケーション DIの利用 ①生成 クラスA クラスB DIコンテナ クラスB クラスC ③利用 ①生成②注入 クラスA インタフェース ②取得 コンポーネント インタフェース ②利用 ①生成 ③利用 DIを実現するためにイン スタンスを管理する領域 を「DIコンテナ(またはIoC コンテナ)」と呼ぶ 依存関係 定義 依存関係 定義
  10. 10. 10Copyright © 2016 NTT DATA Corporation. Springの技術要素 DI概要 2/3  DIを利用しない場合  Mainは、executeメソッドを実行するために、new演算子でServiceインスタンス (ServiceA)を用意する必要がある  ServiceAの代わりにServiceBを利用するように変更する場合、Mainのクラスを 修正する必要がある(せっかくServiceを汎化したにもかかわらず) 実装例 public class ServiceA implements Service { // … } public class Main { // … public void use() { Service service = new ServiceA(); service.execute(); } // … } 生成 Main ServiceA 利用 ServiceAのインスタンスをMainが直接生 成する →ServiceBに切り替えるため にはコード変更が必要になる Mainの修正が発生するケースの例 ・単体テスト時 ・Mainの汎化、再利用時 ・・・ ServiceB インタフェース (Service) 依存関係 定義 生成...? 修正...?
  11. 11. 11Copyright © 2016 NTT DATA Corporation. Springの技術要素 DI概要 3/3  DIコンテナを利用する場合  DIコンテナが、Serviceのインスタンス(ServiceA)を生成し、 Mainインスタンスへ注入(インスタンスの関連付け)を行う  依存関係が外部定義されたことにより、ServiceAの代わりにServiceBを利用する ように変更する場合でも、Mainのクラスを修正する必要がない 実装例 @Component public class ServiceA implements Service { // … } public class Main{ @Autowired Service service; // … public void use() { service.execute(); } // … } DIコンテナ Main ServiceA ①生成②取得 or 注入 インタフェース (Service) コンポーネト ②Beanの注入 ①Beanの生成 ③利用 SpringにはBeanの定義を 記述する方法が3種類あります ③Beanの利用 DIコンテナが生成し、 DIコンテナで管理される インスタンスをBeanと呼 びます 依存関係 定義
  12. 12. 12Copyright © 2016 NTT DATA Corporation. Bean定義の記述方法3種類 • XML Config • Java Config • Annotation Config Java Config XML Config Annotation Config (単品では利用不可) 利用可能 @Component @Qualifier(“accountService”) public class AccountServiceImpl implements AccountService { /*…*/ } <bean id=“accountService” class=“com.example.AccountServiceImpl”> <!-- … --> </bean> @Configuration public class AccountConfig { @Bean public AccountService accountService() { // … return new AccountServiceImpl(); } } bean.xml AccountConfig.java AccountServiceImpl.java 記述方法の関係性
  13. 13. 13Copyright © 2016 NTT DATA Corporation. Bean定義の記述方法3種類 • XML Config • Java Config • Annotation Config Java Config XML Config Annotation Config (単品では利用不可) 利用可能 @Component @Qualifier(“accountService”) public class AccountServiceImpl implements AccountService { /*…*/ } <bean id=“accountService” class=“com.example.AccountServiceImpl”> <!-- … --> </bean> @Configuration public class AccountConfig { @Bean public AccountService accountService() { // … return new AccountServiceImpl(); } } bean.xml AccountConfig.java AccountServiceImpl.java 記述方法の関係性 XMLスキーマ定義に従い厳格に記述できるため統制しやすい 古い時代のSpringから提供されている手法 反面、タイプセーフでなく実行時でないとミスに気づきにくい +冗長感あり タイプセーフに記述できる(IDEで開発中に定義ミスに気付く) JavaなのでBean定義に動的な操作が記述できる(自由度が高い) XMLファイルレス、All Javaでエレガント!? 依存定義とBeanが1ファイル(Java)に集約 (大規模開発での大量のBean管理時に扱いやすい) 本日紹介 本日紹介
  14. 14. 14Copyright © 2016 NTT DATA Corporation. Bean定義方法の紹介 <<interface>> AccountService AccountServiceImpl <<interface>> AccountRepository AccountRepositoryImpl DIのメリットを活かすため、 汎化しておくことをお勧めします 今回、Bean化するクラス
  15. 15. 15Copyright © 2016 NTT DATA Corporation. XML Config <beans xmlns="...略"> <bean id="accountService" class="com.example.AccountServiceImpl" scope="singleton"> <property name="accountRepository" ref="accountRepository" /> </bean> <bean id="accountRepository“ class="com.example.AccountRepositoryImpl" scope="singleton"/> </beans> public class Main { public static void main(String[] args) { ApplicationContext context = new ClassPathXmlApplicationContext(“bean.xml"); AccountService service = context.getBean("accountService", AccountService.class); AccountRepository repository = context.getBean(AccountRepository.class); // ... } } Main.java bean.xml定義 利用
  16. 16. 16Copyright © 2016 NTT DATA Corporation. XML Config <beans xmlns="...略"> <bean id="accountService" class="com.example.AccountServiceImpl" scope="singleton"> <property name="accountRepository" ref="accountRepository" /> </bean> <bean id="accountRepository“ class="com.example.AccountRepositoryImpl" scope="singleton"/> </beans> public class Main { public static void main(String[] args) { ApplicationContext context = new ClassPathXmlApplicationContext(“bean.xml"); AccountService service = context.getBean("accountService", AccountService.class); AccountRepository repository = context.getBean(AccountRepository.class); // ... } } Main.java bean.xml Beanの生成モードを設定 singleton: 1つのインスタンスを使いまわす(default) prototype: 後述するgetBean()毎に新インスタンスを生成 インスタンスのフィールド変数(プロパティ)へsetterメソッド経由で DIを行う ※コンストラクタ経由でもDIできる(<constructor-arg>) インジェクト
  17. 17. 17Copyright © 2016 NTT DATA Corporation. XML Config <beans xmlns="...略"> <bean id="accountService" class="com.example.AccountServiceImpl" scope="singleton"> <property name="accountRepository" ref="accountRepository" /> </bean> <bean id="accountRepository“ class="com.example.AccountRepositoryImpl" scope="singleton"/> </beans> public class Main { public static void main(String[] args) { ApplicationContext context = new ClassPathXmlApplicationContext(“bean.xml"); AccountService service = context.getBean("accountService", AccountService.class); AccountRepository repository = context.getBean(AccountRepository.class); // ... } } Main.java bean.xml クラスパス上にあるBean定義ファイル(xml)から DIコンテナ(ApplicationContext)およびbeanを作成 getBean()でDI済みのbeanを取得 Bean名(id)や型などの条件でbeanの選択が可能
  18. 18. 18Copyright © 2016 NTT DATA Corporation. 参考: Namespaceによる簡略化 <beans xmlns="...略"> <bean id="emails“ class="org.springframework.beans.factory.config.ListFactoryBean"> <property name="sourceList"> <list> <value>pechorin@hero.org</value> <value>raskolnikov@slums.org</value> <value>stavrogin@gov.org</value> <value>porfiry@gov.org</value> </list> </property> </bean> <beans xmlns="…略" xmlns:util="http://www.springframework.org/schema/util" xsi:schemaLocation="...略... http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd"> <util:list id="emails"> <value>pechorin@hero.org</value> <value>raskolnikov@slums.org</value> <value>stavrogin@gov.org</value> <value>porfiry@gov.org</value> </util:list> bean.xml bean.xml XML Schemaを利用した典型定義の簡略化が可能(下記はListのBeanを作る場合の例) DIコンテナ上に展開されるSpring MVCやSpring Securityでは不可欠な機能! Before After
  19. 19. 19Copyright © 2016 NTT DATA Corporation. Annotation Config @Service @Qualifier("accountService") public class AccountServiceImpl implements AccountService { @Autowired private AccountRepository accountRepository; public void deleteAccount(String id) { accountRepository.delete(id); } } @Repository public class AccountRepositoryImpl implements AccountRepository { // ... } *.java定義 XML Configと同じ 利用 <beans xmlns="...略"> <context:component-scan base-package="com.example" /> bean.xml
  20. 20. 20Copyright © 2016 NTT DATA Corporation. Annotation Config @Service @Qualifier("accountService") public class AccountServiceImpl implements AccountService { @Autowired private AccountRepository accountRepository; public void deleteAccount(String id) { accountRepository.delete(id); } } @Repository public class AccountRepositoryImpl implements AccountRepository { // ... } *.java定義 XML Configと同じ <beans xmlns="...略"> <context:component-scan base-package="com.example" /> bean.xml 汎用的な@Componentに加え、用途に応じた マーカーアノテーション@Service, @Controller, @Repositoryも利用可能 Annotation Configを有効にし、スキャン対象の クラスを基底パッケージで指定 (Namespaceで設定を簡略化) 利用
  21. 21. 21Copyright © 2016 NTT DATA Corporation. Annotation Config @Service @Qualifier("accountService") public class AccountServiceImpl implements AccountService { @Autowired private AccountRepository accountRepository; public void deleteAccount(String id) { accountRepository.delete(id); } } @Repository public class AccountRepositoryImpl implements AccountRepository { // ... } *.java定義 XML Configと同じ 利用 <beans xmlns="...略"> <context:component-scan base-package="com.example" /> bean.xml 名前ベースでgetBean()やDIを使用する場合に必要 インスタンスのフィールド変数(プロパティ) へDIを行う(setterメソッドは不要) ※JSR 330の@Inject等も使用可能
  22. 22. 22Copyright © 2016 NTT DATA Corporation. 前半の流れ SpringのDIの紹介 Spring MVCの紹介 Spring MVCのデモ Spring Securityの紹介 Spring Securityのデモ
  23. 23. Copyright © 2016 NTT DATA Corporation. 23 Spring MVCの紹介
  24. 24. 24Copyright © 2016 NTT DATA Corporation. Spring MVCアーキテクチャ概要 1/2  Spring MVCの概要  MVCパターンを採用したアクションベースのWebアプリケーションフレームワーク  Model :アプリケーションの状態(データ)やビジネスロジックを提供する要素  View :Modelが保持するアプリケーションの状態(データ)を参照し、 クライアントへ返却するレスポンスデータを生成する要素  Controller :リクエストをハンドリングし、ModelとViewの呼び出しを制御する要素 Controller クライアント (ブラウザ) View (JSP) Model (1) リクエスト (2) 状態の更新 (ロジック実行) データ参照 (4) レスポンス (HTML) (3) レスポンスデータ (HTML)生成
  25. 25. 25Copyright © 2016 NTT DATA Corporation. Spring MVCアーキテクチャ概要 2/2 Dispatcher Servlet Handler Mapping Handler Adapter View Resolver Controller Service (業務処理) Repository Model View ①リクエスト ② ③ ④ ⑤ ⑥ ⑦ ⑧レスポンス Controllerを選定 業務処理 を実行 処理結果を Modelに設定 View解決 Modelに格納されている処理結果を参照 データベース View名を返却 業務処理を実行 するクラス Webブラウザに、HTML/PDFなど さまざまな形式でレスポンスを返却 データベースアクセス を提供するクラス 【凡例】 要作成 フレームワーク 提供 要作成 (フレームワーク提供も含まれる) 処理の流れ 処理内容 画面遷移の制御、Serviceの 呼び出しを行うクラス Controller View Model 各インスタンスはDIコンテナ上に作成され Springに管理される
  26. 26. 26Copyright © 2016 NTT DATA Corporation. コード例 <?xml version="1.0" encoding="ISO-8859-1"?> <web-app xmlns:xsi=…略> <listener> <listener-class> org.springframework.web.context.ContextLoaderListener </listener-class> </listener> <context-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:spring/application-config.xml</param-value> </context-param> <servlet> <servlet-name>dispatcherServlet</servlet-name> <servlet-class> org.springframework.web.servlet.DispatcherServlet </servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/mvc-config.xml</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>dispatcherServlet</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> </web-app> web.xml 子DIコンテナ 親DIコンテナ 子から親はアクセス可能 もちろんServlet3.0のServletContainerInitializerも利用可
  27. 27. 27Copyright © 2016 NTT DATA Corporation. コード例 <!-- SpringMVCに@Controllerを検知させる --> <mvc:annotation-driven /> <!-- @Controllerの探索場所を指定する --> <context:component-scan base-package="com.example.helloworld.app" /> <!– Viewの種類(JSP)およびパスの設定 --> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="prefix" value="/WEB-INF/view/"/> <property name="suffix" value=".jsp"/> </bean> @Controller public class HelloController { @RequestMapping("/hello") public String greeting( @RequestParam("name") String name, Model model) { model.addAttribute("name", name); return "greeting"; } } <!DOCTYPE html> <html> <head> <title>Hello World</title> </head> <body> <h2>your name is ${name}</h2> </body> </html> HelloController.java WEB-INF/view/greeting.jsp mvc-config.xml
  28. 28. 28Copyright © 2016 NTT DATA Corporation. コード例 <!-- SpringMVCに@Controllerを検知させる --> <mvc:annotation-driven /> <!-- @Controllerの探索場所を指定する --> <context:component-scan base-package="com.example.helloworld.app" /> <!– Viewの種類(JSP)およびパスの設定 --> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="prefix" value="/WEB-INF/view/"/> <property name="suffix" value=".jsp"/> </bean> @Controller public class HelloController { @RequestMapping("/hello") public String greeting( @RequestParam("name") String name, Model model) { model.addAttribute("name", name); return "greeting"; } } <!DOCTYPE html> <html> <head> <title>Hello World</title> </head> <body> <h2>your name is ${name}</h2> </body> </html> HelloController.java WEB-INF/view/greeting.jsp mvc-config.xml Spring MVCのネームスペースを利用し、 Spring MVCモジュールの設定を簡略化 @ControllerのついたbeanをDIコンテナに 生成するために必要
  29. 29. 29Copyright © 2016 NTT DATA Corporation. 参考 Spring Bootでは・・・ <?xml version="1.0" encoding="ISO-8859-1"?> <web-app xmlns:xsi=…略> <listener> <listener-class> org.springframework.web.context.ContextLoaderListener </listener-class> </listener> ... web.xml ... <!– Viewの種類(JSP)およびパスの設定 --> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="prefix" value="/WEB-INF/view/"/> <property name="suffix" value=".jsp"/> </bean> @Controller public class HelloController { @RequestMapping("/hello") public String greeting( @RequestParam("name") String name, Model model) { model.addAttribute("name", name); return "greeting"; } } <!DOCTYPE html> <html> <head> <title>Hello World</title> </head> <body> <h2>your name is ${name}</h2> </body> </html> HelloController.java WEB-INF/view/greeting.jsp mvc-config.xml
  30. 30. 30Copyright © 2016 NTT DATA Corporation. 参考 Spring Bootでは・・・ <?xml version="1.0" encoding="ISO-8859-1"?> <web-app xmlns:xsi=…略> <listener> <listener-class> org.springframework.web.context.ContextLoaderListener </listener-class> </listener> ... web.xml ... <!– Viewの種類(JSP)およびパスの設定 --> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="prefix" value="/WEB-INF/view/"/> <property name="suffix" value=".jsp"/> </bean> mvc-config.xml @Controller public class HelloController { @RequestMapping("/hello") public String greeting( @RequestParam("name") String name, Model model) { model.addAttribute("name", name); return "greeting"; } } <!DOCTYPE html> <html> <head> <title>Hello World</title> </head> <body> <h2>your name is ${name}</h2> </body> </html> HelloController.java WEB-INF/view/greeting.jsp Auto Configurationにより設定不要 application.propertiesで簡易化 spring.mvc.view.prefix=/WEB-INF/jsp/ spring.mvc.view.suffix=.jsp
  31. 31. 31Copyright © 2016 NTT DATA Corporation. 参考 Spring Bootでは・・・ <?xml version="1.0" encoding="ISO-8859-1"?> <web-app xmlns:xsi=…略> <listener> <listener-class> org.springframework.web.context.ContextLoaderListener </listener-class> </listener> ... web.xml ... <!– Viewの種類(JSP)およびパスの設定 --> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="prefix" value="/WEB-INF/view/"/> <property name="suffix" value=".jsp"/> </bean> mvc-config.xml @Controller public class HelloController { @RequestMapping("/hello") public String greeting( @RequestParam("name") String name, Model model) { model.addAttribute("name", name); return "greeting"; } } <!DOCTYPE html> <html> <head> <title>Hello World</title> </head> <body> <h2 th:text=“‘your name is ’ + ${name}” /> </body> </html> HelloController.java templates/greeting.html Auto Configurationにより設定不要 application.propertiesで簡易化 spring.mvc.view.prefix=/WEB-INF/jsp/ spring.mvc.view.suffix=.jsp Spring Bootなら Thymeleaf! もちろんSpring MVCだけでも 同様にViewの切り替えが可能!
  32. 32. 32Copyright © 2016 NTT DATA Corporation. 前半の流れ SpringのDIの紹介 Spring MVCの紹介 Spring MVCのデモ Spring Securityの紹介 Spring Securityのデモ
  33. 33. Copyright © 2016 NTT DATA Corporation. 33 Spring MVCのデモ
  34. 34. 34Copyright © 2016 NTT DATA Corporation. Spring MVCのデモ •疎通確認 –Controllerの作成 –ComponentScanの有効化 –JSPの作成 •Echo入力ページ作成 –フォームオブジェクトの作成 –Controllerにフォームオブジェクトの登録 –JSPへテキストボックスを追加 •Echo出力ページ作成 –出力用のリクエストハンドラを追加 –出力用JSPの作成
  35. 35. 35Copyright © 2016 NTT DATA Corporation. 前半の流れ SpringのDIの紹介 Spring MVCの紹介 Spring MVCのデモ Spring Securityの紹介 Spring Securityのデモ
  36. 36. Copyright © 2016 NTT DATA Corporation. 36 Spring Securityの紹介
  37. 37. 37Copyright © 2016 NTT DATA Corporation. 認可認証 Spring Security概要 Spring Security概要 アプリケーションのセキュリティを担う「認証」、「認可」 の2つを主な機能として提供している  認証:なりすましによる不正アクセスに対抗するために、 ユーザを識別すること  認可:認証された(ログイン中)ユーザの権限(ロール)に応 じて、システムのリソースに対するアクセス制御を行うこと 商品データ 顧客データ 豊洲 太郎 商品開発担当 月島 次郎 営業担当 OK NG OK OK = = ? ? id/pw id/pw
  38. 38. 38Copyright © 2016 NTT DATA Corporation. Spring Security アーキテクチャ概要 spring-security-web FilterChain Proxy <interface> Http Firewall (3)(2)Client Web Application Resources Servlet Filter Servlet jsp ・・・ (5) 巨大な Servlet Filter (1) (6) <interface> SecurityFilterChain Security Filter 1 ・・・ Security Filter N (4) DIコンテナで 管理される Bean
  39. 39. 39Copyright © 2016 NTT DATA Corporation. コード例 ... <listener> <listener-class> org.springframework.web.context.ContextLoaderListener </listener-class> </listener> <context-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:spring/security-config.xml</param-value> </context-param> <filter> <filter-name>springSecurityFilterChain</filter-name> <filter-class> org.springframework.web.filter.DelegatingFilterProxy </filter-class> </filter> <filter-mapping> <filter-name>springSecurityFilterChain</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> ... web.xml Spring Securityのコンポーネントを管理する DIコンテナを作成 DIコンテナ上のSpring Securityコンポーネント へ処理を移譲するサーブレットフィルタ Step1: サーブレットフィルタの設定
  40. 40. 40Copyright © 2016 NTT DATA Corporation. コード例 <?xml version="1.0" encoding="UTF-8"?> <beans xmlns=“...略"> <sec:http> <sec:form-login login-page="/login/loginForm" /> <sec:intercept-url pattern="/sales/**" access="hasRole('SALES')" /> <sec:intercept-url pattern="/producs/**" access="hasAnyRole('SALES', 'DEVS')" /> <sec:intercept-url pattern="/login/**" access="permitAll" /> <sec:intercept-url pattern="/**" access="isAuthenticated()" /> </sec:http> <sec:authentication-manager> <sec:authentication-provider> <sec:user-service> <sec:user name="taro.toyosu" password="xxx“ authorities="ROLE_DEVS" /> <sec:user name="jiro.tsukishima" password="yyy" authorities="ROLE_SALES" /> </sec:user-service> </sec:authentication-provider> </sec:authentication-manager> </beans> security-config.xml Step2: SecurityFilterChainのbean定義
  41. 41. 41Copyright © 2016 NTT DATA Corporation. コード例 <?xml version="1.0" encoding="UTF-8"?> <beans xmlns=“...略"> <sec:http> <sec:form-login login-page="/login/loginForm" /> <sec:intercept-url pattern="/sales/**" access="hasRole('SALES')" /> <sec:intercept-url pattern="/producs/**" access="hasAnyRole('SALES', 'DEVS')" /> <sec:intercept-url pattern="/login/**" access="permitAll" /> <sec:intercept-url pattern="/**" access="isAuthenticated()" /> </sec:http> <sec:authentication-manager> <sec:authentication-provider> <sec:user-service> <sec:user name="taro.toyosu" password="xxx“ authorities="ROLE_DEVS" /> <sec:user name="jiro.tsukishima" password="yyy" authorities="ROLE_SALES" /> </sec:user-service> </sec:authentication-provider> </sec:authentication-manager> </beans> security-config.xml Step2: SecurityFilterChainのbean定義 認証方法としてフォーム認証を選択 (他はBASIC認証などが選択可能) login-page属性を省略すると、Spring Securityの 組込フォーム画面を利用することもできる
  42. 42. 42Copyright © 2016 NTT DATA Corporation. <?xml version="1.0" encoding="UTF-8"?> <beans xmlns=“...略"> <sec:http> <sec:form-login login-page="/login/loginForm" /> <sec:intercept-url pattern="/sales/**" access="hasRole('SALES')" /> <sec:intercept-url pattern="/producs/**" access="hasAnyRole('SALES', 'DEVS')" /> <sec:intercept-url pattern="/login/**" access="permitAll" /> <sec:intercept-url pattern="/**" access="isAuthenticated()" /> </sec:http> <sec:authentication-manager> <sec:authentication-provider> <sec:user-service> <sec:user name="taro.toyosu" password="xxx“ authorities="ROLE_DEVS" /> <sec:user name="jiro.tsukishima" password="yyy" authorities="ROLE_SALES" /> </sec:user-service> </sec:authentication-provider> </sec:authentication-manager> </beans> security-config.xml Step2: SecurityFilterChainのbean定義 コード例 認証処理の実行:authentication-manager 認証情報の提供:authentication-provider 簡単のためXML組込の認証情報を使用 (user-service)しているが、DB参照や任意の 拡張が可能
  43. 43. 43Copyright © 2016 NTT DATA Corporation. <?xml version="1.0" encoding="UTF-8"?> <beans xmlns=“...略"> <sec:http> <sec:form-login login-page="/login/loginForm" /> <sec:intercept-url pattern="/sales/**" access="hasRole('SALES')" /> <sec:intercept-url pattern="/producs/**" access="hasAnyRole('SALES', 'DEVS')" /> <sec:intercept-url pattern="/login/**" access="permitAll" /> <sec:intercept-url pattern="/**" access="isAuthenticated()" /> </sec:http> <sec:authentication-manager> <sec:authentication-provider> <sec:user-service> <sec:user name="taro.toyosu" password="xxx“ authorities="ROLE_DEVS" /> <sec:user name="jiro.tsukishima" password="yyy" authorities="ROLE_SALES" /> </sec:user-service> </sec:authentication-provider> </sec:authentication-manager> </beans> security-config.xml Step2: SecurityFilterChainのbean定義 コード例 各リソースに対する認可制御のルールを EL式で定義 ※Spring Security 4以上ではhasRole()など で「ROLE_」プレフィックスが省略可能
  44. 44. 44Copyright © 2016 NTT DATA Corporation. 前半の流れ SpringのDIの紹介 Spring MVCの紹介 Spring MVCのデモ Spring Securityの紹介 Spring Securityのデモ
  45. 45. Copyright © 2016 NTT DATA Corporation. 45 Spring Securityのデモ
  46. 46. 46Copyright © 2016 NTT DATA Corporation. Spring Securityのデモ •Spring Securityの設定 –Dependencyの追加 –Filterの追加 –Spring Security用のConfigの追加 •認証 –AuthenticationManagerの設定 –ログアウトボタンの作成 •認可 –ページに認可設定
  47. 47. Copyright © 2016 NTT DATA Corporation. Springを用いたWebアプリケーション開発入門 後半
  48. 48. 48Copyright © 2016 NTT DATA Corporation. 後半の概要  前半では、Springを使ったWebアプリケーション開発 の概要を見ていきました。  とはいえ、ここまでの内容で実際の開発が滞りなく 進むわけではありません。  ここからは、SIの現場でよくあるポイントをコード例な どを交えつつ紹介します。
  49. 49. 49Copyright © 2016 NTT DATA Corporation. サマリ 開発ノウハウ  アーキテクチャに関するノウハウ  環境依存をどう排除するか  アプリケーションレイヤをどう切るか  機能に関するノウハウ  DBアクセス  入力チェック  セッション管理
  50. 50. Copyright © 2016 NTT DATA Corporation. 50 アーキテクチャに関するノウハウ
  51. 51. 51Copyright © 2016 NTT DATA Corporation. 環境依存を どう排除するか?
  52. 52. 52Copyright © 2016 NTT DATA Corporation. 環境依存をどう排除するか? Springはアプリケーションの構成を決めていない。 例えば、試験環境と本番環境の差分(DBのURLとか、JNDI名とか)を どう管理するかはユーザー任せ。 どうデプロイする?どうビルドして Java Jar 設定ファイル … ビルドスクリプトで頑張る? サーバーの環境変数で頑張る? それもなんだかなぁ・・・
  53. 53. 53Copyright © 2016 NTT DATA Corporation. 環境依存をどう排除するか? 「いっそmavenのmulti-moduleで環境設定を切り出してしまおう」 試験環境なら、env-test.jar、本番環境なら、env-prov.jar… ちなみに: 一応、@ProfileでDIの設定を切り替えることはできる。 しかし、そもそもテスト用の設定が本番にデプロイされてしまうのは事故の元。 XXX-App XXX-Web XXX-domain XXX-env (試験用) XXX-env (本番用) 試験用 War 本番用 War 環境ごとにビルドすればいいや!
  54. 54. 54Copyright © 2016 NTT DATA Corporation. 環境依存をどう排除するか? さらにもう一歩進んで… デプロイ方法は以下のように開発フェーズに応じてやり方を変えるとよい。 ビルド方法 利用 シーン 説明 env.jarをwarファイルに 含めない 運用時 • 環境依存性を排除するためにenv.jarをwarファ イルに含めない(どの環境でも同じものが利用 できる) • envモジュールのみ環境ごとにビルドしてデプロ イする env.jarをwarファイルに 含める 開発時 • 環境に依存したwarファイルが作成される(テス ト時に簡単のため利用する) • 環境ごとにビルドが必要で、別環境では正しく 動作する保証がない
  55. 55. 55Copyright © 2016 NTT DATA Corporation. コードイメージ <!– web pom.xml --> <profiles> <profile> <id>warpack</id> </profile> <profile> <id>warpack-with-env</id> <dependencies> <dependency> <groupId>${project.groupId}</groupId> <artifactId>xxx-env</artifactId> <exclusions> <exclusion> <!-- omitted --> </exclusion> </exclusions> </dependency> </dependencies> </profile> </profiles> <dependencies> <dependency> <groupId>${project.groupId}</groupId> <artifactId>xxx-domain</artifactId> </dependency> </dependencies> $ cd ./todo -- envを含めない $ mvn -P warpack clean package -- envを含める $ mvn -P warpack-with-env clean package
  56. 56. 56Copyright © 2016 NTT DATA Corporation. アプリケーションレイヤ を どう切るか?
  57. 57. 57Copyright © 2016 NTT DATA Corporation. アプリケーションレイヤをどう切るか?  Spring-mvcはあくまでmvcの切り方は決まる  しかし、ビジネスロジックやDAO等の作り方は決まってない。 業務処理の結果を参照する Controller View リクエスト レスポンス データベース Model データベース アクセス 画面遷移する 業務処理を呼び出す MVCはわかったけど… 結局どこに何を書けばいいんだろう…?
  58. 58. 58Copyright © 2016 NTT DATA Corporation. アプリケーションレイヤをどう切るか? その気になれば1クラスに全部押し込むこともできる。 もちろん、それはNG  複雑度が増す • テストしにくい or できない • コピペコードの氾濫  環境依存度が増す • OS/MWが常に必要 結果、  機能追加も無理です…  デグレ確認するときは常に全量だ… もうメンテできないよ・・・
  59. 59. 59Copyright © 2016 NTT DATA Corporation. アプリケーションレイヤをどう切るか? 項番 レイヤ 概要 1 ドメイン層 業務処理を実行する 2 インフラストラクチャ層 データストア(RDBMS、NoSQLなど)へのアクセスを行う 3 アプリケーション層 クライアントとのデータの入出力を制御する View Controller RepositoryImplServiceImpl HTTP リクエスト HTTP レスポンス Repository インタフェース O/R Mapper (1) (2) (3) (4) (6) (7)(8) (9) (10) (5) Entity Service インタフェース アプリケーション層 ドメイン層 インフラストラクチャ層 データ ベース 以下のようにする。 Controllerは画面遷移に徹する。 ビジネスロジックはPOJOに切り出してControllerにDIして呼び出す。 DAOも別クラスに切り出して隠蔽化する。 •アプリケーションを論理的なレイヤに分けると良い。
  60. 60. 60Copyright © 2016 NTT DATA Corporation. アプリケーションレイヤをどう切るか? Controller RepositoryImpl O/R Mapper ServiceImpl Entity use instantiate use Service インタフェース Repository インタフェース use use View Formオブジェクト use use ドメイン層 アプリケーション層 インフラストラクチャ層 use use Model View Controller
  61. 61. 61Copyright © 2016 NTT DATA Corporation. コード例 <<Controller>> @Controller public class TodoController { @Inject TodoService todoService; @RequestMapping(value = "todo/list") public String list(Model model) { Collection<Todo> todos = todoService.findAll(); model.addAttribute("todos", todos); return "todo/list"; } } <<todo/list.jsp>> ${f:h(todo.todoTitle)} GET /todo/list 次ページ へ
  62. 62. 62Copyright © 2016 NTT DATA Corporation. <<Repositoryインタフェース>> public interface todoRepository<T> { T findOne(ID id); boolean exists(ID id); List<T> findAll(); long count(); void delete(T entity); } <<Serviceインタフェース>> public interface TodoService { Collection<Todo> findAll(); Todo create(Todo todo); Todo finish(String todoId); void delete(String todoId); } <<ServiceImpl>> @Service @Transactional public class TodoServiceImpl implements TodoService { @Inject TodoRepository todoRepository; // … @Transactional(readOnly = true) public Collection<Todo> findAll() { return todoRepository.findAll(); } // … } <<Entity>> public class Todo { private String todoId; private List<Item> itemCode; // setter/getter }
  63. 63. Copyright © 2016 NTT DATA Corporation. 63 機能に関するノウハウ
  64. 64. 64Copyright © 2016 NTT DATA Corporation. DBアクセス
  65. 65. 65Copyright © 2016 NTT DATA Corporation. DBアクセス  spring-mvcだけだとDBアクセス部分は素のJDBCになってしまう。  springはDBアクセスの方法をいくつか持っている。  Spring FrameworkのJDBCTemplate(と、Spring DataのJDBC Extentions)  Spring Data JPA  3rd-partyライブラリも色々ある  Hibernate  MyBatis  Doma etc...
  66. 66. 66Copyright © 2016 NTT DATA Corporation.  SpringのJDBCTemplateではSQLをソースに書いたり、マッピ ング処理をソースで書くので、大規模開発になると辛い・・・ ということで…  SQL文を書きたいならMyBatisがよいかな  SQL文・発行タイミングを細かくチューニングできる  JPA(というかHibernate)のノウハウがあるなら、 Spring JPA(+ Hibernate)かな
  67. 67. 67Copyright © 2016 NTT DATA Corporation. Bean定義ファイルの設定例 <mybatis:scan base-package="com.example.domain.repository.todo" /> JavaのインタフェースとMyBatis3の設定ファイルの配置 ・Repositoryインタフェース src com example domain repository todo TodoRepository.java ・マッピングファイル resources com example domain repository todo TodoRepository.xml ファイル名は 「Repositoryインタフェース名」+「.xml」 とする Repositoryインタフェースとマッピングファイルは 同一階層に配置する Repositoryインタフェース名
  68. 68. 68Copyright © 2016 NTT DATA Corporation. TodoRepository.xmlの例 <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="todo.domain.repository.todo.TodoRepository"> <resultMap id="todoResultMap" type="Todo"> <id property="todoId" column="todo_id" /> <result property="todoTitle" column="todo_title" /> <result property="finished" column="finished" /> <result property="createdAt" column="created_at" /> </resultMap> <select id="findAll" resultMap="todoResultMap"> <![CDATA[ SELECT todo_id, todo_title, finished, created_at FROM todo ]]> </select> <insert id="create" parameterType="Todo"> // ommited </insert> <update id="update" parameterType="Todo"> // ommited </update> </mapper>
  69. 69. 69Copyright © 2016 NTT DATA Corporation. 入力チェック
  70. 70. 70Copyright © 2016 NTT DATA Corporation. 入力チェック  サーバーサイドでの入力チェックは絶対必要。クライアントだけじゃダメゼッタイ。  入力チェックの方法は色々存在する  古くはcommons-validator  Spring自身もSpring Validatorを持っている  割と最近Javaでも標準化された(JSR303 Bean Validation@JavaEE6~)  spring-mvcと合わせて使うならBeanValidation一択。  Spring ValidatorがBean Validationに対応していて、透過的に扱える  実装はRIのHibernate Validatorで。 Controller SpringMVCブラウザ ① 入力データを送信 ⑦ 結果を返却 View Form オブジェクト ⑤ View名を返却 ② Formオブジェクトに入力データを格納し て、リクエストハンドラメソッドの引数に指定 処理 メソッド ④ Formオブジェクト の検証結果を確認 ⑥ エラーメッセージを設定 Bean Validation/Spring Validator ③ Controller呼び出しのタイミング でFormオブジェクトの検証を行う
  71. 71. 71Copyright © 2016 NTT DATA Corporation. Formオブジェクトの実装例 public class UserForm implements Serializable { @NotNull @Size(min = 1, max = 20) private String name; @NotNull @Size(min = 1, max = 50) @Email private String email; @NotNull @Min(0) @Max(200) private Integer age; } Controllerの実装例 @Controller @RequestMapping("user") public class UserController { @RequestMapping(value = "create", method = RequestMethod.POST, params = "confirm") public String createConfirm( @Validated UserForm form, BindingResult result) { if (result.hasErrors()) { return "user/createForm"; } return "user/createConfirm"; } } 入力チェックを行うために@Validatedを指定する 検証結果を格納するBindingResultを 直後に指定する BindingResult#hasErrors()で検証結果にエラーが 含まれるか確認する
  72. 72. 72Copyright © 2016 NTT DATA Corporation. Viewの実装例 <form:form modelAttribute="userForm" method="post" action="${pageContext.request.contextPath}/user/create"> <form:label path="name">Name:</form:label> <form:input path="name" /> <form:errors path="name" /> <br> <form:label path="email">Email:</form:label> <form:input path="email" /> <form:errors path="email" /> <br> <form:label path="age">Age:</form:label> <form:input path="age" /> <form:errors path="age" /> <br> <form:button name="confirm">Confirm</form:button> </form:form> path属性に、対象のフィールド 名を指定する 画面の表示例 RFC2822準拠のE-mail形式ではないため、エラー メッセージが表示されている 0から200の範囲外のため、エラーメッセージが表示 されている
  73. 73. 73Copyright © 2016 NTT DATA Corporation. セッション管理
  74. 74. 74Copyright © 2016 NTT DATA Corporation. セッション管理  Javaにかぎらず、サーバーサイドアプリケーションではセッションがつきもの。 JavaのServlet仕様だとSessionを低レイヤに扱うので辛い・・・  Spring-mvcでは以下の2択で対処する。 • @SessionAttributes • sessionスコープのBean 方法 利用シーン 利用例 sessionスコープのBean 複数のControllerをまたいで、データを持ち 回る場合 ショッピングサイトのカートのように、複数 のユースケースでデータを共有する場合 @SesseionAttributes Controller内に閉じて、 データを持ち回る場合 ウィザード画面のような複数の画面で、 1つ処理を構成する場合 ブラウザ Controller-A methodA HttpSession session Bean sessionスコープのBeanのイメージ Controller-C Controller-B methodB methodC 画面1 画面2 画面3 ブラウザ @SessionAttributesのイメージ Controller-A methodA HttpSession form Object methodB methodC 画面1 画面2 画面3 複数のControllerからセッションに 格納された同一のデータを参照 Controller内の画面遷移でセッション に格納された同一のデータを参照
  75. 75. 75Copyright © 2016 NTT DATA Corporation. コード例は割愛
  76. 76. Copyright © 2016 NTT DATA Corporation. 76 最後に
  77. 77. 77Copyright © 2016 NTT DATA Corporation. ここまで紹介してきた開発ノウハウは TERASOLUNAで公開しています! しかも今日の内容は ほんの一部です!
  78. 78. 78Copyright © 2016 NTT DATA Corporation. TERASOLUNA Server Framework for Java (5.x) Development Guideline http://terasolunaorg.github.io/guideline/
  79. 79. 79Copyright © 2016 NTT DATA Corporation.
  80. 80. 80Copyright © 2016 NTT DATA Corporation. きっとヒントになるはず! ぜひ、一回見てみてください!
  81. 81. 81Copyright © 2016 NTT DATA Corporation. 他にも役に立つものがいろいろ! •エンタープライズ向けに必要な汎用的な部品共通ライブラリ •OSSを利用したエンタープライズ向け アプリ開発におけるベストプラクティスドキュメントガイドライン •基本的な開発方法を学ぶ学習教材チュートリアル •ガイドラインに則って一部の機能を実装したアプリケーションサンプルAP •プロジェクト構成のひな形ブランクプロジェクト
  82. 82. Copyright © 2011 NTT DATA Corporation Copyright © 2016 NTT DATA Corporation.

×