咖啡日语论坛

 找回密码
 注~册
搜索
查看: 3725|回复: 3

サーバーサイドJava超入門

[复制链接]
发表于 2007-5-25 11:01:05 | 显示全部楼层 |阅读模式
回复

使用道具 举报

 楼主| 发表于 2007-5-25 11:02:24 | 显示全部楼层
サーバーサイドJava超入門(1)



リスト1 ●文字列「Hello World 」を表示するサーブレット「HelloServlet 」(sample0 )
[画像のクリックで拡大表示]

図1●WebブラウザからHelloServletを呼び出したところ(sample0)
[画像のクリックで拡大表示]

図2●HelloServletが動作する手順(sample0)。文字を表示するだけだが,HTTPを利用するれっきとしたWebアプリケーションだ
[画像のクリックで拡大表示]
    【要約】 JavaはもともとクライアントのWebブラウザ上で動作する技術として開発されました。しかし現在では,サーバーサイドのアプリケーションを構築する技術として大活躍しています。今や,Javaプログラミングをものにするのに,サーバーサイドの知識の習得は避けて通れません。ここではサーバーサイドJavaを基礎から解説していきます。【本文】 サーバーサイドJavaの仕様である「Java Enterprise Edition(Java EE)」*1が企業の情報システムの構築によく使われるようになったのには,いくつか理由があります。
 まず,Java自体が優れた特徴を持っている点です。特集2で解説したように,オブジェクト指向をうまく利用することで効率のよいプログラミングができます。Windows,Linux,各種商用UNIXなど,多くのプラットフォームに実行環境が用意されている点も見逃せません。メモリー管理が自動化されているため,C/C++で問題になっていたメモリーの解放ミスに起因するメモリー・リークを気にする必要がないことも,開発者にとって大きなメリットです。
 もう一つの理由は,JavaEEにはサーバーサイド・アプリケーションを構築するために必要な様々な技術があらかじめ用意されていることです。HTTP(HypertextTransferProtocol)のリクエストを処理してレスポンスを返す「サーブレット」,WebページにJavaプログラムを埋め込む「JavaServerPages(JSP)」,サーバーサイドで動作するコンポーネントを実現する「Enterprise JavaBeans(EJB)」などがあります。
 現在のサーバーサイド・アプリケーションでは,クライアントにWebブラウザを利用するWebアプリケーションが主流です。こうしたアプリケーションでは,サーブレットを核に,JSPやEJBなどを組み合わせた構成を採るのが一般的になっています。JSPだけでWebアプリケーションを構築することも可能ですが,JSPでWebページに大量のJavaコードを埋め込むと,可読性や保守性が著しく悪くなってしまいます。そこで今回は,サーブレットを中心に解説していきます。JSPは,最後にサーブレットから表示関係の処理を抜き出す際に取り上げます*2
サーブレットの基礎とセッション管理

 実際にサーブレットを作ってみましょう。リスト1[拡大表示]にサーブレットとして動作する最低限のコードを示しました(sample0)。プログラミングのサンプルとしておなじみの「Hello World」です*3。これを実行すると図1[拡大表示]のように表示されます。
 「サーバーサイドJavaは難しい」と思っている人には拍子抜けするくらい簡単なコードですが,必要最低限の機能を持ったWebアプリケーションとしてはこれで十分です。サーブレットの位置を示すURLにWebブラウザからアクセスすると,Webコンテナがサーブレットを起動します(図2[拡大表示])。そして,サーブレットの実行結果を,Webブラウザに送って表示させます。クライアントであるWebブラウザとサーバー上で動作するサーブレットの間では,HTTPによる通信が必ず行われます*4
