Javaサーブレットのスコープについてもっと理解するために、アクセスカウンターを作成してみましょう。
counter.java
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
public class counter extends HttpServlet {
public void service(HttpServletRequest req,HttpServletResponse res) throws ServletException, IOException {
res.setContentType("text/html; charset=EUC-JP");
//アプリケーションスコープから属性"count"をget
//返り値はObject型なのでObject型→String型→int型に変換が必要
Object count=getServletContext().getAttribute("strCnt");
int counti;
if(count==null){
counti=0;
}else{
counti=Integer.parseInt((String)count);
}
//setAttributeの引数はObject型なのでint型は格納できない
String counts=Integer.toString(++counti);
//アプリケーションスコープに"counti"をset
getServletContext().setAttribute("strCnt",counts);
PrintWriter out = res.getWriter();
out.println("かうんたー:");
out.println(counti+"<br>\n");
}
}
|
一番意味のわからない型変換は気にしないとして、リロードすると値が増えていきます。
別のPCからアクセスしてもカウンターの値は共通しています。
ファイルに保存していないカウンターの値が何故保持されるのか、それはJavaサーブレットの動作方法に理由があります。
HTTPやPerlといった旧来のWebコンテンツはサーバ上で常に待機しているわけではなく、リクエストがあった場合にサーバから呼び出され、プログラムを実行するなりHTMLファイルを返すなりしたらそのまま終了してしまいます。
プログラムを終了してしまうのですから、それまでメモリ上にあった値はすべて破棄されます。
必要な情報はファイルやDB等に保存しなければなりません。
それに対しJavaやPHPといった最近のWebコンテンツは、サーバ上で常駐し、リクエストがあると常駐しているプログラム内部で処理を行います。
プログラムを終了しないので、メモリ上の値はずっと保存されます。
中でも特に、アクセスしてきた者全員で共有できるスコープをアプリケーションスコープといいます。
web.xmlでは<context-param>で、JavaサーブレットではServletContextで、JSPではapplicationで、ELではapplicationScopeとinitParamでアクセスすることができます。
JSPやELについてはまたそのうち。
アプリケーションスコープに突っ込むだけで簡単に情報を共有できるので、ファイルに保存せずに掲示板等が作成できてしまいます。
bbs.java
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
public class bbs extends HttpServlet {
public void service(HttpServletRequest req,HttpServletResponse res) throws ServletException, IOException {
res.setContentType("text/html; charset=UTF-8");
//アプリケーションスコープから属性"bbsData"をget
String bbsData=(String)getServletContext().getAttribute("bbsData");
//フォーム内容を取得
req.setCharacterEncoding("UTF-8");
String strFormData = req.getParameter("strFormData");
//フォームが空でなければ追加
if(strFormData!="" && strFormData!=null){
strFormData = strFormData.replaceAll("&","&");
strFormData = strFormData.replaceAll("<","<");
strFormData = strFormData.replaceAll(">",">");
strFormData = strFormData.replaceAll("\"",""");
strFormData = strFormData.replaceAll("'","'");
bbsData=bbsData+"<hr>"+strFormData;
}
//アプリケーションスコープに"bbsData"をset
getServletContext().setAttribute("bbsData",bbsData);
PrintWriter out = res.getWriter();
out.println("<form method='POST' action='"+req.getRequestURI()+"'>" +
"内容<input type='text' name='strFormData'>" +
"<input type='submit' value='送信'><hr>");
out.println(bbsData);
}
}
|
サニタイジングとぬるぽ対策以外は何もやっていない非常にいい加減な、とりあえず動けばいい掲示板です。
サーバの再起動等があると当然メモリ上のデータもすべて消えてしまいます。
簡易チャット程度ならいいですが、長期にわたりログを保存する場合は、やはりストレージに記憶することになるでしょう。
次回はリスナーについて、はどうせ使わないからいいか。フィルタの話でもしましょうか。
PR