- PR -

フレーム化したJSPからのrequestについて

1
投稿者投稿内容
ringo
会議室デビュー日: 2006/05/12
投稿数: 16
投稿日時: 2006-06-08 13:52
いつも参考にさせていただいております。

実は昨日誤って同名の質問をDBスレに挙げてしまい、そちらではjsp配置等の階層を
理解していない為発生している問題ではないか?というご指摘をいただいたので
階層周りも一応一通りWeb等を参照して考えてみたのですが、
project
 + webapp
   + image
   + jsp
このような階層のjspフォルダのなかにすべてのjspファイルを保存しているので
呼ぶファイルが変わった場合、サーブレット等の呼び出し階層が変わることは
無い?という理解しか出来ず、凝りもせずまた同じ質問をコチラに挙げさせていただきました。
元スレは( http://www.atmarkit.co.jp/bbs/phpBB/viewtopic.php?topic=31146&forum=26&1 )です。



2つにフレーム分けしてあるうちの1つのjspからServletに要求を投げると
ちゃんと呼ばれない、という事象が発生しており、悩んでいます。

LoginServlet.java
Login.jsp
ListFrame.jsp
 + list_menu.jsp
 + list_body.jsp
Welcome.jsp


主要機能としては上記6つのファイルから成り立っており、
http://localhost:8080/project/LoginServlet
にアクセスすると
@ログイン画面を表示する
A「ログイン」ボタンを押すとListFrame.jspを表示する
BListFrameで表示されているList_body.jspから、「next」ボタンを押すとWelcome画面に遷移

簡単に言うと上記のような処理をさせたいのですが、
Bのnextボタンを押下すると、画面に

The requested resource (/project/jsp/LoginServlet) is not available.

というエラーが表示されます。
Systemログは出ていません。
また、Jspファイルはすべて同じ階層においています。


試しにAでList_Frameではなく、List_body.jspを直接呼び出すようにすると
画面表示とBのnextボタンの実行まで成功することが分かりました。

そこで、println文を使ってログを出して、何が原因なのか探っていたところ
フレームとなっている List_frame.jspを表示させる時点で、フレーム分けしていない
画面を呼ぶ時とログがすでに違っていることが分かりました。


Jspで表示する処理がどう挟まれるか知りたかったので、 List_body.jsp 側に
<% System.out.println("■■■List_body.jspの処理■■■"); %>
というログを出させるようにしておき、

LoginServlet.javaにも以下のようにログを出すところを作って実行してみました。


【LoginServlet.java】
package loginManager;
import java.io.IOException;
import java.util.Date;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
* LoginServletクラス
*/
public class LoginServlet extends HttpServlet {

  /**
   * service()メソッド
   * クライアントからリクエストがあると、必ず実行されるメソッド
   */
  protected void service(HttpServletRequest request, HttpServletResponse response)
    throws ServletException, IOException {

    RequestDispatcher rd = null;

    //押されたボタン名を取得します。
    String submitValue = request.getParameter("submitValue");
    //ページ名を取得します。
    String pageName = request.getParameter("pageName");
    System.out.println("--- [pageName] =" + pageName);
    System.out.println("--- [submitValue]=" + submitValue);
    

    //初期画面表示
    if (submitValue == null) {
      System.out.println("--- ログイン画面表示");
      rd = this.getServletContext().getRequestDispatcher("/jsp/login.jsp");
    } else {
      //値をエンコーディングします
      //submitValue = new String(submitValue.getBytes("8859_1"), "JISAutoDetect");
      
      //*******リクエストしてきたページがlogin.jspの場合
      if (pageName.equals("login")) {

        System.out.println("--- ログイン画面からの要求");
        //ログインボタンが押された場合        
        if (submitValue.equals("LOGIN")) {
            rd = this.getServletContext().getRequestDispatcher("/jsp/list_frame.jsp");
            //rd = this.getServletContext().getRequestDispatcher("/jsp/list_body.jsp");
          }
          
          System.out.println("★ 表示1");
        }
        System.out.println("★ 表示2");
        
        
      //************** リクエストしてきたページが list_body.jspの場合
      }else if (pageName.equals("list_body")) {

        System.out.println("★★★ list_bodyからの要求");
        System.out.println("★★★ ログイン画面表示するよ");
        rd = this.getServletContext().getRequestDispatcher("/jsp/Welcome.jsp");
        
      }
      System.out.println("★ 表示3");
    }
    System.out.println("★ 表示4");
    System.out.println("--- 画面表示GO!" + rd.toString());
    request.setAttribute("loginbean", loginbean);

    // 画面を表示
    try{
      rd.forward(request, response);
      System.out.println("★ 表示5");
      
    }catch(Exception e){
      System.out.println("★ 画面表示エラー");
      System.out.println("★ " + e.toString());
      System.out.println("★ " + e.getStackTrace());
      e.getStackTrace();
      System.out.println("[LoginServlet]-[service] " + " END");
    }
    System.out.println("★★★ リクエスト処理終了 ★★★");
    System.out.println("[LoginServlet]-[service] " + " END");
    
  }
}


