ServletContext對象
-
問題:
Request解決了一次請求内的資料共享問題,session解決了使用者不同請求的資料共享問題,那麼不同的使用者的資料共享該怎麼辦呢?
-
解決:
使用ServletContext對象
-
作用:
解決了不同使用者的資料共享問題(如目前網頁被浏覽的次數)
-
原理:
ServletContext對象由伺服器進行建立,一個項目隻有一個對象。不管在項目的任意位置進行擷取得到的都是同一個對象,那麼不同使用者發起的請求擷取到的也就是同一個對象了,該對象由使用者共同擁有。
-
特點:
伺服器進行建立
使用者共享
一個項目隻有一個
-
生命周期:
伺服器啟動到伺服器關閉
-
作用域:
項目内
-
使用:
(1)擷取ServletContext對象:三種方式
方式一:(常用)
ServletContext sc = this.getServletContext();
方式二:
ServletContext sc2 = this.getServletConfig().getServletContext();
方式三:(常用)
ServletContext sc3 = req.getSession().getServletContext();
(2)使用ServletContext對象完成資料共享: 使用作用域進行共享資料流轉
資料存儲:sc.setAttribute(name, value)
資料擷取:sc.getAttribute(name)傳回的Object類型
注意:
不同的使用者可以給ServletContext對象進行資料的存取。
擷取的資料不存在傳回null。
(3)擷取web.xml中的全局配置
Web.xml:(配置全局資料):
<context-param>(一個該标簽隻能有一組鍵值對,多個聲明多個該标簽)
<param-name>name</param-name>
<param-value>zhangsan</param-value>
</context-param>
//擷取web.xml全局配置
String names = Sc.getInitParameterNames();//傳回鍵名的枚舉類
String name = Sc.getInitParameter(“name”);//擷取上面全局配置參數, 資料不存在傳回null
作用:将靜态資料和代碼進行解耦;(相當于異地戀)。
(4)擷取MyEcplise中webroot(Eclipse中的webContent檔案夾)下資源絕對路徑
擷取項目根目錄下的資源的絕對路徑:
IO流寫法,固定寫好的:
String path = “D:\\tomcat\webapps\sc\doc\1.txt”;
動态擷取:擷取的目錄是項目根目錄,path參數為項目根目錄中的路徑
String path = sc.getRealPath(String path);
(5)擷取webContent或webroot項目根目錄下資源的流對象
InputStream is = Sc.getResoureAsStream(String path);
注意:
此種方式隻能擷取項目根目錄下的資源流對象,可以取到和WEB-INF統計目錄下的檔案的流對象;
class檔案的流對象需要使用類加載器擷取(不進WEB-INF檔案夾);
編譯好的class檔案不能取到;
案例(ServletContext對象網站計數器)
- 原理:在使用者登入校驗中建立計數器并自增,然後存儲到ServletContext對象中,在首頁面裡取出計數器資料顯示給使用者即可。
-
實作:
第一步:在登入成功的servlet進行重定向之前,建立計數器或計數器加1。
//建立網頁計數器:
//擷取計數資料
ServletContext sc = this.getServletContext();
if( sc.getAttribute(“nums”) != null){
int nums = (int)sc.getAttribute(“nums”);
//計數器自增
nums+=1;
//再次存儲到ServletContext對象中
sc.setAttribute(“nums”, nums);
}else{
sc.setAttribute(“nums”, 1);
}
第二步:在登入成功後繪制頁面的servlet中擷取網頁浏覽次數并顯示
//擷取網頁浏覽次數
int nums = Integer.parseInt(this.getServletContext().getAttribute(“nums”))
response.getWriter().write(“目前網頁浏覽次數為:”+nums)
第三步:在cookie登入校驗三天免登陸的重定向之前網頁計數器也要自增,因為也是一次登入。
int nums = (int)sc.getAttribute(“nums”);
//計數器自增
nums+=1;
//再次存儲到ServletContext對象中
sc.setAttribute(“nums”, nums);
-
問題:
重新開機伺服器,計數器就會重置
-
解決方法:
在webroot(WebContent)下面建立nums檔案夾,建立nums.txt。在網站關閉時,将計數器資訊寫入nums.txt。
-
解決實作:
建立NumServlet,别名:/num
覆寫init初始化方法,将資料讀取到ServletContext對象中
init(){
//擷取檔案中的計數器資料
//擷取檔案路徑
String path = this.getServletContext().getRealPath(“/num/nums.txt”);
//聲明流對象
FileReader fr=null;
BufferedReader br = null;
try{
fr= new FileReader(path);
br = new BufferedReader(fr);
String nums = br.readLine();//第一次啟動時為null,但在之前設定了為null判斷,是以不會出錯
System.out.println(nums)
this. sc.getServletContext().setAttribute(“nums”,nums);
} catch(Exception e){
e.printStackTrace();
}finally{
//下面關閉需要try
fr.close();
br.close();
}
}
覆寫銷毀方法,存儲計數器到檔案中
Destroy(){
//擷取網頁計數器
String num = (String) this.getServletContext().getAttribute(“nums”);
//聲明流對象
BufferedWriter bw = null;
FileWrier fw = null;
//擷取檔案路徑
String path = this.getServletContext().getRealPath(“/num/nums.txt”);
try{
fw = new FileWriter(path);
bw = new BufferedWriter(fw);
bw.write(nums+“”);//将nums轉換為string類型
bw.flush();
}catch(Exception e){
e.printStackTrace();
}finally{
//下面關閉需要try
fw.close();
bw.close();
}
打開web.xml檔案,找到NumServlet,配置<load-on-startup>1</load-on-startup>