struts2 tutorial

74
STRUTS2 で 楽々WEBアプリケーション開発 いまい けいご http://d.hatena.ne.jp/keigoi/ 1 2008年7月25日

Upload: nhoc-ngo

Post on 02-Dec-2014

614 views

Category:

Documents


15 download

TRANSCRIPT

STRUTS2 で 楽々WEBアプリケーション開発

いまい けいごhttp://d.hatena.ne.jp/keigoi/

1

2008年7月25日

対象者 / 必要なものeclipse で Javaのコードを書いたことがある人向け

必要なもの

eclipse の Tomcat プラグイン(http://www.eclipsetotale.com/tomcatPlugin.html)

Tomcat (http://struts.apache.org/2.x/)

struts2 をダウンロードしておいてください(http://struts.apache.org/2.x/)

2

公開してます

http://www.agusa.i.is.nagoya-u.ac.jp/person/sydney/20080725/

このスライド (struts2-tutorial.pdf)

サンプルコード (grape_sample.zip)

3

Struts2(*) とは

Java J2EE上のWebアプリフレームワーク Strutsの後継

ただし原型は殆どない

OpenSymphony WebWork2 の拡張版

(*) http://struts.apache.org/2.x/4

その前に!

Struts2 は サーブレット/JSP をベースにしていて一部サーブレットの機能を使っている

まずは サーブレット/JSPについて 概観します

5

アーキテクチャ

J2EE Webサーバ(サーブレットコンテナ)

サーブレット / JSP

Struts2

ビジネスロジックを実現する機能

入力値の整理,バリデーション,JSPのための便利なタグなど

基本的な機能MVC (ServletとJSPの連携),セッション,認証などの実現

HTTPリクエスト・レスポンスをWebブラウザとServlet/JSP間でやりとりデータソース(DBとのTCP接続)の管理

6

TOMCATのインストールとECLIPSE -

TOMCATプラグインの設定

7

Apache Tomcat(*) : サーブレットコンテナ

バージョンは?

5.x 系で良いと思う

インストールは?

適当なフォルダに zipを展開。これだけ。

(*) http://tomcat.apache.org/

J2EE Webサーバ(サーブレットコンテナ)

サーブレット / JSP

Struts2

8

Tomcatプラグイン

eclipseに Tomcatプラグイン(*)をインストール

Tomcatプラグインの設定

Tomcatの起動、webアプリのテスト用配備など

(*) http://www.eclipsetotale.com/tomcatPlugin.html9

Tomcat Pluginの設定

10

サーブレット/JSPによるWEBアプリケーション

11

J2EE サーブレット/JSP

JavaでWebアプリケーションを書くための基本的技術

Webコンテナ (Apache Tomcat 等)上で動作する

J2EE Webサーバ(サーブレットコンテナ)

サーブレット / JSP

Struts2

12

Tomcatプロジェクトの作成

名前を grape_sample にしました。

まずは、以下のフォルダ構成になるはず

13

Java サーブレット拡張Referenced Libraries で Tomcatのjarを参照しているのに注目これが Servletのjarファイルです配備時はTomcatのクラスローダが事前にロード

14

サーブレットを書こう: srcとclaessesTomcatプロジェクトの作成直後の状態では…eclipse で WEB-INF/src 以下にソースを置くとWEB-INF/classes に .classファイルが配置されます以後、src と classes フォルダを同一視します

package explorerではclassesフォルダは不可視です

eclipseにより自動コンパイル後WEB-INF/classesに配置 される

15

サーブレットを書いてみよう文字列 Hello, World ! を出力する コード

package controller;

<import...>

public class MyServlet1 extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { resp.getWriter().println("Hello, World !"); }

}

WEB-INF/src/controller/MyServlet1.java

16

サーブレットのきまりHttpServlet クラスを extend して、doGetメソッドをオーバーライドする引数 HttpServletRequest, HttpServletResponsereq は HTTPのリクエストパラメータを得る為に,res は HTTPのレスポンスを返す為に使う

public class MyServlet1 extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { resp.getWriter().println("Hello, World !"); }}

WEB-INF/src/controller/MyServlet1.java

17

web.xmlの設置web.xml で URL にサーブレットを 対応付けます

その他 認証等の設定もココに書く

18

web.xml

<web-app> <servlet> <servlet-name>my_servlet1</servlet-name> <servlet-class>controller.MyServlet1</servlet-class> </servlet> <servlet-mapping> <servlet-name>my_servlet1</servlet-name> <url-pattern>/myServlet1</url-pattern> </servlet-mapping></web-app>

最低限の設定URL /myServlet1 を クラス controller.MyServlet1 にマッピング

WEB-INF/web.xml

19

さあ実行しよう :Webアプリの配備

プロジェクトを右クリック -> Tomcat project -> Update context definition<CATALINA_HOME>/conf/Catalina/localhost/ に、 eclipseのプロジェクトフォルダをコンテキストルートとして配備する設定が書き込まれる。

20

Tomcat の起動

左から 起動、停止、再起動

二重起動すると 8080 が already in use だと怒られるので注意

21

アクセスしてみようweb.xml に書いた <url-pattern> に対応するURLにアクセスしてみよう

http://localhost:8080/grape_sample/myServlet1

:: <servlet-mapping> <servlet-name>my_servlet1</servlet-name> <url-pattern>/myServlet1</url-pattern> </servlet-mapping>:

web.xml (再掲)

ブラウザ

22

そのほか<cxt-root> 以下に置いたファイルは静的コンテンツとして扱えます (URLから直接参照できる)

例外:WEB-INF 以下は不可視 (セキュリティ上)

.jsp という拡張子をもつファイルは JSP (Java Server Pages) で、スクリプトレットが記述できる

JSPはstruts2でも使います。後述。

23

JSP (Java Server Pages)HTMLの文の中に、Javaのコードを埋め込めるスクリプトレット という機能

<% someStatement; %>, <%= “文字列” %>

<% while(...) { %> <tr>...</tr> <% } %> みたいな

タグ拡張

jspタグ e.g. <jsp:include page=””/>

タグは追加できる。タグライブラリも豊富にある(strutsのタグライブラリ、JSTLなど)

24

STRUTS2 - 準備編

25

Struts2 と サーブレットの関係

サーブレット … 何でもできるが、使い勝手がわるい

入力値の扱いが面倒 e.g. Integer.parseInt(req.getParameter(“param1”))

バリデーション機能がない

サーブレットの上に新しいフレームワークを作った

一部、サーブレットの機能を使う

JSPのタグライブラリを含むJ2EE Webサーバ

(サーブレットコンテナ)

サーブレット / JSP

Struts2

26

Struts2 : 準備

WEB-INF/lib/*.jar

struts-blank から

struts2-codebehind

設定

WEB-INF/web.xml

WEB-INF/classes/struts.xml

この状態にしよう

27

jarstruts-blankのWEB-INF/lib のものをコピー

あと struts2-codebehind-plugin-*.jar も

コピーしただけでは参照できないぞ!eclipseの設定でクラスパスに追加するのを忘れずに

commons-logging-1.0.4.jar struts2-core-2.0.11.2.jar freemarker-2.3.8.jar xwork-2.0.5.jar ognl-2.6.11.jar struts2-codebehind-plugin-2.0.11.2.jar

WEB-INF/lib

28

web.xml の設定Servlet/JSPフレームワークの <フィルタ> として設定全リクエストはまず struts2に処理される (url-pattern が /* )

<web-app> <filter> <filter-name>struts2</filter-name> <filter-class>org.apache.struts2.dispatcher.FilterDispatcher</filter-class> <init-param> <param-name>actionPackages</param-name> <param-value>actions</param-value> </init-param> </filter> <filter-mapping> <filter-name>struts2</filter-name> <url-pattern>/*</url-pattern> </filter-mapping></web-app>

WEB-INF/web.xml

Zero Configuration固有の設定。

後でこの actionsというパッケージを作ります

29

struts.xml の設定クラスパスのルート、すなわち WEB-INF/classes に配置 ( → WEB-INF/srcに置けばよい)

Zero Configuration のおかげで ほぼ空っぽ

<struts> <constant name="struts.enable.DynamicMethodInvocation" value="false" /> <constant name="struts.devMode" value="true" /></struts>

WEB-INF/classes/struts.xml

30

(*) Zero Configuration+codebehindで省力化

struts2 の Zero Configuration + codebehindプラグインで、徹底的に省力化しよう!

Zero Configuration が無い場合=> struts.xml に <action> タグが必要

codebehind が無い場合1. <action>タグを書くか、2. アクションクラスに @Result を加える

31

STRUTS2 - 超基本編

32

MVCアーキテクチャModel (データやビジネスロジック), View (表示系), Controller (その間) をきちんと分けて書きましょうねという考え方

Struts では、アクションが Controller Model, JSP が View にあたる (インタセプタ等がController)

Ian Roughleyの本を参照のこと

コンポーネント間の依存関係をスッキリさせる

実のところ私はよくわかってないかも wikipediaより33

??データ

PDFデータ

struts2 Webアプリのフロー

GETやPOSTでアクションが呼ばれる。アクションはビジネスロジックを実行する。

アクションはリザルトの名前を返す。リザルトの名前に従ってJSP等が返される。

JSP Action

JSP

GET または POST

フォーム

データ

TestAction(test.action)

test-input.jsp

test-success.jsp

“fail”

...

success

fail

...

リザルト...

...

34

??データ

PDFデータ

struts2 と MVC

アクションはMVCにおけるコントローラ(C) モデル(M) 。

JSPはMVCにおけるビュー(V)。

JSP Action

JSP

GET または POST

フォーム

データ

TestAction(test.action)

test-input.jsp

test-success.jsp

“fail”

...

success

fail

...

リザルト...

...

35

Model : アクションの作成

struts2 の init-param で指定したパッケージ ”actions” にアクションを配置~~ Action という名前にする。Zero Configurationの規約。TestAction という名前にしてみた

: <init-param> <param-name>actionPackages</param-name> <param-value>actions</param-value> </init-param> :

WEB-INF/web.xml (抜粋)パッケージ

36

アクションクラスの書き方何もextends/implementsしなくていい (ActionSupportクラスをextendsすると便利...?)public な executeメソッドだけ準備する戻り値”success”は リザルトの名前.転送先ページを指定する(後述)

package actions;

public class TestAction { public String execute() { /* ビジネスロジックをココに書く */ return "success"; }}