サーブレットの記述には「決まりごと」がある リスト1の内容を詳しく見ていきましょう。最初に属するパッケージを宣言しています。これは特集2にも出てきましたね。次の三つのimport文で,サーブレットに必要なクラスを宣言しています。「*」はそのパッケージの下にあるすべてのクラスを指します。それなら,「javax.servlet.*があればjavax.servlet.http.*は要らないんじゃないの」と思うかもしれません。しかし実際には,*が表すのはパッケージの直下のクラスだけで,その下のパッケージのクラスは含まないのでそうはいきません。javax.servletパッケージにはサーブレット一般に関するクラス,javax.servlet.httpパッケージにはサーブレットでHTTPを扱うためのクラス,java.ioパッケージにはシステム入出力に関するクラスがそれぞれ入っています。
 サーブレットの本体に相当するのがHelloServletクラスです。サーブレットのクラスは,サーブレットの基本機能を備えた既存のHttpServletクラスを継承する決まりになっています。通常のWebアクセスを処理するサーブレットは,HttpServletクラスにあらかじめ用意されているdoGetメソッドをオーバーライドして,その中に処理を記述します(doGetの意味はあとで説明します)。
 doGetメソッドはHttpServletRequest型とHttpServletResponse型の二つの引数を取ります。前者はWebブラウザからの「リクエスト・メッセージ」のオブジェクト,後者はWebブラウザに返信する「レスポンス・メッセージ」のオブジェクトを表します。サーブレットの処理を一言で表すと「リクエストを受け取り,それに基づく結果をレスポンスとして返す」ことです。
 throwsの後には二つの例外クラスを記述します。最初は「こう書くものだ」と考えておけばいいでしょう。実際のシステムで使われるサーブレットには,例外が起こったときの処理を明示的にプログラミングする必要があります。
 ここまでがサーブレットを書くときの「決まりごと」です。したがって動作を表すコードは,後に続く2行しかありません。最初の行で,レスポンス・オブジェクトのgetWriterメソッドを呼び出し,文字列を表示するためのPrintWriterオブジェクトを取得しています。次の行で,このオブジェクトに「Hello World」という文字列を出力しています。これがHTMLのデータとしてブラウザに返信されるのです。
回复 支持 反对

使用道具 举报

 楼主| 发表于 2007-5-25 11:03:53 | 显示全部楼层
サーバーサイドJava超入門(2)


ユーザーがブラウザで入力したデータを処理して返す
      

図3 ●ブラウザから入力したメッセージをWeb ページに表示するサンプル(sample1 )
[画像のクリックで拡大表示]

リスト2 ●メッセージ入力画面のHTML ファイル(sample1 )
[画像のクリックで拡大表示]

リスト3 ●ブラウザから入力したメッセージをWeb ページに表示するサーブレット「ShowMessage 」
[画像のクリックで拡大表示]

図4 ●HTTP リクエストのGET メソッドとPOST メソッドの違い
[画像のクリックで拡大表示]

図5 ●セッション・オブジェクトを利用してセッション間で情報を共有するサンプル(sample2 )
[画像のクリックで拡大表示]

リスト4 ●セッションの処理を追加した「ShowMessage 」のdoPost メソッド(sample2 )
[画像のクリックで拡大表示]

