接上篇:JavaWeb-Servlet(三)Servlet的一些細節
在正文之前,補充一點。
-
Servlet與反射
當用戶端發送請求,伺服器接收到請求,根據web.xml中的資訊得到要響應的servlet類,這時得到的是一個類名的字元串,是以要利用反射來完成後續的工作。
ServletContext
1. ServletContext概述
伺服器會為每個應用建立一個ServletContext 對象::
- ServletContext 對象的建立是在伺服器啟動時完成的;
- ServletContext 對象的銷毀是在伺服器關閉時完成的。
一個項目隻有一個ServletContext對象!
ServletContext對象的作用是在整個Web應用的動态資源之間共享資料!例如在AServlet 中向ServletContext對象中儲存一個值, 然後在BServlet中就可以擷取這個值,這就是共享資料了。
2.擷取ServletContext
在Servlet中擷取ServletContext 對象:
- 在void init(ServletConfig config)中:
,ServletContext context =config.getServletContext()
- ServletConfig類的
方法可以用來擷取ServletContext 對象。getServletContext()
在GenericServlet或HttpServlet中擷取ServletContext對象:
- GenericServlet類有
方法 ,是以可以直接使用getServletContext()
來擷取。this.getServletContext()
3.域對象的功能
ServletContext是JavaWeb四大域對象之一。
- PageContext;
- ServletRequest;
- HttpSession;
- ServletContext;
所有域對象都有存取資料的功能,因為域對象内部有一個Map,用來存儲資料,下面是ServletContext對象用來操作資料的方法:
-
:用來存儲一個對象,也可以稱之為存儲一個域屬性,例如:void setAttribute(String name, Object value)
,在ServletContext中儲存了一個域屬性,域屬性名稱為xxx,域屬性的值為XXX。請注意,如果多次調用該方法,并且使用相同的name,那麼會覆寫上一次的值,這一特性與Map相同。servletContetxtAttribute("xxx", “XXX")
-
:用來擷取ServletContext中的資料,目前在擷取之前需要先去存儲才行,例如:Object gettribute(String name)
,擷取名為xxx的域屬性;String value = (String)servletContextAttribute("xxx");
-
:用來移除ServletContext中的域屬性,如果參數name指定的域屬性不存在,那麼本方法什麼都不做;void removeAttribute(String name)
-
:擷取所有域屬性的名稱。Enumeration getAttributeNames()
4.擷取應用初始化參數
Servlet也可以擷取初始化參數,但它是局部的參數;也就是說,一個servlet隻能擷取自己的初始化參數,不能擷取别人的,即初始化參數隻為一個Servlet準備。
還可以使用ServletContext來擷取在web.xml檔案中配置的應用初始化參數,即配置公共的初始化參數,為所有Servlet而用。
配置格式
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
......
<context-param>
<param-name>name1</param-name>
<param-value>value1</param-value>
</context-param>
<context-param>
<param-name>name2</param-name>
<param-value>value2</param-value>
</context-param>
......
</web-app>
示例
public class AServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
/*
* 1.得到ServletContext
* 2.調用它的getInitParameter(String name)方法得到初始化參數
*/
ServletContext context = this.getServletContext();
String initParameter = context.getInitParameter("name1");
System.out.println(initParameter);
}
}
5.擷取資源的相關方法

1) 擷取真實路徑
還可以使用ServletContext對象來擷取Web應用下的資源,例如在應用的根目錄下建立a.txt檔案,現在想在Servlet中擷取這個資源,就可以使用ServletContext來擷取。
- 擷取a.txt的真實路徑:
, realPath的值為a.txt檔案的絕對路徑: F:\tomcat7\webapps\hello\a.txtString realPath = servletContext.getRealPath("/a.txt");
- 擷取b.txt的真實路徑:
String realPath= servletContext.getRealPath("/WEB-INF/b.txt");
2) 擷取資源流
不隻可以擷取資源的路徑,還可以通過ServletContext擷取資源流,即把資源以輸入流的方式擷取:
- 擷取a.txt資源流:
InputStream in= servletContext.getResourceAsStream("a.txt");
- 擷取b.txt資源流:
InputStream in= servletContext.getResourceAsStream("/WEB-INF/b.txt");
3) 擷取指定目錄下所有資源路徑
還可以使用ServletContext 擷取指定目錄下所有資源路徑,例如擷取/WEB-INF下所有資源的路徑:
ServletContext context = this.getServletContext();
Set set = context.getResourcePaths("/WEB-INF");
System.out.println(set);
注意!這個方法必須以“/”開頭!
輸出:
6.案例:通路量統計
一個項目中所有的資源通路都要對通路量進行了累加!
建立一個int類型的變量,用來儲存通路量,然後儲存到ServletContext的域中,這樣可以讓所有的Servlet都可以通路到。
- 最初,ServletContext中沒有通路量相關的屬性,
- 當本站第一次被通路的時候,建立一個變量,設定其值為1,儲存到ServletContext中;
- 當以後的通路時,就可以從ServletContext中擷取這個變量,然後在其基礎之上加1。
public class AServlet extends HttpServlet {
/**
* 統計網站通路量
*/
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// 擷取ServletContext對象
ServletContext servletContext = this.getServletContext();
// 從ServletContext對象中擷取名為count的屬性
Integer count = (Integer) servletContext.getAttribute("count");
// 如果存在,給通路量加1,然後儲存回去
// 如果不存在,說明是第一次通路。向ServletContext中儲存名為count的屬性,值為1
if (count == null) {
servletContext.setAttribute("count", 1);
} else {
servletContext.setAttribute("count", count + 1);
}
// 向浏覽器輸出:需要使用響應對象
PrintWriter pw = response.getWriter();
pw.print("<h1>" + servletContext.getAttribute("count") + "</h1>");
}
}
不過伺服器重新開機的話,計數就會被重置。