TestAction.java

超スッキリ!37

View : JSP の作成

<アクション名>-<リザルトの名前>.jsp というファイル名で、JSPを配置する. codebehindの規約。

ここでは test-success.jsp という名前になる

public class TestAction { public String execute() { return "success"; }}

Hello, this is JSP!!

TestAction.java

test-success.jsp

38

アクセスしてみよう

39

STRUTS2 - ACTION-JSP連携 (1)

ACTIONからJSPへ

(Struts1のタグライブラリの事は忘れましょう…)

40

MVC Webアプリのフロー

制御の流れはそのままデータの流れでもある

フォームに入力したデータが、GETでActionに渡され、 Actionの結果は転送先のJSPで表示される

JSP

Action

JSP

GET または POST

フォーム データ

TestAction(test.action)

input.jsp test-success.jsp

return “success”;

41

MVC Webアプリのフロー

この部分の流れを考えてみよう

JSP

Action

JSP

GET または POST

フォーム データ

TestAction(test.action)

input.jsp test-success.jsp

return “success”;

42

Actionからデータを受け取るJSP カスタムタグ

Struts用カスタムタグを使いましょう

JSPの頭にカスタムタグの宣言を置こう

タグの接頭辞には s: が付きますよという意味

タグ定義はstruts2のjarに入ってる /struts-tags