【Aまで実行したときのログの違い】

List_frame.jspを呼んだ場合
★ 表示1
★ 表示2
★ 表示3
★ 表示4
--- 画面表示GO!org.apache.catalina.core.ApplicationDispatcher@1f9338f
★ 表示5
★★★ リクエスト処理終了 ★★★
■■■List_body.jspの処理■■■



List_body.jspを呼んだ場合
★ 表示1
★ 表示2
★ 表示3
★ 表示4
--- 画面表示GO!org.apache.catalina.core.ApplicationDispatcher@1000bcf
■■■List_body.jspの処理■■■
★ 表示5
★★★ リクエスト処理終了 ★★★
[LoginServlet]-[service] END


となっているのです。
フレームを呼ぶとサーブレットとしての処理が完結した後、jspの処理が始まり、
直接List_body.jspを呼ぶと jspの表示処理が終わってからサーブレットに
処理が戻るようになっています。

どなたかご教示いただけますようお願い致します。

長文申し訳ありません。


[ メッセージ編集済み 編集者: ringo 編集日時 2006-06-08 13:58 ]
uk
ぬし
会議室デビュー日: 2003/05/20
投稿数: 1155
お住まい・勤務地: 東京都
投稿日時: 2006-06-08 14:14
引用:

そこで、println文を使ってログを出して、何が原因なのか探っていたところ
フレームとなっている List_frame.jspを表示させる時点で、フレーム分けしていない
画面を呼ぶ時とログがすでに違っていることが分かりました。


そりゃそうでしょう、としかいいようがないですね。
フレーム分けした場合、List_body.jspへのリクエストはList_frame.jspのレスポンスが
戻ってきた後に行われるのに対し、直接呼ぶ場合は、LoginServletからのforward処理で
呼び出されるんですから。

たぶんnextボタンを押した際のアクションの指定に問題があるんだと思います。
List_body.jspのパスからの相対指定となっているのではないですか?
mio
ぬし
会議室デビュー日: 2005/08/25
投稿数: 734
お住まい・勤務地: 神奈川県
投稿日時: 2006-06-08 14:15
>The requested resource (/project/jsp/LoginServlet) is not available.
「/jsp/LoginServlet」というURLをリクエストしているわけで…。
なんで「/jsp/」がくっつくのかは、フレームのソースを見れば分かるはずなんですが。

まずは静的なHTMLだけで同じ構造のものを作って、理解するほうが良いのではないでしょうか。
ringo
会議室デビュー日: 2006/05/12
投稿数: 16
投稿日時: 2006-06-08 14:37
ukさん。
コメントありがとうございます。

フレーム分けしたコードを表示したときのログの違いがやっと分かりました。
ここの時点で既に不具合があったからログが変化したというわけではなかったのですね。
ありがとう御座います。

nextボタンを押した際のアクションですが、
LoginServletでリクエストを受け、添付したLoginServlet.java(72)の
rd = this.getServletContext().getRequestDispatcher("/jsp/Welcome.jsp");
と実行してくれていると思っているのですが、ここのパス("/jsp/Welcome.jsp")が問題
なのでしょうか?・・・ ってもちろん試してみましたが結果は同じでした。(こんなんですみません。)
フレーム分けしているソースだと、他の箇所の getRequestDispatcherでの指定と同じだと
いけないのでしょうか?


mioさん。
いつも本当にありがとう御座います。


HTMLで希望の形を作ってからJSPに直しているんですが・・・
Jspに直すときに変なことしているのかもしれません。
なぜこんなつまづきばかりなのか本当に凹みます。
申し訳ないです。

エラーを発見する為に、処理を極力少なくして試してみています。
やはり、、、変でしょうか?

