■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
                      2008年01月13日

    楽しいJava講座 - 初心者から達人へのパスポート
                  vol.087

                                セルゲイ・ランダウ
 バックナンバー: http://www.flsi.co.jp/Java_text/
■■■■■■■■■■■■■■■■■■■■■■■■■■■■■


[このメールマガジンは、画面を最大化して見てください。]


========================================================
◆ 01.Tomcatのアプリケーション開発
========================================================


次に、CustomerDbManagerクラスのときと同様にして、下記の
ようなItemDbManagerクラスを作成しましょう。
--------------------------------------------------------
package jp.co.flsi.lecture.webapp.db;

import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Vector;

import jp.co.flsi.lecture.webapp.entity.Item;

public class ItemDbManager extends DbManager {
   private Vector<Item> itemList = new Vector<Item>();
   private String selectAllSql = "SELECT * FROM ITEM";
   private String selectNameSql = "SELECT * FROM ITEM" +
                           " WHERE NAME LIKE ?";
   private String selectCategorySql = "SELECT * FROM ITEM" +
                           " WHERE CATEGORY LIKE ?";
   private String selectNameAndCategorySql = "SELECT * FROM ITEM" +
                           " WHERE NAME LIKE ? AND CATEGORY LIKE ?";

   public Vector<Item> getItemList() {
      return itemList;
   }

   public void selectAllData() {
      try {
         connect();
         Statement selectSql = conn.createStatement();
         ResultSet rs = selectSql.executeQuery(selectAllSql);
         while (rs.next()) {
            Item aItem = new Item();
            aItem.setNum(rs.getString("NUM"));
            aItem.setName(rs.getString("NAME"));
            aItem.setPrice(rs.getInt("PRICE"));
            aItem.setImage(rs.getString("IMAGE"));
            aItem.setCategory(rs.getString("CATEGORY"));
            aItem.setQuantity(rs.getInt("QUANTITY"));
            getItemList().addElement(aItem);
         }
         selectSql.close();
         disconnect();
      }
      catch (SQLException exception) {
         exception.printStackTrace();
      }
   }
  
   public void selectData(String name, String category) {
      try {
         connect();
         PreparedStatement selectPs = null;
         ResultSet rs;
         if (name == null && category == null) {
            selectPs = conn.prepareStatement(selectAllSql);
            rs = selectPs.executeQuery(selectAllSql);
         }
         else if (name != null && category == null) {
            selectPs = conn.prepareStatement(selectNameSql);
            selectPs.setString(1, '%' + name + '%' );
            rs = selectPs.executeQuery();
         }
         else if (name == null && category != null) {
            selectPs = conn.prepareStatement(selectCategorySql);
            selectPs.setString(1, '%' + category + '%' );
            rs = selectPs.executeQuery();
         }
         else {
            selectPs = conn.prepareStatement(selectNameAndCategorySql);
            selectPs.setString(1, '%' + name + '%' );
            selectPs.setString(2, '%' + category + '%' );
            rs = selectPs.executeQuery();
         }
         while (rs.next()) {
            Item aItem = new Item();
            aItem.setNum(rs.getString("NUM"));
            aItem.setName(rs.getString("NAME"));
            aItem.setPrice(rs.getInt("PRICE"));
            aItem.setImage(rs.getString("IMAGE"));
            aItem.setCategory(rs.getString("CATEGORY"));
            aItem.setQuantity(rs.getInt("QUANTITY"));
            getItemList().addElement(aItem);
         }
         selectPs.close();
         disconnect();
      }
      catch (SQLException exception) {
         exception.printStackTrace();
      }
   }

}
--------------------------------------------------------

このソース・コードのselectData()メソッドの中では、引数の
nameやcategoryがnullの場合の処理も行っていますが、これらが
nullであるということがどういう意味を持つのかについてはあと
で説明します。

残りの部分は説明しなくてもわかりますね。
わからない人は、vol.025やvol.044あたりを復習するとよいで
しょう。


次に、customerList.jspのときと同様にして、下記のような
itemList.jspを作成しましょう。
--------------------------------------------------------
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="Shift_JIS" %>

