プログラム

(秘)JavaServlet技法

初心者から上級者まで。Java言語によるプログラミングの真髄をレクチャーします。Webシステム開発のエキスパート「株式会社 慶」が発行。

全て表示する >

(秘)JavaServlet技法 第22号(01/12/26)

2001/12/26

〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓
まぐまぐマガジンID                                             melma! マガジンID
0000073164              ┏━━━━━━━━━━━━━━━┓             m00048716
                               (秘)JavaServlet技法
━━━━━━━━━━━━┻━━━━━━━━━━━━━━━┻━━━━━━━━━━━
                                                           第22号 2001/12/26発行
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
                                   【お知らせ】
                      来年から配信日が月曜日に変更になります。
                        配信時間は今まで通り午前11時です。
                               よろしくお願いします。

                                  はるな@編集長

━【もくじ】━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
 ・ServletTips:0016
 ・Javaのお作法:第13回
 ・コラム
 ・次回予告
 ・編集後記
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
━【ServletTips:0016】━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
○ログインチェック
今回、作るのはパスワードを使用した簡単なログインチェックです。
自分のWebページで使ってみるのもいいかもしれません。(Servletが動けばですが)
ただし、幾つか問題はあります。
 ・パスワードが一つしか設定できない。(頑張ればたくさん設定できますが・・・)
 ・直にログイン後の画面のURLを指定すると表示されてしまう。
上記の問題点を回避する方法としては
 ・パスワードはDBで管理する
 ・セッション管理を行う
等がありますが、DBやセッションを使用したシステムはまた今度作成したいと思います。

下記の3つのファイルを用意してください。
login.html
PwdServlet.java
success.jsp

/* ここからlogin.html */

<html>
<head>
<title>ログイン画面</title>
</head>
<body>
<center>
<form method="post" action="/servlet/PwdServlet">
パスワードを入力してログインボタンを押して下さい<br>
<input type="text" name="pass" value="" size="30"><br><br>
<input type="submit" name="login" value="ログイン">
</form>
</center>
</body>
</html>

/* ここまでlogin.html */

/* ここからPwdServlet.java */

import java.io.* ;
import java.util.* ;
import javax.servlet.* ;
import javax.servlet.http.* ;

/**
 * PwdServletクラス<br>
 * @author (秘)JavaServlet技法
 */
public class PwdServlet extends HttpServlet {

    String passwd = "JavaServlet" ;     // パスワード

    public void init(ServletConfig con) throws ServletException {
        super.init(con) ;
    }

    public void doPost(HttpServletRequest req, HttpServletResponse res)
      throws ServletException, IOException {

        /* doLoginメソッドでログイン処理をする */
        doLogin(req, res) ;
    }

    /* ログインボタン用処理 */
    public void doLogin(HttpServletRequest req, HttpServletResponse res)
      throws ServletException, IOException {
        res.setContentType("text/html; charset=shift_jis") ;
        PrintWriter pw = res.getWriter() ;
        String pass = req.getParameter("pass") ;

        if (pass.equals(passwd)) {
            String output = "/success.jsp" ;
            ServletContext context = getServletContext() ;
            RequestDispatcher rd = context.getRequestDispatcher(output) ;
            rd.forward(req, res) ;
        }
        else {
            pw.println("<html><head>") ;
            pw.println("<title>ログイン失敗</title>") ;
            pw.println("</head><body><center>") ;
            pw.println("パスワードが違います。<br>") ;
            pw.println("パスワードは" + passwd + "です。") ;
            pw.println("</center></body></html>") ;
        }
    }

    /* リソースクリーンアップ */
    public void destroy() {
        super.destroy() ;
    }
}

/* ここまでPwdServlet.java */

/* ここからsuccess.jsp */

<%@ page contentType="text/html; charset=Shift_JIS" %>

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=Shift_JIS">
<title>ログイン成功</title>
</head>
<body>
<center>ログインしました。</center>
</body>
</html>

/* ここまでsuccess.jsp */

