Más contenido relacionado
La actualidad más candente (20)
Similar a Jsug 20160422 slides (20)
Más de Yuichi Hasegawa (14)
Jsug 20160422 slides
- 1. Copyright © 2016 NTT DATA Corporation.
Springを用いたWebアプリケーション開発入門
2016/04/22
JSUG勉強会 2016年その3
- 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. 3Copyright © 2016 NTT DATA Corporation.
はじめに
本勉強会の目的
Spring MVCやSpring Securityを用いてWebアプリケーションを
開発する際に最低限必要な基礎知識を習得すること。
あえてSpring Boot無しで。
上記開発を始めるためのキッカケになること。
本勉強会の前提・対象者
Java、Servlet/JSP、HTML、 Eclipseを知っていること。
SpringでのWeb開発経験はほとんどない(入門者向け)。
本勉強会の形式
本勉強会はハンズオン形式ではありませんが、コードレベルで
の解説を時間をかけて行い、理解を深められるようにしたいと
考えています。
- 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. 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. 7Copyright © 2016 NTT DATA Corporation.
前半の流れ
SpringのDIの紹介
Spring MVCの紹介
Spring MVCのデモ
Spring Securityの紹介
Spring Securityのデモ
- 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. 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. 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. 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. 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. 14Copyright © 2016 NTT DATA Corporation.
Bean定義方法の紹介
<<interface>>
AccountService
AccountServiceImpl
<<interface>>
AccountRepository
AccountRepositoryImpl
DIのメリットを活かすため、
汎化しておくことをお勧めします
今回、Bean化するクラス
- 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. 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. 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. 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. 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. 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. 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. 22Copyright © 2016 NTT DATA Corporation.
前半の流れ
SpringのDIの紹介
Spring MVCの紹介
Spring MVCのデモ
Spring Securityの紹介
Spring Securityのデモ
- 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. 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. 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. 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. 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. 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. 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. 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. 32Copyright © 2016 NTT DATA Corporation.
前半の流れ
SpringのDIの紹介
Spring MVCの紹介
Spring MVCのデモ
Spring Securityの紹介
Spring Securityのデモ
- 34. 34Copyright © 2016 NTT DATA Corporation.
Spring MVCのデモ
•疎通確認
–Controllerの作成
–ComponentScanの有効化
–JSPの作成
•Echo入力ページ作成
–フォームオブジェクトの作成
–Controllerにフォームオブジェクトの登録
–JSPへテキストボックスを追加
•Echo出力ページ作成
–出力用のリクエストハンドラを追加
–出力用JSPの作成
- 35. 35Copyright © 2016 NTT DATA Corporation.
前半の流れ
SpringのDIの紹介
Spring MVCの紹介
Spring MVCのデモ
Spring Securityの紹介
Spring Securityのデモ
- 37. 37Copyright © 2016 NTT DATA Corporation.
認可認証
Spring Security概要
Spring Security概要
アプリケーションのセキュリティを担う「認証」、「認可」
の2つを主な機能として提供している
認証:なりすましによる不正アクセスに対抗するために、
ユーザを識別すること
認可:認証された(ログイン中)ユーザの権限(ロール)に応
じて、システムのリソースに対するアクセス制御を行うこと
商品データ
顧客データ
豊洲 太郎
商品開発担当
月島 次郎
営業担当
OK
NG
OK
OK
=
=
?
?
id/pw
id/pw
- 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. 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. 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. 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. 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. 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. 44Copyright © 2016 NTT DATA Corporation.
前半の流れ
SpringのDIの紹介
Spring MVCの紹介
Spring MVCのデモ
Spring Securityの紹介
Spring Securityのデモ
- 46. 46Copyright © 2016 NTT DATA Corporation.
Spring Securityのデモ
•Spring Securityの設定
–Dependencyの追加
–Filterの追加
–Spring Security用のConfigの追加
•認証
–AuthenticationManagerの設定
–ログアウトボタンの作成
•認可
–ページに認可設定
- 48. 48Copyright © 2016 NTT DATA Corporation.
後半の概要
前半では、Springを使ったWebアプリケーション開発
の概要を見ていきました。
とはいえ、ここまでの内容で実際の開発が滞りなく
進むわけではありません。
ここからは、SIの現場でよくあるポイントをコード例な
どを交えつつ紹介します。
- 49. 49Copyright © 2016 NTT DATA Corporation.
サマリ
開発ノウハウ
アーキテクチャに関するノウハウ
環境依存をどう排除するか
アプリケーションレイヤをどう切るか
機能に関するノウハウ
DBアクセス
入力チェック
セッション管理
- 52. 52Copyright © 2016 NTT DATA Corporation.
環境依存をどう排除するか?
Springはアプリケーションの構成を決めていない。
例えば、試験環境と本番環境の差分(DBのURLとか、JNDI名とか)を
どう管理するかはユーザー任せ。
どうデプロイする?どうビルドして
Java
Jar
設定ファイル
…
ビルドスクリプトで頑張る?
サーバーの環境変数で頑張る?
それもなんだかなぁ・・・
- 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. 54Copyright © 2016 NTT DATA Corporation.
環境依存をどう排除するか?
さらにもう一歩進んで…
デプロイ方法は以下のように開発フェーズに応じてやり方を変えるとよい。
ビルド方法 利用
シーン
説明
env.jarをwarファイルに
含めない
運用時 • 環境依存性を排除するためにenv.jarをwarファ
イルに含めない(どの環境でも同じものが利用
できる)
• envモジュールのみ環境ごとにビルドしてデプロ
イする
env.jarをwarファイルに
含める
開発時 • 環境に依存したwarファイルが作成される(テス
ト時に簡単のため利用する)
• 環境ごとにビルドが必要で、別環境では正しく
動作する保証がない
- 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
- 57. 57Copyright © 2016 NTT DATA Corporation.
アプリケーションレイヤをどう切るか?
Spring-mvcはあくまでmvcの切り方は決まる
しかし、ビジネスロジックやDAO等の作り方は決まってない。
業務処理の結果を参照する
Controller
View
リクエスト
レスポンス
データベース
Model
データベース
アクセス
画面遷移する
業務処理を呼び出す
MVCはわかったけど…
結局どこに何を書けばいいんだろう…?
- 58. 58Copyright © 2016 NTT DATA Corporation.
アプリケーションレイヤをどう切るか?
その気になれば1クラスに全部押し込むこともできる。
もちろん、それはNG
複雑度が増す
• テストしにくい or できない
• コピペコードの氾濫
環境依存度が増す
• OS/MWが常に必要
結果、
機能追加も無理です…
デグレ確認するときは常に全量だ…
もうメンテできないよ・・・
- 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. 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. 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. 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
}
- 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. 66Copyright © 2016 NTT DATA Corporation.
SpringのJDBCTemplateではSQLをソースに書いたり、マッピ
ング処理をソースで書くので、大規模開発になると辛い・・・
ということで…
SQL文を書きたいならMyBatisがよいかな
SQL文・発行タイミングを細かくチューニングできる
JPA(というかHibernate)のノウハウがあるなら、
Spring JPA(+ Hibernate)かな
- 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. 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>
- 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. 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. 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の範囲外のため、エラーメッセージが表示
されている
- 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内の画面遷移でセッション
に格納された同一のデータを参照
- 77. 77Copyright © 2016 NTT DATA Corporation.
ここまで紹介してきた開発ノウハウは
TERASOLUNAで公開しています!
しかも今日の内容は
ほんの一部です!
- 78. 78Copyright © 2016 NTT DATA Corporation.
TERASOLUNA Server Framework for Java (5.x) Development Guideline
http://terasolunaorg.github.io/guideline/
- 81. 81Copyright © 2016 NTT DATA Corporation.
他にも役に立つものがいろいろ!
•エンタープライズ向けに必要な汎用的な部品共通ライブラリ
•OSSを利用したエンタープライズ向け
アプリ開発におけるベストプラクティスドキュメントガイドライン
•基本的な開発方法を学ぶ学習教材チュートリアル
•ガイドラインに則って一部の機能を実装したアプリケーションサンプルAP
•プロジェクト構成のひな形ブランクプロジェクト
- 82. Copyright © 2011 NTT DATA Corporation
Copyright © 2016 NTT DATA Corporation.