リスト5 ●セッションを利用してブラウザの入力データを取り出すサーブレット「ShowSec­ond 」のdoGet メソッド(sample2 )
[画像のクリックで拡大表示]
    ユーザーがブラウザで入力したデータを処理して返す サーブレットの基本形がわかったところで,もう少しWebアプリケーションらしくしてみましょう。リスト1はブラウザから入力データを受け取っていないため,リクエストの処理が存在しません。また,ブラウザに返すデータも,コンテント・タイプの指定やタグがない素の文字列だけで,あまりにそっけなさすぎます。
 そこで,ブラウザから入力されたデータを処理し,その結果をWebページの形で返すように改造します(図3[拡大表示],sample1)。入力画面のHTMLをリスト2[拡大表示]に示しました。ユーザーが入力フォームに文字を入れて「メッセージを送る」と書かれたボタンを押すと,messageという名前の文字列のデータがShowMessageというサーブレットに送られます。formタグのmethod属性はpostと指定しています。
 ShowMessageサーブレットのコードはリスト3[拡大表示]です。リスト1ではdoGetメソッドをオーバーライドしていたのに対し,今度はdoPostメソッドをオーバーライドしています。これらの違いは何でしょう。
 実は,doGetの「Get」とdoPostの「Post」は,HTTPの仕様で決められている2種類のリクエストの送り方,「GETメソッド」と「POSTメソッド」をそれぞれ表しています。これらはJavaのメソッドとは意味が違いますので注意してください。HTTPのGETメソッドで送られてくるリクエストを処理するのがサーブレットのdoGetメソッド,POSTメソッドで送られてくるリクエストを処理するのがdoPostメソッドです。ややこしいですね。
 GETメソッドは,ブックマーク,リンク,URLの指定などによる通常のWebアクセスの際にリクエストを送る方式です。formタグでmethod属性にgetを指定すると,ユーザーがフォームに入力したデータもGETメソッドで送ることができます(図4[拡大表示])。この場合,URLにデータが埋め込まれます*5。一方,formタグでmethod属性にpostを指定すると,フォームのデータはPOSTメソッドで送られます。データはリクエスト・メッセージの本体であるメッセージ・ボディに格納されます。
 GETメソッドによるフォーム・データの送信は,検索系のサイトでよく使われています。検索結果のページのURLに検索キーが埋め込まれるので,ブックマークしたりリンクを張ったりできるからです。ただ,GETメソッドでは,送るデータが多くなるにつれてURLが長くなってしまいます。アンケートの入力ページなど,URLにデータを残す必要がない場合はPOSTメソッドを使用します。
 GETとPOSTの違いがわかったところでリスト3に戻りましょう。まず,ブラウザから送られたリクエストの処理です。リクエスト・オブジェクトのsetCharacterEncodingメソッドで,文字コードをシフトJISに指定します*6。この指定をしないと正しい文字コードでデータを受け取れず,フォームで日本語を入力して送信した場合に文字化けが起こるので注意してください。フォームの入力データを受け取るメソッドがgetParameterです。このメソッドはStringオブジェクトを返します。
 リクエストの処理が終わったら,ブラウザに返信するレスポンスの処理を行います。HTMLとして返信するには,コンテント・タイプの指定が必要です。レスポンス・オブジェクトのsetContentTypeメソッドで指定します。表示するWebページの文字コードも同時に指定しています。
 今回は,PrintWriterオブジェクトに出力する内容にHTMLタグを追加し,きちんとしたWebページにしています。WebブラウザはHTMLタグの部分を解釈して表示します。一つのprintlnメソッドにHTMLをすべて記述すると見にくくなるので,適当に分割して記述するのが普通です。取得したStringオブジェクトをHTMLのコードの中に埋め込めば,Webページにユーザーが入力したメッセージが表示されるようになります。
セッション・オブジェクトを利用し
複数のWebページで情報を共有 ただ,これだけではまだ,Webアプリケーションを実現する既存の仕組みであるCGIとさほど違いはありません。サーブレットを利用するメリットは,Webアプリケーションの構築に便利な様々な機能があらかじめ備わっている点にあります。
 中でも重要なのが,セッション管理の機能です*7。HTTPは,1回のアクセスごとにセッションが完結するという性質を持っています。このため,そのままでは複数のWebページで情報を共有することができません。CGIで複数ページにわたって情報を共有するには,セッションの情報を保存しておく何らかの仕組みをプログラマが作り込む必要がありました。
 これに対してサーブレットには,ユーザー単位のセッションを表す「セッション・オブジェクト」があらかじめ用意されています。ユーザーがWebサイトにアクセスしている間は,ユーザーごとにセッション・オブジェクトが自動的に保持されます*8。ここにデータを貼り付けておくだけで,異なるWebページの間でデータを共有できるのです*9。セッション・オブジェクトは,ユーザーがブラウザを終了するか,セッションを共有しているWebページに一定時間アクセスしないと自動的に破棄されます*10
 セッション・オブジェクトの動作を確認するため,Webブラウザで入力したデータをリンク先のページに表示するサンプルを用意しました(図5[拡大表示],sample2)。最初にアクセスするShowMessageサーブレットで入力データをセッション・オブジェクトに貼り付けます。ShowMessageからリンクで飛ぶShowSecondサーブレットで,セッション・オブジェクトから入力データを取り出して表示しています。
 セッションを扱えるように改造したShowMessageがリスト4[拡大表示]です。getSessionは,セッション・オブジェクトを取得するためのメソッドです。引数に「true」を指定すると,セッション・オブジェクトが存在しない場合には新たに作られます。「false」を指定した場合は,セッション・オブジェクトがなくても生成されません。
 保存しておきたいオブジェクトをセッション・オブジェクトに貼り付けるメソッドがsetAttributeです。ここでは「message」という名前で入力データのStringオブジェクトを貼り付けています。
 ShowSecondサーブレットでは,セッションから必要なデータを取り出しています(リスト5[拡大表示])。まず,getSessionメソッドで,すでにあるセッション・オブジェクトを呼び出しています。ここではセッション・オブジェクトを生成する必要はないのでfalseを指定しています*11
 次にgetAttributeメソッドで「message」という名前が付いたオブジェクト,すなわちユーザーがブラウザで入力したデータを取得しています。Stringオブジェクトとして取り出すために,String型でキャストしています*12。このデータをHTMLに組み込んで表示しています。