<HTML>
<HEAD>
<TITLE>商品リスト</TITLE>
</HEAD>
<BODY bgcolor="#77ffff" text="#fa5a00">
<H1>商品のリスト</H1>
<TABLE border="1" width="100%">
  <TBODY>
    <TR>
      <TH>商品番号</TH>
      <TH>商品名</TH>
      <TH>価格</TH>
      <TH>カテゴリー</TH>
      <TH>イメージ</TH>
    </TR>

<%@ page import="java.util.Vector" %>
<%@ page import="jp.co.flsi.lecture.webapp.entity.*" %>
<jsp:useBean class="jp.co.flsi.lecture.webapp.db.ItemDbManager" id="ITEMDB" scope="request" />
<%    Item  anItem;
      Vector<Item> itemList = ITEMDB.getItemList();
      for (int i = 0; i < itemList.size(); i++) {
         anItem = itemList.elementAt(i); %>
          <TR>
            <TD><%= anItem.getNum() %></TD>
            <TD><%= anItem.getName() %></TD>
            <TD><%= anItem.getPrice() %></TD>
            <TD><%= anItem.getCategory() %></TD>
            <TD><IMG src="http://localhost:8080/JStudy2<%= anItem.getImage() %>"></TD>
          </TR>
<%      } %>

  </TBODY>
</TABLE>

</BODY>
</HTML>
--------------------------------------------------------

このソース・コードの中の

<IMG src="http://localhost:8080/JStudy2<%= anItem.getImage() %>">