−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
<実行結果>
ログイン画面でパスワードを入力し、
パスワードが正しければ success.jsp に遷移し、
「ログインしました。」というメッセージが表示されます。

パスワードが間違っていれば、
「パスワードが違います。」というメッセージと
ログインするための正しいパスワードが表示されます。

−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
<解説>
まず、ログイン画面で入力したパスワードを、PwdServletクラスが
String pass = req.getParameter("pass")の部分で取得します。

次に取得したパスワードとあらかじめ決めておいた文字列と比較します。
String passwd = "JavaServlet" ; でパスワードをJavaServletに設定しています。
(pass.equals(passwd)) で入力された文字列とパスワードを比較しています。
入力された文字列が JavaServlet であれば success.jsp に遷移します。
入力された文字列が間違っていた(ここでは JavaServlet でない) 場合、
else { 以下に処理が移ります。
                                                                  はるな@編集長
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
━【Javaのお作法】━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
○第13回目のお作法では、前回に出した問題の解説を行います。
  ぜひ、前回の問題と並べて読んでみてください。
  そして、できればもう一度問題に挑戦してみてください。
--------------------------------------------------------------------------------
[初級篇]
1.この問題の要点は、String型の配列を作成することにあります。
   まず、悪い例を提示します。

    悪例1)
        String[] st = {1, 2, 3, 4, 5, 6, ・・・, 100} ;

    悪例2)
        String st = "1" ;
        for (int i = 2 ; i <= 100 ; i++) {
            st = st + Integer.toString(i) + " " ;
        }

    悪例1)のどこが悪いかは、すぐにおわかりでしょう。
    自然数を1から100まで書くのは、かなり大変ですし、仮に問題が
    「1から1000000までの自然数の配列を作成する」とかだったりしたら、
    このやり方ではもはや不可能です。
    もっと汎用的なやり方で配列を作成しなければなりません。
    このようなときは、for文を使います。
    そこで、悪例2)となります。この例では、まずString型のオブジェクトを作成し、
    そこにfor文の中で文字を追加しています。
    このようなやり方だと、確かに汎用性は確保されますが、
    パフォーマンスという面で問題を抱えてしまいます。
    String型のオブジェクトの特徴は、読み出し専用で不変であるということです。
    そのため、for文の中でString型のオブジェクトに文字列を追加した場合、
    改めて新規のオブジェクトを作成し、そこに連結された文字列を入れるという作業が
    行われていることになります。
    つまり、for文が一周するたびに新しいオブジェクトが作成されるわけですから、
    どうしても非効率になるのです。
    正しい解答としては、「for文の中で文字列を連結する場合、
    Stringではなく、StringBufferを使う」ということになります。

2.異なる型の変数同士の計算を行う場合、JAVAの変換規則により出現する
   いちばん大きな型にすべてが拡張されます。
   したがって計算結果を代入する変数はdouble型でないと
   コンパイルエラーが発生してしまいます。

