サーブレットとJSP ミニTips
サーブレットから他のページへのジャンプ(フォワード)

RequestDispatcher d = getServletContext().getRequestDispatcher("/newpage.html");
d.forward(request, response);

JSPから他のページへのフォワード

<jsp:forward page="/moreinfo.jsp">
<jsp:param name="user" value="guest"/>
</jsp:forward>

JSP文書から別のページにフォワードするには、jsp:forwardタグを使います。 page=の値がジャンプ先ですが、これは必ずスラッシュ(/)で開始します。 URLは そのWebアプリケーションのコンテキスト・ルートからの相対パスになります。
jsp:forwardタグの中にはjsp:paramタグを入れ子にすることができ、 POST変数と同じように扱われるフォーム変数をフォワード先の文書に渡すことができます。
なお、フォワードしてもWebブラウザに表示されるURLは元のままです。

JSPでインクルードするファイルが文字化け
インクルードされるファイルの中に日本語の文字を書いていて、 日本語が??に変換されてしまう場合、インクルードされるファイルにも冒頭に

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

が書いてあるか確認します。 そして、インクルードするファイルに

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

を書けば問題ないと思います。

フォーム変数の日本語化(Tomcat7以前)
Tomcat7以前では、フォーム変数をサーブレットやJSPで受け取ったとき文字列をISO8859-1で解釈しようとするので、 日本語の文字列が正しくUTF-8として取り込まれないことがあります。これを防ぐには、次のような変換をかけます。

String param = request.getParameter("kanjiName");
param = new String(param.getBytes("8859_1"), "Windows-31J");

フォーム変数の日本語化(Tomcat8以降)
…で、Tomcat8以降はこの入力フォームの値、つまりリクエストパラメータを解釈するエンコーディングの初期値、 URIEncodingのデフォルトがISO8859-1からUTF-8に変更されました。 したがってUTF-8で読み取りたいときは何もしなくてよい一方、 上記の変換を掛けていたアプリケーションをTom8以降にそのまま移植すると今度はかえって文字化けしてしまいます。
これを防ぐには?手っ取り早いレガシー延命策は、$CATALINA_HOME/conf/server.xmlを編集して、 Connectorの部分にURIEncodingを指定することです。

<Connector port="8080" protocol="HTTP/1.1" redirectPort="8443"
           URIEncoding="ISO-8859-1" />

ServletFilterをweb.xmlに追加した途端、Servletの冒頭で行っているsetCharacterEncodingが効かず文字化けするようになった
そのFilterの中に、リクエストパラメータを読み出すような処理があるとそれが原因です。 ServletRequest#setCharacterEncoding()のAPIコメントにあるように、 ServletRequest#getReader()より前に実行しないとエンコーディングの設定は効かない(ことがある)ようです。
つまり、リクエストパラメータを読み出すようなFilterを作るなら、 Servletとは別にもう1個setCharacterEncodingを行うFilterを作り、後者を先に実行させる必要があります。

Webサーバ上の名前が日本語のファイルをServletでダウンロードしたい
これは延々悩みます。というのは利用者のフォーム入力を受け取るエンコーディングの設定部分と、 OSのファイルシステム上のファイルをJavaVMが読み取る際のエンコーディングの設定部分を分けて考える必要があるので、 両者を混同してしまうと際限のない迷宮にはまり込んでしまいます。

final String storeDir = "/the/path/of/files";

// 日本語のファイル名を扱う場合、つまり日本語を含むフォームパラメータを受け取る場合必須
request.setCharacterEncoding("UTF-8");

String fileName = request.getParameter("filename");

response.setHeader("Cache-Control", "no-cache");
response.setHeader("Pragma", "no-cache");
response.setContentType("application/octet-stream");

// ダウンロードファイル名。日本語はエンコードが必須
response.setHeader("Content-Disposition", " attachment; filename=\""
  + URLEncoder.encode(fileName, "UTF-8") + "\"");

ServletOutputStream os = response.getOutputStream();

FileInputStream fis = new FileInputStream(storeDir + "/" + fileName);
byte[] buffer = new byte[4096];
int bytesRead = -1;

while ((bytesRead = fis.read(buffer)) != -1) {
    os.write(buffer, 0, bytesRead);
}
fis.close();
// ServletOutputStreamもcloseして良い。というかしないと駄目
os.close();

ポインツ(複数形)はコメントにある3個所です。まずその日本語を含むファイル名をフォーム入力データから受け取る場合、 そのエンコーディングを、Tomcatが動くJavaVMがOSのファイルシステムから日本語のファイル名を読み取るエンコーディングと一致させる必要がある点。 次にそれをダウンロードダイアログにデフォルトファイル名として表示する場合今度はURLEncoderによるエンコードが必要になる点。 さらに日本語名のファイルに限りませんがファイルをダウンロードさせたらServletOutputStreamをcloseする必要がある点。 どれも分かりにくいですね。

WEB-INF以外にHTTP直アクセスを禁止するディレクトリを作る

