67
AOPMVC for Beginner 2012/2/20

Spring3.1 aop-mvc

  • View
    1.533

  • Download
    0

Embed Size (px)

DESCRIPTION

JSUG 第2回初心者向け勉強会資料

Citation preview

Page 1: Spring3.1 aop-mvc

AOPとMVC for Beginner

2012/2/20

Page 2: Spring3.1 aop-mvc

問題 • インスタンス変数に宣言したのと同じ型のインスタンスをインジェクションしてもらうためのアノテーションは?

• インスタンス化され、インジェクションされるために、クラス宣言の前に書くアノテーションは?

• 結局、DIコンテナって何のためにあるのか?

2

Page 3: Spring3.1 aop-mvc

前回の続き •  SpringのDIを使って、部品化はできた(気がする)

• でも・・・ ‒ ログなどの共通処理部分が部品に残っている ‒ 例外処理も部品化を壊している

• それに・・・ ‒ トランザクション管理は面倒だし、難しい

3

Page 4: Spring3.1 aop-mvc

AOPの基本 Springの説明の前に・・・

4

Page 5: Spring3.1 aop-mvc

AOPを使ってもっと部品化する •  AOPを使えば処理を後からクラスに追加できる

‒ 例:トレースログを追加する

5

public class DaoImpl extends Dao{ ・・・ public List find() { List list = select(); return list; } }

>java ・・・ 16:00:01 *Start* find() DaoImpl 16:00:02 *End* find() DaoImpl 17:02:12 *Start* find() DaoImpl 17:02:13 *End* find() DaoImpl

DaoImpl

find() ServiceImpl

find()を呼ぶ

Dao

実行結果

Page 6: Spring3.1 aop-mvc

AOPをもう少し正しく

6

Aspect

ソースコード

Pointcut

Pointcut

Advice

Advice

Joinpoint

Adviceを追加できるときがJoinpointとなる Joinpointを条件で絞り込む

フィルター

追加したい処理

Page 7: Spring3.1 aop-mvc

Joinpoint •  Adviceを追加できるとき(ポイント) •  AOPの仕様であり、実装者は変更できない •  Joinpointの仕様例

‒ メソッドの開始時、終了時 ‒ プロパティが利用されたとき

7

DaoImpl

add() delete() find() update() Joinpoint

例:メソッドの開始時や終了時

Page 8: Spring3.1 aop-mvc

Pointcut •  Joinpointに達した命令を、Adviceまで到達させるか否かフィルタリングするフィルター

8

DaoImpl

add() delete() find() update()

Joinpoint

Pointcut

Advice

追加したい処理

Joinpointを条件「add*」で絞り込む

ServiceImpl

Dao

Page 9: Spring3.1 aop-mvc

Befor Advice •  Joinpointの前で実行される

9

Client Servant

method()

return

Before Advice

Exception

メソッドの実行前に割り込む

Page 10: Spring3.1 aop-mvc

After Advice •  Joinpointの後で実行される

10

Client Servant

method()

return

Exception

メソッドの実行後に割り込む

After Advice

Page 11: Spring3.1 aop-mvc

After Returning Advice •  Joinpointが正常終了した後に実行される

11

Client Servant

method()

return

Exception

After Returning Advice

メソッドの実行後に正常終了時に割り込む

Page 12: Spring3.1 aop-mvc

Around Advice •  Joinpointの前後で実行される

12

Client Servant

method() return

Exception

Around Advice

method()

メソッドの実行前と実行後、例外発生時にも割り込む

Page 13: Spring3.1 aop-mvc

Throw Advice •  Joinpointで例外が発生した時に実行される

13

Client Servant

method()

return

Exception Throw Advice

例外発生時に割り込む

Page 14: Spring3.1 aop-mvc

問題 • メソッドの開始と終了のログをとりたかったら?

• メソッドが正常終了したログをとりたかったら?

• メソッドが異常終了したときのログをとりたかったら?

14

Page 15: Spring3.1 aop-mvc

AOPの仕組み例 •  Proxyベースの場合、ProxyオブジェクトはSpringが自動生成する

1-15

:Proxy

:Bean

Interface :Client

Bean定義 ファイル

Adviceの呼び出し

自動生成

:Advice

:Spring

Pointcutの参照

処理の 依頼

処理の依頼

Page 16: Spring3.1 aop-mvc

AOPの主な利用方法 •  各クラスに記述されている同一の処理を抜き出し、ひとまとめにして、既存のクラスに後から追加する ‒  ライブラリとの違い