<%@ taglib prefix="s" uri="/struts-tags" %>

43

s:propertyタグ

<s:property name=”foobar” />

Actionの getFoobar() メソッドの戻り値が出力される

<s:property value=”foobar” />

44

s:propertyタグ を使う

public class GetTodayAction { public String execute() { return "success"; } public String getToday() { // 今日は何日? return new SimpleDateFormat("yyyy/MM/dd") .format(new Date()); }}

<%@ taglib prefix="s" uri="/struts-tags" %>今日は <s:property value=”today” /> です。

GetTodayAction.java

getToday-success.jsp

45

実行してみると

<%@ taglib prefix="s" uri="/struts-tags" %>今日は <s:property value=”today” /> です。

getToday-success.jsp

46

Struts2のタグライブラリ(*)

Genericタグ

制御構造タグ if-else(elseif), iterator他

Dataタグ

property タグ他

色々使ってみてください。

(*) http://struts.apache.org/2.x/docs/tag-developers-guide.html47

STRUTS2 - ACTION-JSP連携 (2)リクエストパラメータを受け取ろう

48

MVC Webアプリのフロー

この部分の流れを考えてみよう

フォームでPOST / リクエストパラメータでGET

まずは リクエストパラメータを受け取ってみる

JSP

Action

JSP

GET または POST

フォーム データ

TestAction(test.action)

input.jsp test-success.jsp

return “success”;

49

getterも必要

setter でリクエストパラメータを受け取る

public class Test3Action { // 計算機 int x, y, sum, diff, mult, div; public String execute() { sum = x+y; diff = x-y; mult = x*y; div = x/y; return "success"; } public void setX(int x) { this.x = x; } public void setY(int y) { this.y = y; }

public int getX() { return x; } public int getY() { return y; } :

リクエストパラメータを受け取るsetter

CalcAction.java

http://.../calc.action?x=100&y=33

50

あとはさっきと同じ<s:property .../>

<%@ taglib prefix="s" uri="/struts-tags" %>x + y = <s:property value="sum"/><br/>x - y = <s:property value="diff"/><br/>x * y = <s:property value="mult"/><br/>x / y = <s:property value="div"/><br/>

calc-success.jsp

public class CalcAction { // 計算機 : public int getSum() { return sum; } public int getDiff() { return diff; } public int getMult() { return mult; } public int getDiv() { return div; }}

CalcAction.java

51

実行結果

<%@ taglib prefix="s" uri="/struts-tags" %>x + y = <s:property value="sum"/><br/>x - y = <s:property value="diff"/><br/>x * y = <s:property value="mult"/><br/>x / y = <s:property value="div"/><br/>

calc-success.jsp

52

STRUTS2 - ACTION-JSP連携 (3)フォームとバリデーション, UIタグとテーマ

53

Struts2 UI タグとバリデーション

フォーム入力のバリデーション(妥当性検査)次第で入力ページに転送されることもある

この時、以前に入力した値が消えていたら困る…

Struts2の UI タグを使おう(*) http://struts.apache.org/2.x/docs/ui-tags.html

Action

GET または POST

JSPフォーム

TestAction(test.action)test-input.jsp

バリデーション失敗(リザルト “input”)

“success”

54

Struts2 UI タグ : フォームの作成

<%@ taglib prefix="s" uri="/struts-tags" %><s:form action='calc'> <s:textfield label="x is" name="x"/> <s:textfield label="y is" name="y"/> <s:submit/></s:form>

calc-input.jsp

ブラウザで http://localhost:8080/grape_sample_struts2/test3-input.jsp にアクセス

55

バリデーションが必要

56

アノテーションでバリデーション

public class CalcAction extends ActionSupport { : @FieldExpressionValidator( expression="y!=0", message="y should not be zero.") public int getY() { return y; } :}

CalcAction.java

FieldExpressionValidator で getter か setter にアノテーション を加える (FieldExpressionValidatorなど)

ValidationAware を implement する

普通、ActionSupport を extends すればよい

ブラウザ

57

UI タグとテーマcalc-input.jsp

<form action="calc.action" method="post"><table> <tr><td><label>x is:</label></td> <td><input type="text" name="x"/></td></tr> <tr><td><label>y is:</label></td> <td><input type="text" name="y"/></td> </tr> <tr><td colspan="2"> <div align="right"> <input type="submit" value="Submit" /></div></td> </tr></table></form>

<%@ taglib prefix="s" uri="/struts-tags" %><s:form action='calc'> <s:textfield label="x is" name="x"/> <s:textfield label="y is" name="y"/> <s:submit/></s:form>

このようにレンダリングされる:

デフォルトの‘xhtml’ テーマを使っている

58

テーマの切り替え勝手に<table> や <label> を入れられたくない…

‘simple’テーマを使おう

calc-input.jsp

<form action="calc.action" method="post"> <input type="text" name="x"/> <input type="text" name="y"/> <input type="submit" value="Submit"/></form>

<%@ taglib prefix="s" uri="/struts-tags" %><s:form action='calc' theme="simple" > <s:textfield label="x is" name="x"/> <s:textfield label="y is" name="y"/> <s:submit/></s:form>

このようにレンダリングされる:

<s:form action='calc' theme="simple" >

59

simpleテーマ時のエラー表示

エラー表示も自分でデザインしなければならない

s:actionerror, s:fielderror タグを使おう

60

テーマの切り替え (補足)

struts.xml に、

と書いてもよい

<constant name='struts.ui.theme' value="simple" />

61

テーマの作成

自分でテーマを作成できる

struts2タグの出力をFTLでデザインする

FTL ... FreeMakerフレームワークのテンプレート言語

62

そのほかのトピックス

63

Struts2 の制御フロー

設定編でみたように、struts2はサーブレットAPI の Filter Dispatcherから駆動される。

様々なインターセプタが、バリデーションの実行、リクエストパラメータの設定などする

アクションがビジネスロジックを実行し、リザルトはブラウザにHTML等をレンダリングし返す。

64

OGNL

Object-Graph Navigation Language

Struts2タグの属性から オブジェクトを参照するための言語

65

STRUTS1との比較

66

struts1との比較Convention over Configuration

URL、ファイル名やクラス名に関する規約により、 設定ファイルを可能なかぎり廃している。

設定もできるので、カスタマイズ可能性は十分に残されている。

アノテーション

バリデーションの設定を ~~.xml ではなくソースにアノテーションを使って記述。

ActionはPOJO!

より軽量なWeb開発が可能に67

struts1との比較 (私の主観とぐち)struts-config : 設定の嵐、嵐…

Servletのように、ソースコードにファイル名やURLをハードコードするよりはマシだった

「どのactionと、どのクラスを結びつけたのか」「どのActionForwardが、どのJSPに転送されるのか」「どのActionFormがどのActionで使われるのか」等、管理が二重になっていた

そのかわり、再コンパイルなしで様々な設定が変更できた…が、あまり修正の必要がないものばかりだったような。(むしろ識別子の変更がやりにくくて不便)

また、設定ファイルを増やしても信頼性が上がるとはいえない

言うほどActionやJSPのモジュール性は良くない (再利用しない)

よりシンプルなほうが良いじゃん!68

form beanは…

各クラスそのものにgetter/setterを定義

型付き (かつ、Integer.parseIntとかは要らない)

余計なクラスは要らない

<form-beans> <form-bean name="searchForm" type="agusadb.struts.action.person.form.SearchForm"/> <form-bean name="updateStartForm" type="agusadb.struts.action.person.form.UpdateStartForm"/> <form-bean name="person" type="agusadb.struts.action.person.form.PersonForm"/> </form-beans>

各アクション毎にform beanのクラス1つ (DynaActionFormとかもあったけど…)

69

action mapping は…Zero Configuration

設定が要らなくなった!(書いてもよいが)

名前付け規約。

<action>-<result>.jsp

これぞ CoC

<action path="/main" forward="person.main"/><action path="/searchStart" forward="person.search"/><action path="/search" type="agusadb.struts.action.person.SearchPersonAction" name="searchForm" scope="request" input="person.search"> <forward name="notFound" path="person.search"/> <forward name="detailView" path="person.detail"/> <forward name="listView" path="person.list"/></action><action path="/updateStart" type="agusadb.struts.action.person.UpdateStartAction" name="person" scope="request"> <forward name="existPerson" path="person.update.start"/> <forward name="newPerson" path="person.register.start"/></action><action path="/updateConfirm" type="agusadb.struts.action.person.UpdatePersonConfirmAction" name="person" scope="request"> <forward name="retryUpdate" path="person.update.start"/> <forward name="retryRegister" path="person.register.start"/> <forward name="confirmUpdate" path="person.update.confirm"/> <forward name="confirmRegister" path="person.register.confirm"/></action><action path="/updateProceed" type="agusadb.struts.action.person.UpdatePersonProceedAction" name="person" scope="request"> <forward name="retryUpdate" path="person.update.start"/> <forward name="retryRegister" path="person.register.start"/> <forward name="proceededUpdate" path="person.update.proceeded"/> <forward name="proceededRegister" path="person.register.proceeded"/></action>

70

さいごに

71

英語を恐れない

日本語の資料は少ないが、Struts2のサイトにある情報だけで十分に開発できる

Googleで検索しまくる前に、原典に当たろう

72

参考文献・サイトServlet/JSP 古典コア・サーブレット&JSP―Javaサーバ技術によるWeb開発 (単行本), Marty Hall著, サンモア・サーブレット

Struts2Apache Struts2 Documentation - Guides

すべてはここに始まり、ここに終わる (かも)

http://struts.apache.org/2.x/docs/guides.htmlStarting Struts 2 (PDF版; free)

http://www.infoq.com/minibooks/starting-struts273

ご清聴ありがとうございました。

74