回复 支持 反对

使用道具 举报

 楼主| 发表于 2007-5-25 11:04:31 | 显示全部楼层

      

図6●セッションを利用したショッピング・カートのサ
[画像のクリックで拡大表示]

リスト6●商品の入力画面のHTML ファイル(sample3 )
[画像のクリックで拡大表示]

リスト7 ●ショッピング・カートを実現するサーブレット「CartServlet 」(sample3 )
[画像のクリックで拡大表示]

図7 ●リスト7 のCartServlet を,入出力に特化したCartServlet とカートの本体であるCart オブジ
[画像のクリックで拡大表示]

リスト8●Cart オブジェクトを利用するよう改造したCartServlet のdoPost メソッド(sample4 )
[画像のクリックで拡大表示]

リスト9●Cart オブジェクトを生成するためのCart クラス(sample4 )
[画像のクリックで拡大表示]
   
ショッピング・カートでMVC を実感する

 入力したメッセージをそのまま表示するサーブレットのサンプルにはさすがに飽きてきましたね。もうちょっと実用に近いサンプルを取り上げてみましょう。セッションを利用するアプリケーションといえば何といっても「ショッピング・カート」です。
まずは一つのサーブレットでカートを実現してみる ショッピング・カートの基本機能は「ユーザーが入力した商品をカートに追加していく」ことです(図6[拡大表示])。これをセッション・オブジェクトを使って実現することにしましょう。
 まず,入力画面のHTMLを用意します(リスト6[拡大表示])。product1として商品1に追加したい数,product2として商品2に追加したい数をそれぞれ入力するようになっています。
 ショッピング・カートの動作を一つのサーブレットで実現したのがリスト7に示した「CartServlet」です(sample3)。中でどんな処理を行っているのか,順番に見ていきましょう。
 まず,ブラウザで入力された値をint型の配列で受け取っています*13。int型にしたのは,ブラウザで入力された数字を計算に使う必要があるからです。ただ,getParameterメソッドが返す値はStringオブジェクトです。そこで,IntegerクラスのparseIntというメソッドでint型の整数値に変換しています*14
 次にgetSessionメソッドでセッション・オブジェクトを取得しています。最初のアクセスでは,ここでセッション・オブジェクトが生成されます。
 セッション・オブジェクトに貼り付けるのは,amountという名前のIntegerオブジェクトにしました。int型の整数だと,セッション・オブジェクトに貼り付けたり取り出したりするのが面倒だからです。amountが表す数字が,カートに入っている商品の累計を表します。プログラムでは,セッション・オブジェクトから取得したIntegerオブジェクトをamountに入れています。
 最初のアクセスでは,まだセッション・オブジェクトには何もないので,amountの値はnullになります。そこで,amountがnullの場合は,「0」を表すIntegerオブジェクトを生成し,amountの値にしています。
 次の部分で,ブラウザで入力した数値(product)をamountに加算しています。Integerオブジェクトからint型の整数値を取り出すため,intValueというメソッドを使いました。こうして加算されたamountをセッション・オブジェクトに書き戻しています。
 最後に,商品の累計であるamountをHTMLで表示しています。「買い物を続ける」というリンクをクリックすると,また商品の入力ページに戻ります。入力ページで商品の数を追加すると,それに応じてカートに入っている商品の数も増えていきます。
 これで,図6のように動作するショッピング・カートのサーブレットが実現できました。カートに商品が入っている状態で一度ブラウザを終了し,もう一度アクセスしてみると,セッションが作り直されて前のデータが消えていることを確認できます。サーブレットが動作しているマシンに複数のパソコンからアクセスできる環境であれば,それぞれのパソコンごとに別のカートが用意されているのを確認できます。