•  ライブラリは呼び出さないといけない •  AOPは勝手に追加される

•  追加すると便利な処理 ‒  トランザクション管理

•  トランザクション管理は難しいくプログラマに任せられない ‒  ログ管理

•  メソッドの開始と終了のトレースログが正しく出力されない ‒  誰もフォーマットを守らない ‒  トレースログを追加し忘れる

‒  例外管理 •  処理の途中でExceptionが握りつぶされてしまう

‒  Exceptionを実行時例外にする

16

Page 17: Spring3.1 aop-mvc

AOPでやらない方が良いこと • 個別の処理(特定業務の処理、デバッグ) ‒ プログラマが個別にAOPをいれるのは不可

• そこで何をやっているのかが分からなくなる

• 業務アプリのプログラマではなく、基盤チームとかが使う技術!?

17

Page 18: Spring3.1 aop-mvc

SpringのAOP • 定義ファイルの利用

‒ Spring1.x系では基本 • アノテーションの利用

‒ Spring2.x系以降、アノテーションの利用が増えている(大規模開発や大手SI便だでは定義ファイルの利用が多い)

18

Page 19: Spring3.1 aop-mvc

問題 書いてないけど? • 例えば

‒ アノテーション • メリット:定義ファイルの管理が不要 • デメリット:プログラマにアノテーションを意識

‒ とか、定義ファイルのメリットとかデメリット

19

Page 20: Spring3.1 aop-mvc

AOP アノテーションを使った

20

Page 21: Spring3.1 aop-mvc

アスペクトの例 • アノテーションの利用

21