--------------------------------------------------------------------------------
[中級篇]
1.この問題は、clone() メソッドによる浅いコピーと深いコピーの違いを
   確認してもらうためのものです。
   classA の clone() と classB の clone() を比較してみましょう。

    /* classA の clone() メソッド */
    public Object clone() {
        try  {
            return super.clone() ;
        }
        catch (CloneNotSupportedException e) {
            throw new InternalError() ;
        }
    }

    /* classB の clone() メソッド */
    public Object clone() {
        try  {
            classB newClassB = (classB)super.clone() ;
            newClassB.clsBuf_ = (classBuffer)this.clsBuf_.clone() ;

            return newClassB ;

        }
        catch (CloneNotSupportedException e) {
            throw new InternalError() ;
        }
    }

    これでは少しわかりにくいので、classA の方を

    public Object clone() {
        try  {
            classB newClassB = (classB)super.clone() ;
            return newClassB ;
        }
        catch (CloneNotSupportedException e) {
            throw new InternalError() ;
        }
    }

    と置き換えて見ると違いは

    newClassB.clsBuf_ = (classBuffer)this.clsBuf_.clone() ;

    この1文があるかないかになりますね。この1文の内容は、
      ※ clsBuf_ のクローンも作成する
    ということをしています。
    すなわち、 classA のコピーは classA 自身だけをコピーし、
    classB は classB とその中にある clsBuf_ もコピーしたことになります。
    これをしない場合とした場合の違いを書くと、

    classA
      ・classA をコピーしたものが newClassA
      ・newClassA 内の clsBuf_ インスタンスは classA 内の clsBuf_ と同じもの
        ただし、同じ場所を見ているのでどちらかが内容を変更するともう片方の
        内容も変わる

        classA  →  newClassA
          │            (clsBuf_ は classA 内の clsBuf_ を参照する)
        clsBuf_

    classB
      ・classB をコピーしたものが newClassB
      ・newClassB 内の clsBuf_ インスタンスは classB 内の clsBuf_ とは違うもの
        ただし、中の内容はコピーされたものが入っているため同じ値である。
        片方を変更した場合でも、もう片方には影響しない。

        classB  → newClassB
          │          │
        clsBuf_ →  clsBuf_(clsBuf_ は classB の clsBuf_ とは違うオブジェクト)

    ということになります。
    classA のようなコピーを「浅いコピー」又は「シャロウコピー」といい、
    classB のようなコピーを「深いコピー」又は「ディープコピー」といいます。

--------------------------------------------------------------------------------
[上級篇]
1.この問題では、簡単なスレッドプログラミングと、exception による例外処理を
   確認してもらい、不変オブジェクトを作成してもらうためのものです。
   Question1 クラスはスレッドによる実行クラスなので、
   start() メソッドにより、 クラス内の run() スレッドが実行されることになります。
   run() 内では、設定された時間だけ sleep() メソッドで処理を停止
                            ↓
            「○」を表示(4拍ごとに「●」を表示)
                            ↓
                  16回表示したら終了
   という流れです。
   スレッド化により、 QuestionMain クラスとは別のスレッドで実行されます。
   このプログラムは、BPM(1分間の拍数)を見るためのプログラムで、4拍おきに
   ●を表示し、あとの3拍は○を表示していきます。

    java QuestionMain [数値]
    で入力した数値は args[0] に代入され、BPMに必要な時間を計算しています。
    ここでもし数値以外のものを入力した場合、
    NumberFormatException が返ってくるのですが、
    try 〜 catch 〜 finally で例外処理をキャッチしているので、
    catch(NumberFormatException) の中が実行されるのです。
    数値だった場合は、Question1 のコンストラクタにより計算され、
    ミリ秒・ナノ秒を持っています。
    この値を sleep() メソッドの引数として使用し、停止させることができます。

    設問3では、不変オブジェクトの理解度を確かめてみました。
    不変オブジェクトとは、生成してから変化することのないオブジェクトのことを
    言います。そのためには、他のクラスから直接データを変更させることのないよう
    データを保護する必要があります。
    前提として、
        1.クラス内のデータをすべてprivate宣言する。
        2.ゲッターメソッドのみ提供する。(セッターはだめ)
        3.クラス内のデータはすべてコンストラクタで設定する。
    などの条件があります。
    この設問の場合は、ミリ秒とナノ秒がそれにあたります。
    このデータを他のクラスから参照する場合、ゲッターメソッドを作成しそこから
    参照するしか方法はありません。
                                              まぃまぃ・けん・New かときっちゃん
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
━【コラム】━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
○「Javaの女神」

Javaが最初からWebシステム用の言語として開発されたと思っている方も
いらっしゃいますが、実際にはそうではありません。

Javaの開発は携帯情報端末開発プロジェクトの一部として1991年にスタートしました。
当時はまだ"Java"という名前も存在せず、"OAK"と呼ばれていました。
ところが、そのプロジェクトは失敗し、1994年時点ではJava(OAK)は
お蔵入り寸前だったようです。