<security-constraint>
    <web-resource-collection>
        <web-resource-name>Restricted Resources</web-resource-name>
        <url-pattern>/data/*</url-pattern>
    </web-resource-collection>
    <auth-constraint />
</security-constraint>

例えばWebアプリケーションapp1があるとき、app1/WEB-INF ディレクトリはデフォルトでHTTP直アクセスが禁止されます。
これに加えて、同様に直アクセスさせないディレクトリを作るには、web.xmlに上のように記述します。 この例では app1/data ディレクトリ内のファイルには直アクセスを禁止しています。

サーブレットのリクエストパスからローカルファイルのパスを得る
サーブレットコンテナの設定により、特定の拡張子やパターンを持つ複数のリクエストパスに対し、 同じサーブレットを起動できます。 その場合に呼び出されたサーブレットから、元のリクエストパスを知るには次のようなコードを使います。

String svPath   = request.getServletPath();
String realPath = getServletContext().getRealPath(svPath);

WebアプリケーションのコンテキストルートのWebサーバ上のパスを得る
同様に次のようにできます。

String docBase = request.getServletContext().getRealPath("/");

Windowsの機種依存文字が文字化け
UNIXやインターネットでは行儀悪いとか言われますが、 業務システムではどうしても丸囲み数字やローマ数字などの機種依存文字をユーザが使ってしまうもの。 それらに対応するにはContent-typeとpageEncodingを "Shift_JIS" ではなく、"Windows-31J" とします。

Webアプリケーション(ServletContext)にパラメータを渡したい
サーブレットやJSPにweb.xmlのinit-paramタグで初期化パラメータが渡せるように、 Webアプリケーション全体で共有できる、つまりServletContextに記憶させることができる初期化パラメータもあります。 これはweb.xmlに書くcontext-paramというタグを次のように使います。

<context-param>
  <param-name>setup.file.path</param-name>
  <param-value>/WEB-INF/setup.xml</param-value>
</context-param>

これで、サーブレットやリスナー(ServletContextListener)の中から、 getServletContext().getInitParameter("setup.file.path")メソッドを使えば、 "/WEB-INF/setup.xml" が得られます。

古いJSPの引用符に関するエラーを防止する
Tomcat5よりも前の時代に作られたJSPを新しいTomcatで動かそうとすると 「*** is quoted with " which must be escaped when used within the value」 というエラーが出ることがあります。典型的には、

<jsp:setProperty ...(略)... value="<%=request.getParameter("name")%>"/>

このように書かれている場合で、新しいJSPで次のように一重引用符にしないといけません。

<jsp:setProperty ...(略)... value='<%=request.getParameter("name")%>'/>

けど修正が大変な場合は、WEB-INF/web.xmlのServlet=jspにパラメータstrictQuoteEscapingを値falseで定義すればOKです。

<servlet>
  <servlet-name>jsp</servlet-name>
  <servlet-class>org.apache.jasper.servlet.JspServlet</servlet-class>
...
...
  <init-param>
    <param-name>strictQuoteEscaping</param-name>
    <param-value>false</param-value>
  </init-param>
</servlet>

ちなみに、アプリケーションによってはweb.xmlに最初からjspという名前のServletを定義してないこともあると思います。 その場合は、上の記述部分全体を追記します。

セッションのタイムアウト時間を設定する
web.xmlのsession-timeoutタグで、デフォルトの30分を変更できます。単位は分です。

<session-config>
  <session-timeout>60</session-timeout>
</session-config>

welcomeページを表示する
welcomeページとは、ディレクトリを指すURLにアクセスされた際に、 代わりに表示するページのことです。これも、web.xmlで指定できます。

<welcome-file-list>
  <welcome-file>login.jsp</welcome-file>
  <welcome-file>../login.jsp</welcome-file>
</welcome-file-list>

このように、複数指定する理由は?
1つ下の階層のディレクトリに直接アクセスされた場合も効くようにするためです。

HttpServletRequest.setAttribute()で設定した情報は、フレームのページでは見れない?
フレームは、下地となるページをHTTPサーバが送り出した後、 各フレームのページを個別にHTTPサーバが送信することで実現されています。 つまり、request.setAttribute()の情報は下地となるページを送り出した時に終わりとなるので、 各フレームの個別のページでは参照できません。
各フレームの個別のページで情報を見れるようにする最も簡単な方法は? requestの代わりにHttpSession.setAttribute()でセッションに格納することですね。

web.xmlのタグの順序早見表
DTDにはこのように書かれていますね。

<!ELEMENT web-app (icon?, display-name?, description?, distributable?,
context-param*, filter*, filter-mapping*, listener*, servlet*,
servlet-mapping*, session-config?, mime-mapping*, welcome-file-list?,
error-page*, taglib*, resource-env-ref*, resource-ref*, security-constraint*,
login-config?, security-role*, env-entry*, ejb-ref*,  ejb-local-ref*)>

Server Side Java Index Top

(first uploaded 2002/01/19 last updated 2025/07/27, URANO398)