@Aspect public class AspectMessage {

@After("execution(* exMethod())") public void hoge() { // メソッド終了後に動くAdvice System.out.println("after called"); } }

Page 22: Spring3.1 aop-mvc

アノテーション一覧

アノテーション 説明 @Aspect Adviceとなるクラスを指定するアノテーション @Around Around Adviceとなるメソッドを指定するアノテーション @Before Before Adviceとなるメソッドを指定するアノテーション @After After Adviceとなるメソッドを指定するアノテーション @AfterReturning After Returning Adviceとなるメソッドを指定するアノテーション @AfterThrowing After Throwing Adviceとなるメソッドを指定するアノテーション

22

• アノテーションを利用したAOP ‒ Bean定義ファイルの記述が簡潔になる ‒ ソースコードに記述することで管理が煩雑

Page 23: Spring3.1 aop-mvc

アドバイス詳細(1) •  Before, After

‒  @After(“Primitiveポイントカット”) •  メソッド名は任意、メソッドのパラメータと戻り値はなしでも可能。メソッド内で、アスペクト対象となっているメソッド名やパラメータ,戻り値などの取得をする場合は、パラメータにJoinPoint

•  メソッド内で、アスペクト対象となっているメソッドを呼び出す必要はない

23

@Before(“execution(* exMethod())”) public void hoge() { ・・・ }

Page 24: Spring3.1 aop-mvc

アドバイス詳細(2) • Around

‒ @Around(“Primitiveポイントカット”) • メソッド名は任意、メソッドのパラメータには必ずProceedingJoinPointが必要、戻り値はアスペクト対象のメソッドにあわせる

• メソッド内で、アスペクト対象となっているメソッドを呼び出す必要がある ‒  ProceedingJoinPoint#proceed()メソッド

»  Object proceed() throws Trowable • メソッド内で、アスペクト対象となっているメソッド名やメソッドのパラメータの取得はProceedingJoinPointを介しておこなう

24

Page 25: Spring3.1 aop-mvc

アドバイス詳細(3) •  Around

‒  戻り値はアスペクト対象にあわせる

25

public String getMessage() { return “hello!”; }

@Around(“execution(* getMessage())”) public String fuga(ProceedingJoinPoint pjp) throws Throwable {; String msg = (String)pjp.proceed(); return msg; }

アスペクト対象のメソッド

Page 26: Spring3.1 aop-mvc

アドバイス詳細(4)

26

public int getFigure() { return 100; }

@Around(“execution(* getFigure())”) public int fuga(ProceedingJoinPoint pjp) throws Throwable {; Integer figure= (Integer)pjp.proceed(); return figure.intValue(); }

アスペクト対象のメソッド

Page 27: Spring3.1 aop-mvc

アドバイス詳細(5) •  Around

‒  ProceedingJoinPointの使い方

27

Signature sig = pjp.getSignature(); System.out.println("Sig: " + sig.getName());

メソッド名の取得

Object[] os = pjp.getArgs(); System.out.println("Args: " + os[0]);

パラメータの取得(最初のパラメータ)

Page 28: Spring3.1 aop-mvc

問題~重複してたらどうなる?

28

@Around(“execution(* add())”) public int hoge (ProceedingJoinPoint pjp) throws Throwable {; Integer figure= (Integer)pjp.proceed(); return figure.intValue(); }

private int x; public int add(int i) { x = x + i; return x; }

アスペクト対象のメソッド

これと同じhogehogeメソッド が存在したら?

Page 29: Spring3.1 aop-mvc

アドバイス詳細(6) • AfterReturning

‒ @AfterReturning(value=“Primitiveポイントカット”, returnig = “戻り値の変数名”) • メソッド名は任意、メソッドのパラメータはアスペクト対象となっているメソッドの戻り型とアノテーションのretuning属性で指定した変数名

• メソッド内で、アスペクト対象となっているメソッドを呼び出す必要はない

29

Page 30: Spring3.1 aop-mvc

アドバイス詳細(7)

30

@AfterReturning(value=“execution(* exMethod())”, returning=“ret”) public String hoge(String ret) { System.out.println(“Return: “ + ret); }

public String exMethod() { return “hello!”; }

アスペクト対象のメソッド

Page 31: Spring3.1 aop-mvc

アドバイス詳細(8) • AfterThrowing

‒ @AfterReturning(value=“Primitiveポイントカット”, throwing = “例外の変数名”) • メソッド名は任意、メソッドのパラメータはアスペクト対象となっているメソッドの戻り型とアノテーションのthrowing属性で指定した変数名

• メソッド内で、アスペクト対象となっているメソッドを呼び出す必要がない

31

Page 32: Spring3.1 aop-mvc

アドバイス詳細(9)

32

@AfterThrowing(value=“execution(* exMethod())”,                               throwing=“ex”) public String foo(HogeException ex) { System.out.println(“Exception Msg: “ + ex.getMessage()); }

Page 33: Spring3.1 aop-mvc

アドバイス詳細(10) •  AfterThrowing

33

@AfterThrowing(value=“execution(* exMethod())”, throwing=“ex”) public String foo(Throwable ex) { System.out.println(“Exception Msg: “ + ex.getMessage()); }

@AfterThrowing(value=“execution(* exMethod()”, throwing=“ex”) public String var(HogeException ex) { System.out.println(“Exception Msg: “ + ex.getMessage()); } @AfterThrowing(value=“execution(* exMethod()”, throwing=“ex”) public String hoge(Exception ex) { System.out.println(“Exception Msg: “ + ex.getMessage()); }

Page 34: Spring3.1 aop-mvc

問題~どのアドバイス? • 前ページの実装があったとき、どこかのプログラムがExceptionを投げてよこしました

• どのアドバイスが動くでしょう?

34

Page 35: Spring3.1 aop-mvc

Primitiveポイントカット Primitive ポイントカット 概要 execution 呼出先の「メソッド」、「コンストラクタ」を指定する。 within 呼出元の「クラス」を指定する。

withinをPointcutに指定すると、指定されたクラスから呼出される、メソッド等が選択されることになる。対象は、指定されたクラスで宣言されたメソッドに限定され、指定されたクラスの親クラスで宣言されたメソッド内は対象外となる。

this 呼出元の「クラス」を指定する。thisをPointcutに指定すると、指定されたクラスから呼出される、メソッド等が選択されることになる。withinとは、親クラスで定義されたメソッドの呼出しも対象とする点が異なる。

target 呼出先の「クラス」を指定する。ただし、呼出先のstaticフィールドは対象外となる。

args 呼出先「メソッド」の引数の型を指定する。

35

※Primitiveポイントカット:あらかじめ用意されているポイントカットのこと

Page 36: Spring3.1 aop-mvc

executionの基本構文 •  execution(メソッドの修飾子△メソッドの戻り値型△パッケージ.クラスまたはインタフェース.メソッド名(仮引数の型|,仮引数の型…|) △throws 例外)

•  「メソッドの修飾子(publicやprivateは省略可能)」や「throws△例外」は省略することが可能

•  メソッドの戻り値型、パッケージやクラス名、インタフェース名にはワイルドカード(*)の利用が可能

•  仮引数に(..)を記述すると任意の個数の引数と一致させることが可能

36

Page 37: Spring3.1 aop-mvc

ポイントカットで利用できる論理演算子

37

論理 演算子

説明

¦¦ または or

論理和を意味する論理演算子

例) execution(* *..AopExBean.exMethod()) or execution(* *..AopExBeanParent.exMethod())  →AopExBeanのメソッドexMethodまたはAopExBeanParentのメソッドexMethodを指定

&& または and

論理積を意味する論理演算子

例) execution(* *..AopExBean.exMethod()) && execution(* *..AopExBeanParent.exMethod())  →AopExBeanのメソッドexMethodまたはAopExBeanParentのメソッドexMethodを指定

! または not

否定を意味する論理演算子。

例) execution(* exMethod()) and not execution(* *..AopExBeanParent.*())  →AopExBeanParent以外のクラス(インタフェース)のメソッドexMethodを指定

Page 38: Spring3.1 aop-mvc

コーディング例(1)

38

@Aspect public class AspectMessage {

@After("execution(* exMethod())") public void after() { // メソッド終了後に動作するAdvice System.out.println("after called"); }

@Before("execution(* exMethod())") public void before() { // メソッド開始時に動作するAdvice System.out.println("before called"); }

Page 39: Spring3.1 aop-mvc

コーディング例(2)

39

@Around("execution(* exMethod())") public void around(ProceedingJoinPoint pjp) throws Throwable { // メソッド呼出の前後に動作するAdvice System.out.println("pre proceed"); pjp.proceed(); System.out.println("post proceed"); }

Page 40: Spring3.1 aop-mvc

コーディング例(3)

40

@AfterReturning(value="execution(* exMethod())", returning="ret") public void afterReturning(String ret) { // メソッド呼出が例外の送出なしに終了した際に動作するAdvice System.out.println("after returning called"); System.out.println("return value = " + ret); }

@AfterThrowing(value="execution(* exMethod())", throwing="ex") public void afterThrowing(Throwable ex) { // メソッド呼出が例外の送出なしに終了した際に動作するAdvice System.out.println("after throwing called"); System.out.println("exception value = " + ex.toString()); } }

Page 41: Spring3.1 aop-mvc

定義ファイル

41

<?xml version="1.0" encoding="UTF-8"?> <beans xmlns=http://www.springframework.org/schema/beans xmlns:xsi=http://www.w3.org/2001/XMLSchema-instance xmlns:context=http://www.springframework.org/schema/context xmlns:aop=http://www.springframework.org/schema/aop xsi:schemaLocation=” http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd"> … <aop:aspectj-autoproxy/> … </beans>

Page 42: Spring3.1 aop-mvc

AOP 定義ファイルには書かないでしょ!?

42

Page 43: Spring3.1 aop-mvc

それでも書きたい定義ファイル(1)

43

・・・ <aop:config> <aop:aspect id="myAspect" ref="aspectMessage"> <aop:pointcut id="fuga" expression="execution(* getMessage())"/> <aop:before pointcut-ref="fuga" method="foo"/> <aop:after pointcut-ref="fuga" method="var"/> <aop:around pointcut-ref="fuga" method="hoge"/> </aop:aspect>

</aop:config>

Page 44: Spring3.1 aop-mvc

それでも書きたい定義ファイル(2)

44

<aop:config> <aop:aspect id="myAspect2" ref="aspectMessage2"> <aop:pointcut id="fuga2" expression="execution(* getMessage())"/> <aop:after pointcut-ref="fuga2" method="hoge"/> </aop:aspect>

</aop:config> ・・・ <bean id="aspectMessage" class="sample.aop.AspectMsg" /> <bean id="aspectMessage2" class="sample.aop.AspectMsg2" /> ・・・

Page 45: Spring3.1 aop-mvc

コーディング例

45

public class AspectMessage {

public void after() { // メソッド終了後に動作するAdvice System.out.println("after called"); }

public void before() { // メソッド開始時に動作するAdvice System.out.println("before called"); }

・・・以下省略

Page 46: Spring3.1 aop-mvc

問題 消すことできる?

46

<aop:config> <aop:aspect id="myAspect2" ref="aspectMessage2"> <aop:pointcut id="fuga2" expression="execution(* getMessage())"/> <aop:after pointcut-ref="fuga2" method="hoge"/> </aop:aspect>

</aop:config> ・・・ <bean id="aspectMessage2" class="sample.aop.AspectMsg2" /> <bean id="aspectMessage2" class="sample.aop.AspectMsg" /> ・・・

beanを定義している2行

Page 47: Spring3.1 aop-mvc

DIとAOPのまとめ アーキテクチャ・リファクタリング

今までの知識を使ってWebアプリケーションを改善する

47

Page 48: Spring3.1 aop-mvc

アーキテクチャ・リファクタリング(1/5)

•  表示と永続化のフレームワーク導入済 •  インタフェース未使用(もちろんDI,AOPも)

‒ チーム開発がしずらい ‒ 変更、機能拡張、テストが容易ではない

•  連続性も阻害 ‒  Conecctionの引き回し、検査時例外の伝搬

48

FindAction Employee Service

Employee MySql Dao

RDB

ブラウザ

Page 49: Spring3.1 aop-mvc

アーキテクチャ・リファクタリング(2/5)

•  メリット ‒  インタフェースを区切りとして、チーム開発がやりやすくなった ‒  変更、機能拡張、テストが容易になった

•  デメリット ‒  Factoryを実装する必要がある ‒  クラスはFactoryに依存する

49

FindAction <<Singleton>>

Employee ServiceImpl

<<Singleton>> Employee DaoMySql

MySQL

ブラウザ RDB

Employee Dao

Employee Service

Factory

生成 生成 利用 利用

インタフェースの導入

Page 50: Spring3.1 aop-mvc

アーキテクチャ・リファクタリング(3/5)

•  Factoryを実装する必要がない •  クラスはDIコンテナに依存しない

50

FindAction Employee ServiceImpl

Employee DaoMySql MySQL

ブラウザ RDB

Employee Dao

Employee Service

DIコンテナ

生成 生成

Injection Injection

DIの導入

Page 51: Spring3.1 aop-mvc

アーキテクチャ・リファクタリング(4/5)

•  トランザクション管理やログ出力、例外処理が残っている ‒  分岐が多いため、テストの量が多くなる ‒  共通化できる部分が隠蔽できていない ‒  例外処理とConnectionの引き渡しによる連続性の阻害がある

51

public class EmployeeServiceImpl" implements EmployeeService{" @Autowired! private EmployeeDao dao;" ・・・  public List findAll() throws Exception {! if(Log.flag) { System.out.println(“***Start”); }! Connection conn = null;" ・・・ //EmployeeDao dao ! // = (EmployeeDao)Factory.create(KEY);! List employeeList = null;" try {" employeeList = dao.findAll(conn);" conn.commit();!

} catch(Exception e) {! conn.rollback();! ・・・ } finally {! conn.close();! ・・・ }! if(Log.flag) { System.out.println(“***End”); }" return employeeList;" }"・・・

Employee ServiceImpl

DIコンテナ導入後のソースコード

Page 52: Spring3.1 aop-mvc

アーキテクチャ・リファクタリング(5/5)

•  共通ライブラリを廃止してAOPを導入 •  連続性の確保

‒  トランザクション管理、ログ出力、例外処理はAOPで実現しているため、ソースコード上からはなくなっている

‒  Advice実装されており、なくなっている訳ではない •  ソースコードの記述量が減り、バグの数も低下、開発者の作業も軽減 •  テストの容易性も向上

52

public class EmployeeServiceImpl ! implements EmploeeService {! @Autowired! private EmployeeDao dao;!

  public List findAll() {! return dao.findAll();! }!・・・

書くことがなくなりました・・・!

AOP導入後のソースコード

Page 53: Spring3.1 aop-mvc

アーキテクチャ・リファクタリングの嘘 •  AOPで業務例外(例えば、在庫がなかった時にどうする)は処理できないから、そんなに奇麗に例外は消えない(多分…)

•  だって、AOPを使う基盤チームは業務を知らない(多分…)。だから、業務例外はAOPで提供できない

•  それに業務例外がAOPになったら、業務プログラムが読めない!

•  そもそも、業務例外にExceptionを使うのってどうよ(!?)という問題でもある

53

Page 54: Spring3.1 aop-mvc

Spring MVC かる~く

54

Page 55: Spring3.1 aop-mvc

Spring MVCとは •  Spring Frameworkに含まれるWeb MVCフレームワーク ‒ 初期のSpring Frameworkの段階から含まれている

‒ StrutsやJSFと競合 • 特徴

‒ DIコンテナとの親和性 ‒ きれいな設計

• インタフェースを使用して部品化

55

Page 56: Spring3.1 aop-mvc

Spring MVCのController

56

XxxController Employee ServiceImpl

Employee DaoMySql MySQL

ブラウザ RDB

Employee Dao

Employee Service

DIコンテナ

生成 生成

Injection Injection

DIの導入

生成

Page 57: Spring3.1 aop-mvc

難しいと評判(?)のSpring MVC •  Spring1.xのSpring MVC

‒ 設定が難しい ‒ 作り方がよくわからない ‒ 日本語の情報が少ない ‒ そもそも知らない

57

Page 58: Spring3.1 aop-mvc

簡単になったSpring MVC •  Spring 3.xのSpring MVC

‒ Springの新機能を導入 • アノテーションにより設定がシンプルになり、わかりやすくなった

• component-scanにより設定ファイルが最低限ですむようになった

‒ あいかわらず日本語の情報は少ない • 英語のマニュアルを読みましょう

58

Page 59: Spring3.1 aop-mvc

デモ •  STS(SpringSource Tool Suite)で作成

1.  メニューからNew->Project 2.  SpringSource Tool Suite->Spring

Template Projectを選択 3.  Spring MVC Projectを選択

59

Page 60: Spring3.1 aop-mvc

動作概要

60

<<jsp>> /WEB-INF/views/home.jsp

<<controller>> HomeController

home()

ブラウザ Dispatcher

Servlet (ほか色々)

Model

Date (現在の日時)

"serverTime"

Page 61: Spring3.1 aop-mvc

HomeController

61

@Controller public class HomeController {

@RequestMapping(value = "/", method = GET) public String home(Model model) { Date date = new Date();

model.addAttribute("serverTime", date);

return "home"; } }

DIコンテナにより 自動で読み込まれる (component-scan)

HTTPメソッドがGETで 「/」へアクセスした際に 実行される

Viewに渡したいオブジェクトを 設定する

View名をreturnする

※少し手を加えシンプルにしています

Page 62: Spring3.1 aop-mvc

home.jsp

62

<html> <head> <title>Home</title> </head> <body> <h1>Hello world! </h1> <p>The time on the server is ${serverTime}.</p> </body> </html>

Modelに設定したオブジェクトは 自動的にHttpServletRequestに 設定されている

※少し手を加えシンプルにしています

Page 63: Spring3.1 aop-mvc

@RequestMapping色々

63

// 一つのメソッドに複数のURLを割り当て @RequestMapping({"/", "/home"}) public String home() { ・・・

// 一つのURLでHTTPメソッドごとにメソッドを切り分け @RequestMapping(value="/foo", method=GET) public String doGetMethod() { ・・・

@RequestMapping(value="/foo", method=POST) public String doPostMethod() { ・・・

Page 64: Spring3.1 aop-mvc

引数色々①

64

// リクエストパラメータを取得(「/person?id=10」などでアクセス) @RequestMapping(value = "/person", method=GET) public String showPerson1 ( @RequestParam("id") int id, Model model) { Person person = findById(id); model.addAttribute("person", person); ・・・

// URLの値を取得(「/person/10」などでアクセス) @RequestMapping(value = "/person/{id}", method=GET) public String showPerson2( @PathVariable("id") int id, Model model) { Person person = findById(id); model.addAttribute("person", person); ・・・

Page 65: Spring3.1 aop-mvc

引数色々②

65

// 画面からの入力をマッピング(formからデータを送信) @RequestMapping(value = "/person", method = POST) public String registerPerson(@ModelAttribute Person person) { register(person); ・・・

// ほかにも色々 @RequestMapping("/foo") public String foo( Model model, WebRequest req, WebResponse res, Cookie cookie, Locale locale, HttpServletRequest sreq, HttpServletResponse sres) { ・・・

Page 66: Spring3.1 aop-mvc

その他の機能 •  Session管理

‒  @SessionAttributes(model名)をクラスに設定すると、Modelに追加したオブジェクトはHttpSessionに追加される

‒  @ModelAttribute(model名)を引数に設定すると、Sessionのオブジェクトが引数に渡される

‒  SessionStatus#setComplete()でHttpSession内のオブジェクトが破棄される •  ControllerごとにSession内のオブジェクトを管理可能

•  入力チェック(Validation) ‒  JSR-303(Bean Validation)に対応

•  @NotNull String id; •  @Length(max = 30) String name;

‒  Validation対象の引数に@Validを設定する •  例外処理

‒  例外発生時に実行するメソッドに@ExceptionHandler(FooException.class)

66

Page 67: Spring3.1 aop-mvc

BON VOYAGE!

67