【List_frame.jsp】
<%@page contentType="text/html; charset=SJIS" %>
<jsp:useBean id="loginworker" class="loginManager.LoginWorker" scope="request"/>
<HTML>
<!-- ■■■■■ タイトル -->
<CENTER><TITLE>履歴表示画面</TITLE></CENTER>

<FRAMESET COLS="150,*" border="1" bordercolor="#c2d3e2" noresize>
  <FRAME SRC="jsp/list_menu.jsp" NAME = "LIST_MENU">
  <FRAME SRC="jsp/list_body.jsp" NAME = "LIST_BODY">
</FRAMESET>

</HTML>


【List_body.jsp】
<%@page contentType="text/html; charset=SJIS" %>
<jsp:useBean id="loginworker" class="loginManager.LoginWorker" scope="request"/>

<html>
  <body>
    <form name="form" action="LoginServlet" method="post">
      <%
      System.out.println("■■■List_body.jspの処理■■■");
      }%>
      <input type="submit" name="submitValue" value="next">
      <%-- ページ名をHiddenで持ちます --%>
      <input type="hidden" name="pageName" value="list_body">
    </form>
  </body>
</html>


【Welcome.jsp】
<%@page contentType="text/html; charset=SJIS" %>
<html>
  <body>
    <h1>Welcome!</h1>
  </body>
</html>
 
uk
ぬし
会議室デビュー日: 2003/05/20
投稿数: 1155
お住まい・勤務地: 東京都
投稿日時: 2006-06-08 17:15
前の書き込みのとおり、フォームアクションのパス指定の問題です。
フレームを使わない場合は、アドレスバーに表示されているとおりLoginServletからの
相対パスとなっており、フレームの場合は、Frame_body.jspからの相対パスになって
いるだけです。

対応としては、絶対パス指定にするのが簡単でしょう。
HttpServletRequest#getContextPathから取得したコンテキストルートからパス指定を
すればいいでしょう。
mio
ぬし
会議室デビュー日: 2005/08/25
投稿数: 734
お住まい・勤務地: 神奈川県
投稿日時: 2006-06-08 18:10
>HTMLで希望の形を作ってからJSPに直しているんですが・・・
「フレームを表示してみる」という意味じゃないんですが(^_^;。
各コンテンツをそれぞれの階層に置いて、きちんと表示して遷移までできることを確認しているんでしょうか?
リクエストされるURL(今回の場合、ukさんが書かれているようにformのactionから作られる絶対パス)は、サーブレットやjspだからという話ではないんですが。

直接は関係ないんですが、フレームの中だけLoginServletへ遷移していいんでしょうか?
ringo
会議室デビュー日: 2006/05/12
投稿数: 16
投稿日時: 2006-06-09 10:58
ukさん、mioさん。
ご教示ありがとうございます。

ukさん。
ご指摘いただいた"フォームアクションのパス指定"を
Servletで行っているgetRequestDispatcherに指定するパスのことだと
勘違いしておりました。jspで指定するform文のactionに指定する
Servletのパスのことだったのですね。

対策のご教示ありがとう御座います。
不勉強なもので getContextPath というメソッドすら知りませんでした。
API等で調べて、早速動作している部分に組み込んでどのようなパス表示
になっているか取得し、jspのaction部分に加えました。
getContextPath で取得した結果が "/project" だったので

<FORM name="form" action="/project/LoginServlet" method="post">

このように修正したところ、フレームからのリクエストがきちんと
実行されるようになりました。
ありがとうございました。


mioさん。
>「フレームを表示してみる」という意味じゃないんですが(^_^;。
すみません。m(_ _;;;m
HTMLではフレーム表示してみているだけでした。
actionに記述するのはサーブレットのクラス名だけでよいと考えていたことと、
フレームになっていないjspからのリクエストはactionにサーブレットのクラス名
のみでcallされているようだったのでそこに階層等が必要とは思っていませんでした。

また、フレームの中だけ遷移してもよいか?というご指摘に関してですが、
最終的にはbody部分に表示したいjspを作成して表示するつもりだったのですが、
それがうまくいかなかったのでまずは動作するjspを表示させてみようという
試みを行っておりました。現在は、上記対応を行い表示させたいjspを
フレーム内に表示できるようになりました。ありがとうございます。

これからは汎用性等考えて、すべて絶対パスで記述したほうが良いですね。
そのように変更します。
ご教示、本当にありがとうございました。
1

スキルアップ/キャリアアップ(JOB@IT)