は、画像ファイルをWebブラウザーにダウンロードして表示するための
タグで、src属性の値には、画像ファイルの所在場所を示すURLを指定
します。
ここでは、そのURLのうち可変部分を<%= anItem.getImage() %>という
コードによって取り出しています。つまり、URLのうちの固定部分(ここ
ではhttp://localhost:8080/JStudy2の部分)はJSPのファイルに直接
書き込んでおいて、可変部分(画像ファイルによって異なる部分)は
データベースの中に保管しておき、Javaのコードで取り出して書き出す
ようにしています。

あとはcustomerList.jspと同様ですから、説明不要ですね。


次に、CustomerServletクラスのときと同様にして、下記のような
ItemServletクラスを作成しましょう。
--------------------------------------------------------
package jp.co.flsi.lecture.webapp.servlet;

import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import jp.co.flsi.lecture.webapp.db.ItemDbManager;

public class ItemServlet extends HttpServlet {
   public void doPost(HttpServletRequest req, HttpServletResponse res) throws IOException, ServletException {
      req.setCharacterEncoding("Shift_JIS");
      ItemDbManager itemDb = new ItemDbManager();
      itemDb.selectData(req.getParameter("itemName"),req.getParameter("category"));
      req.setAttribute("ITEMDB",itemDb);
      getServletContext().getRequestDispatcher("/itemList.jsp").forward(req,res);
   }

}
--------------------------------------------------------

前回のCustomerServletでは、doGet()メソッドを使いましたが、
ItemServletではdoPost()メソッドを使っていることに注意して
ください。
これは、あとで作成するHTMLファイルの中で、POSTメソッドで呼び
出すためです。

また、上記のソース・コードの中の

req.setCharacterEncoding("Shift_JIS");

(これはHttpServletRequestのスーパーインターフェースのServletRequest
のメソッド)は、vol.075でも説明しましたが、Webブラウザーから入力
されるパラメーターがShift_JISで書かれた文字列であることをサーブ
レットに教えるものです。

パラメーターを入力するためのWebページとしては、あとでitemSelect.html
というファイルを作成しますが、皆さんはShift_JIS環境のEclipseを使っ
て開発しているはずなので、このHTMLファイルもShift_JISになります。
すると、このWebページを開いたときのWebブラウザーのエンコーディン
グはShift_JISになっているはずです。そして、その環境でパラメーター
を入力するとShift_JISで入力されます。
ところが、サーブレットはパラメーターがどのエンコーディングで入力
されたものであるかを知りませんので、上記のようにして明示的に教え
てやる必要があるのです。

あとは、説明しなくてもわかると思います。


では、このサーブレットをWeb Application Deployment Descriptor
(Webアプリケーション・デプロイメント記述子)に登録して
おきましょう。
パッケージ・エクスプローラーの中のJStudy2の中のWEB-INFの中
のweb.xmlを下記のように編集します。
--------------------------------------------------------
<?xml version="1.0" encoding="ISO-8859-1"?>

<web-app xmlns="http://java.sun.com/xml/ns/javaee"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
   version="2.5">

    <servlet>
        <servlet-name>TestServlet</servlet-name>
        <servlet-class>jp.flsi.lecture.servlet.TestServlet</servlet-class>
    </servlet>

    <servlet>
        <servlet-name>TestServlet2</servlet-name>
        <servlet-class>jp.flsi.lecture.servlet.TestServlet2</servlet-class>
    </servlet>

    <servlet>
        <servlet-name>AgeCalcServlet</servlet-name>
        <servlet-class>jp.co.flsi.lecture.webapp.servlet.AgeCalcServlet</servlet-class>
    </servlet>

    <servlet>
        <servlet-name>CustomerServlet</servlet-name>
        <servlet-class>jp.co.flsi.lecture.webapp.servlet.CustomerServlet</servlet-class>
    </servlet>

    <servlet>
        <servlet-name>ItemServlet</servlet-name>
        <servlet-class>jp.co.flsi.lecture.webapp.servlet.ItemServlet</servlet-class>
    </servlet>

    <servlet-mapping>
        <servlet-name>TestServlet</servlet-name>
        <url-pattern>/servlet/test</url-pattern>
    </servlet-mapping>

    <servlet-mapping>
        <servlet-name>TestServlet2</servlet-name>
        <url-pattern>/servlet/test2</url-pattern>
    </servlet-mapping>
   
    <servlet-mapping>
        <servlet-name>AgeCalcServlet</servlet-name>
        <url-pattern>/servlet/age</url-pattern>
    </servlet-mapping>

    <servlet-mapping>
        <servlet-name>CustomerServlet</servlet-name>
        <url-pattern>/servlet/customers</url-pattern>
    </servlet-mapping>

    <servlet-mapping>
        <servlet-name>ItemServlet</servlet-name>
        <url-pattern>/servlet/items</url-pattern>
    </servlet-mapping>
   
</web-app>
--------------------------------------------------------


最後に、キーワードとカテゴリーを(パラメーターとして)入力
して商品を検索するためのHTMLファイル(ファイル名は
itemSelect.htmlとする)を下記のように作成しましょう。

(1) パッケージ・エクスプローラーの中のJStudy2を右クリックし、
「新規」→「ファイル」を選択します。

(2) 「ファイル名」欄に
itemSelect.html
と入力して、「終了」ボタンをクリックします。

(3) パッケージ・エクスプローラーの中にitemSelect.htmlができ
ましたら、それを右クリックし、「アプリケーションから開く」→
「テキスト・エディター」を選択します。

itemSelect.htmlのエディターが開きましたら、下記のようなコードを
入力しましょう。
(キーワードは本来なら説明文の中から抽出すべきでしょうけど、
ここではアプリケーションを簡略化させたために商品の説明文は
ありません。したがって、ここでは商品名の一部をキーワードと
して検索することにします。)

--------------------------------------------------------
<HTML>
<HEAD>
<TITLE>商品の検索</TITLE>
</HEAD>
<BODY bgcolor="#77ffff" text="#fa5a00">
<H1>商品の検索</H1>
<FORM action="http://localhost:8080/JStudy2/servlet/items" method="POST">
キーワード(商品名の一部)とカテゴリーを入力し、「送信」ボタンをクリックしてください。
<BR>
<BR>
キーワード:<INPUT TYPE="text" NAME="itemName" VALUE="" SIZE=20>
<BR>
カテゴリー:<INPUT TYPE="text" NAME="category" VALUE="" SIZE=20>
<BR>
<BR>
<INPUT TYPE="submit" NAME="sumit" VALUE="送信">
</FORM>
</BODY>
</HTML>
--------------------------------------------------------

これも、vol.075などで説明したものとほぼ同じなので、説明は不要
ですね。
上記のHTMLファイルでは、キーワードとカテゴリーのパラメーターの
名前をそれぞれitemNameとcategoryにしていますが、これらの名前が
ItemServletの中で使われていることはわかりますね。

WebブラウザーでこのWebページを開いたときに、これらのパラメーター
に何も入力されなかった場合には、サーブレットのreq.getParameter()
メソッドの戻り値としては、nullが返ってくることになります。
これがItemDbManagerの中でnullの処理をしていた理由です。
つまり、これらのnullはキーワードやカテゴリーが指定されなかったこと
を意味するのです。


では、テストをするためにデータベースにデータを入れておきましょう。

DBViewerのパースペクティブを開いて、INTSHOPデータベースに接続し、

「SQL実行・ビュー」に以下のSQLを入力し、実行してください。
--------------------------------------------------------
insert into ITEM values ('F0001', '製品001', 200, '/images/product001.jpg', '食品', 10);
/
insert into ITEM values ('F0002', '製品002', 200, '/images/product002.jpg', '食品', 10);
/
insert into ITEM values ('G0003', '製品003', 200, '/images/product003.jpg', '雑貨', 10);
/
insert into ITEM values ('G0004', '製品004', 200, '/images/product004.jpg', '雑貨', 10);
/
insert into ITEM values ('S0005', '製品005', 200, '/images/product005.jpg', '文具', 10);
/
insert into ITEM values ('S0006', '製品006', 200, '/images/product006.jpg', '文具', 10);
/
--------------------------------------------------------

あるいは、DBツリー・ビューの中のTABLEフォルダーの中のitemをダブル・
クリックし、表の中を編集することによってデータを入力してもかまい
ません。

予めオート・コミットにしておくか、または、あとでコミットすること
もお忘れなく。


では、続いて、画像ファイルをしかるべき場所に保管しましょう。

(1) Eclipseのワークスペースとなっているフォルダーの中のJStudy2フォ
ルダー、つまり、
C:\JavaWorks\JStudy2
はTomcatプラグインによってTomcatが認識できるようになっており、
これが先ほどJSPファイルの中に入力した画像ファイルのURLのうちの
http://localhost:8080/JStudy2
の部分に該当します。

このフォルダーの中にimagesフォルダーを作りましょう。
つまり、
C:\JavaWorks\JStudy2\images
を作成します。

(2) imagesフォルダー、すなわちC:\JavaWorks\JStudy2\imagesの中に
下記の画像ファイルをコピーします。
product001.jpg
product002.jpg
product003.jpg
product004.jpg
product005.jpg
product006.jpg
これらの画像ファイルはホームページに掲載していますので、それらを
ダウンロードして使うか、あるいは、読者がお持ちの画像ファイルを
上記のファイル名にして利用してもかまいません。
このimagesのフォルダー名(ディレクトリー名)からproduct001.jpgなど
のファイル名までの部分をデータベースのIMAGEカラムに書き込んでおい
たことはおわかりですね。


では、EclipseでTomcatを起動し、テストしてみましょう。

Webブラウザーを起動し、下記のURLを入力してください。

http://localhost:8080/JStudy2/itemSelect.html

(1) 「キーワード」欄、「カテゴリー」欄ともに何も入力せずに
「送信」ボタンをクリックしてみてください。この場合は、サーブ
レットに渡されるパラメーターはitemName、categoryともにnullに
なりますから、すべての商品がリストされますね。

(2) 「キーワード」欄、「カテゴリー」欄のいずれか一方、あるい
は両方に入力して「送信」ボタンをクリックすると、それらに合致
した商品がリストされますね。あるいは合致する商品がない場合は、
リストが空行になりますね。

商品の画像も表示されていることを確認してください。



では、今日はここまでにします。次回からは、商品の注文の機能に
はいっていきます。


(次回に続く)


何か、わからないところがありましたら、下記のWebページまで質問を
お寄せください。



========================================================
◆ 02.前回の演習問題の答え
================================================

Webブラウザー上では結果に変わりはないように見えますが、
エンコーディングを確認して見ると、以前はUTF-8だったのが、
今度はShift_JISになっていることがわかりますね。



┏━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
★ホームページ:
      http://www.flsi.co.jp/Java_text/
★このメールマガジンは
     「まぐまぐ(http://www.mag2.com)」
 を利用して発行しています。
★バックナンバーは
      http://www.flsi.co.jp/Java_text/
 にあります。
★このメールマガジンの登録/解除は下記Webページでできます。
      http://www.mag2.com/m/0000193915.html
★このメールマガジンへの質問は下記Webページにて受け付けて
 います。わからない所がありましたら、どしどしと質問をお寄
 せください。
      http://www.flsi.co.jp/Java_text/
┗━━━━━━━━━━━━━━━━━━━━━━━━━━━┛

Copyright (C) 2008 Future Lifestyle Inc. 不許無断複製