入出力の制御部分とカートの本体に分割する このカートは,最小限の機能しか持っていません。機能を追加したくなってきますね。「在庫データベースを使って在庫管理と連動させる」といった大がかりな改造は置いておくとして,このショッピング・カートにちょっとした改良を加えたい場合,改良点は大きく二つに分かれます。「商品の数を増やしたい」「Webページの見た目をきれいにしたい」という入出力に関する改良と,「商品の数をクリアする機能を付けたい」「商品の合計金額を計算したい」といったカート本体の機能に関する改良です。
 ショッピング・カートのシステムを一人で開発している場合は,すべての機能を一つのサーブレットに詰め込んだほうが管理が楽だと思うかもしれません。しかし,サーバーサイドJavaの開発は,通常は複数の開発者が分担して行います。プログラムを機能別に分割したほうが,開発を分担しやすくなります。たとえ一人で開発する場合でも,プログラムを機能別に分けておいたほうが,バグの原因を追いかけやすくなります。
 そこで今回は,入出力の機能をサーブレットに残して,新たにカート本体を表す「Cartクラス」を作成することにしました(図7[拡大表示],sample4)。Cartクラスから生成したCartオブジェクトに商品の累計の情報を持たせ,サーブレットからアクセサ・メソッドを通してこの情報にアクセスするようにします。CartServletとCartの二つのクラスでsample3と同じ動作を実現します*15
 Cartオブジェクトを利用するように書き換えたCartServletがリスト8[拡大表示]です。sample3(リスト7)では累計を表すIntegerオブジェクトをセッション・オブジェクトに直接貼り付けていました。これに対しsample4では,Cartオブジェクトに商品の累計をint型の整数値として持たせ,Cartオブジェクトをセッション・オブジェクトに貼り付けるようにしています。このため,amountをint型の整数値として扱えるようになりました。
 ブラウザの入力データの取得やセッション・オブジェクトの取得はリスト7と同じです。セッション・オブジェクトからはCartオブジェクトを取り出すように記述します。
 初回のアクセスではCartオブジェクトは貼り付いていないので,Cartオブジェクトを表すcart変数はnullになっています。この場合,新しいCartオブジェクトを生成しています。コンストラクタには,商品の種類を引数として渡します。
 次のforループでCartオブジェクトのアクセサ・メソッドを呼び出しています。addAmountメソッドで,第1引数の番号で表される商品の累計にブラウザの入力値(product)を加算しています。次にgetAmountメソッドを使って,引数の番号で表される商品の累計を取得しています。Cartオブジェクトに対する操作が終わったら,Cartオブジェクトをセッション・オブジェクトに書き戻します。HTMLの出力部分はリスト7と同じです。
 次にCartクラスを見てみましょう(リスト9[拡大表示])。内部で商品の累計を保存する変数としてint型の配列であるamountを宣言しています。この値にクラスの外から直接触れないようにするため,アクセス修飾子はprivateにしています。
 次の部分がコンストラクタです。商品の数を引数に取り,その分の長さを持つamountの配列の領域を確保しています。最後に,累計の値を外から操作するための二つのアクセサ・メソッドを定義しています。累計を返すgetAmountメソッドは,引数が示す番号のamountを返します。もう一つのaddAmountメソッドは,第1引数が示す番号のamountに第2引数の値を加算します。
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注~册

本版积分规则

小黑屋|手机版|咖啡日语

GMT+8, 2024-5-11 12:55

Powered by Discuz! X3.4

© 2001-2017 Comsenz Inc.

快速回复 返回顶部 返回列表