Java(OAK)のインターネットへの方向転換は1994年に行われました。
名称を"Java"に変え、1995年にインターネット用言語として
キャンペーンが開始されました。
この名称変更とキャンペーンを主導したのが、マーケティング担当ディレクターをしていた
キム・ポレーゼ(Kim.Polese)という若くて(当時34歳)魅力的な女性でした。

技術的に優れていたことだけでなく、見事なマーケティング戦略によって
Javaは大成功を収めました。

ポレーゼはJavaを商業面で成功に導いた女神と言えます。

彼女はその後1996年にマリンバ(Marimba)社を創立し、
現在はその会長および最高戦略責任者をしています。
                                                                            蒲生
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
━【次回予告】━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
 ・ServletTips:0017
 ・Javaのお作法:第14回
 ・Q&A
 ・コラム
 次回は、1月7日発行予定です。
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
━【編集後記】━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥
    今年も無事(?)に終わりそうです。
    (秘)JavaServlet技法も、なんとか毎週発行することが出来ました。
    来年はさらに充実した内容に出来ればと思います。
    来年もよろしくお願いします。
                                                                  はるな@編集長
‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥
    今年ももう1週間をきりましたね。
    思えば今年もいろいろあったなぁ…と懐かしく感じてしまいます。
    しかし、来年こそは少しでも成長しなければと反省するところの方が多いわけで…
    まだまだ未熟ですね(笑)
    何はともあれ、来年もいい年でありますように☆
    …大掃除しなきゃ…(汗
                                                                        まぃまぃ
‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥
    年々、時間の経つのが早くなっているような気がします。
    充実しているからか、それとも単に年を取っただけなのか……
    当然、自分としてはいいほうに解釈してるんですけどね。
                                                                            けん
‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥
    世の中のクリスマスフィーバーが終わると次はお正月フィーバーですね。
    お正月はきらいだけどお正月休みは大好き♪ウフウフ(~o~)
                                                             New かときっちゃん
‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥
    この季節は鍋物ですね。この間、フグチリを食べました。
    だしが酒よりも美味かったなあ〜。
                                                                            蒲生
‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆  お知らせ  ◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆

━━━━━━━━━<<実践!Javaセミナー1ヶ月無料キャンペーン>>━━━━━━━━━
『JavaServletによるシステム開発のエキスパート』(株)慶主催のセミナーを無料で!
 ●即戦力が身につく!実践に役立つ!●講習後はフリーSEへの道も!●会場は当社(池袋)
        応募登録はこちら→  http://www.kei-ha.co.jp/touroku/rirekisho.htm
              コメント欄に「無料Javaセミナー希望」と記入して下さい。
                      株式会社  慶  http://www.kei-ha.co.jp
◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆

--------------------------------------------------------------------------------
                              このメールマガジンは、
                        インターネットの本屋さん『まぐまぐ』
                  http://www.mag2.com/ (マガジンID:  0000073164)
                      総合メールマガジンポータルサイト melma!
                   http://www.melma.com/ (マガジンID: m00048716)
                            を利用して発行しています。
--------------------------------------------------------------------------------

┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
        登録/解除の方法
        http://www.kei-ha.co.jp/mag.html
       「(秘)JavaServlet技法」は 上記URLよりいつでも登録/解除可能です。
        メルマガについてのご意見・ご質問等はこちらまで  mag@kei-ha.co.jp
┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
                           Copyright(C) 2001 Kei Corporation All Right Reserved
〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓

規約に同意してこのメルマガに登録/解除する

メルマガ情報

創刊日:2001-10-02  
最終発行日:  
発行周期:毎週月曜発行  
Score!: - 点   

コメント一覧コメントを書く

この記事にコメントを書く

上の画像で表示されている文字を半角英数で入力してください。

※コメントの内容はこのページに公開されます。発行者さんだけが閲覧できるものではありません。 コメントの投稿時は投稿者規約への同意が必要です。

  • コメントはありません。