ServletContext

2.5 Servlet上下文
運行在Java虛擬機中的每個Web應用程序都有一個與之相關的Servlet上下文。Java Servlet API提供了一個ServletContext接口用來表示上下文。在這個接口中定義了一組方法,Servlet可使用這些方法與它的Servlet容器進行通訊,例如,獲得文件的MIME類型,轉發請求,或者向日志文件中寫入日誌消息。
ServletContext對象是Web服務器中的一個已知路徑的根。對於本章的實例,Servlet上下文被定位於http://localhost:8080/ch02。以/ch02請求路徑(稱爲上下文路徑)開始的全部請求被髮送到與此ServletContext關聯的Web應用程序。
Servlet容器提供商負責提供 ServletContext接口的實現。Servlet容器在Web應用程序加載時建立ServletContext對象,做爲Web應用程序的運行時表示,ServletContext對象能夠被Web應用程序中全部的Servlet所訪問。
2.5.1  ServletContext接口
一個ServletContext對象表示了一個 Web應用程序的上下文。Servlet容器在Servlet初始化期間,向其傳遞ServletConfig對象,能夠經過ServletConfig 對象的getServletContext()方法來獲得ServletContext對象。也能夠經過GenericServlet類的 getServletContext()方法獲得ServletContext對象,不過GenericServlet類的 getServletContext()也是調用ServletConfig對象的getServletContext()方法來獲得這個對象的。
ServletContext接口定義了下面的這些方法,Servlet容器提供了這個接口的實現。
Ø public java.lang.Object getAttribute(java.lang.String name)
Ø  public java.util.Enumeration getAttributeNames()
Ø  public void removeAttribute(java.lang.String name)
Ø  public void setAttribute(java.lang.String name, java.lang.Object object)
上面4個方法用於讀取、移除和設置共享屬性,任何一個Servlet均可以設置某個屬性,而同一個Web應用程序的另外一個Servlet能夠讀取這個屬性,無論這些Servlet是否爲同一個客戶進行服務。
Ø  public ServletContext getContext(java.lang.String uripath)
該方法返回服務器上與指定的URL相對應的 ServletContext對象。給出的uripath參數必須以斜槓(/)開始,被解釋爲相對於服務器文檔根的路徑。出於安全方面的考慮,若是調用該方法訪問一個受限制的ServletContext對象,那麼該方法將返回null。
Ø  public String getContextPath()
該方法是在Servlet 2.5規範中新增的,用於返回Web應用程序的上下文路徑。上下文路徑老是以斜槓(/)開頭,但結束沒有斜槓(/)。在默認(根)上下文中,這個方法返回空字符串""。
Ø  public java.lang.String getInitParameter(java.lang.String name)
Ø  public java.util.Enumeration getInitParameterNames()
能夠爲Servlet上下文定義初始化參數,這些參數被整個Web應用程序所使用。能夠在部署描述符(web.xml)中使用<context-param>元素來定義上下文的初始化參數,上面兩個方法用於訪問這些參數。
Ø  public int getMajorVersion()
Ø  public int getMinorVersion()
上面兩個方法用於返回Servlet容器支持的Java Servlet API的主版本和次版本號。例如,對於聽從Servlet 2.4版本的容器,getMajorVersion()方法返回2,getMinorVersion()方法返回4。
Ø  public java.lang.String getMimeType(java.lang.String file)
該方法返回指定文件的MIME類型,若是類型是未知的,這個方法將返回null。MIME類型的檢測是根據Servlet容器的配置,也能夠在Web應用程序的部署描述符中指定。
Ø  public RequestDispatcher getRequestDispatcher(java.lang.String path)
該方法返回一個RequestDispatcher 對象,做爲指定路徑上的資源的封裝。可使用RequestDispatcher對象將一個請求轉發(forward)給其餘資源進行處理,或者在響應中包含(include)資源。要注意的是,傳入的參數path必須以斜槓(/)開始,被解釋爲相對於當前上下文根(context root)的路徑。
Ø  public RequestDispatcher getNamedDispatcher(java.lang.String name)
該方法與getRequestDispatcher()方法相似。不一樣之處在於,該方法接受一個在部署描述符中以<servlet-name>元素給出的Servlet(或JSP頁面)的名字做爲參數。
Ø  public java.lang.String getRealPath(java.lang.String path)
在一個Web應用程序中,資源用相對於上下文路徑的路徑來引用,這個方法能夠返回資源在服務器文件系統上的真實路徑(文件的絕對路徑)。返回的真實路徑的格式應該適合於運行這個Servlet容器的計算機和操做系統(包括正確的路徑分隔符)。若是Servlet容器不可以將虛擬路徑轉換爲真實的路徑,這個方法將會返回null。
Ø  public java.net.URL getResource(java.lang.String path) throws java.net.Malformed URLException
該方法返回被映射到指定路徑上的資源的URL。傳入的參數path必須以斜槓(/)開始,被解釋爲相對於當前上下文根(context root)的路徑。這個方法容許Servlet容器從任何來源爲Servlet生成一個可用的資源。資源能夠是在本地或遠程文件系統上,在數據庫中,或者在WAR文件中。若是沒有資源映射到指定的路徑上,該方法將返回null。
Ø  public java.io.InputStream getResourceAsStream(java.lang.String path)
該方法與getResource()方法相似,不一樣之處在於,該方法返回資源的輸入流對象。另外,使用getResourceAsStream()方法,元信息(如內容長度和內容類型)將丟失,而使用getResource()方法,元信息是可用的。
Ø  public java.util.Set getResourcePaths(java.lang.String path)
該方法返回資源的路徑列表,參數path必須以斜槓(/)開始,指定用於匹配資源的部分路徑。例如,一個Web應用程序包含了下列資源:
—  /welcome.html
—  /catalog/index.html
—  /catalog/products.html
—  /catalog/offers/books.html
—  /catalog/offers/music.html
—  /customer/login.jsp
—  /WEB-INF/web.xml
— /WEB-INF/classes/com.acme.OrderServlet.class
若是調用 getResourcePaths("/"),將返回[/welcome.html, /catalog/, /customer/, /WEB-INF/]。若是調用getResourcePaths("/catalog/"),將返回[/catalog/index.html, /catalog/products.html, /catalog/offers/]。
Ø  public java.lang.String getServerInfo()
該方法返回運行Servlet的容器的名稱和版本。
Ø  public java.lang.String getServletContextName()
該方法返回在部署描述符中使用<display-name>元素指定的對應於當前ServletContext的Web應用程序的名稱。
Ø  public void log(java.lang.String msg)
Ø  public void log(java.lang.String message, java.lang.Throwable throwable)
ServletContext接口提供了上面兩個記錄日誌的方法,第一個方法用於記錄通常的日誌,第二個方法用於記錄指定異常的棧跟蹤信息。

2.5.2  頁面訪問量統計實例
有時候,咱們可能須要統計Web站點上的一個特定頁面的訪問次數,考慮這樣一個場景,你爲了宣傳一個產品,在某個門戶網站花錢作了一個連接,你但願知道產品頁面天天的訪問量,藉此瞭解廣告的效果。要完成上述功能,可使用ServletContext對象來保存訪問的次數。咱們知道一個Web應用程序只有一個ServletContext對象,並且該對象能夠被Web應用程序中的全部Servlet所訪問,所以使用ServletContext對象來保存一些須要在Web應用程序中共享的信息是再合適不過了。
要在ServletContext對象中保存共享信息,能夠調用該對象的setAttribute()方法,要獲取共享信息,能夠調用該對象的getAttribute()方法。針對本例,咱們能夠調用 setAttribute()方法將訪問計數保存到上下文對象中,新增一次訪問時,調用getAttribute()方法從上下文對象中取出訪問計數加 1,而後再調用setAttribute()方法保存回上下文對象中。這個實例的開發主要有下列步驟
Step1:編寫CounterServlet類
在%CATALINA_HOME%\webapps\ch02\src目錄下新建CounterServlet.java,代碼如例2-14所示。
package servlet;

import java.io.IOException;
import java.io.PrintWriter;

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

public class CounterServlet extends HttpServlet

{
  @Override
   public void doGet(HttpServletRequest request, HttpServletResponse response)
       throws ServletException, IOException
  {
    ServletContext context = getServletContext();
    Integer count = null;
     synchronized (context)
    {
      count = (Integer) context.getAttribute( "counter");
       if ( null == count)
      {
        count = new Integer(1);
      }
       else
      {
        count = new Integer(count.intValue() + 1);
      }
      context.setAttribute( "counter", count);

    }
    response.setContentType( "text/html;charset=gb2312");
    PrintWriter out = response.getWriter();
    out.println( "<html><head>");
    out.println( "<title>頁面訪問統計</title>");
    out.println( "</head><body>");
    out.println( "該頁面已被訪問了" + "<b>" + count + "</b>" + "次");
    out.println( "</body></html>");
    out.close();
  }

}

在程序代碼的第17行,調用getServletContext()方法(從GenericServlet類間接繼承而來)獲得Web應用程序的上下文對象。爲了不線程安全的問題,咱們在第19行使用synchronized關鍵字對context對象進行同步。第21行,調用上下文對象的getAttribute()方法獲取counter屬性的值。第21~29行,判斷count是否爲null,若是爲null,則將它的初始值設爲1。當這個Servlet第一次被訪問的時候,在上下文對象中尚未保存counter屬性,因此獲取該屬性的值將返回null。若是 count不爲null,則將count加1。第30行,將count做爲counter屬性的值保存到ServletContext對象中。當下一次訪問這個Servlet時,調用getAttribute()方法取出counter屬性的值不爲null,因而執行第28行的代碼,將count加1,此時count爲2,代表頁面被訪問了兩次。
第39行,輸出count,顯示該頁面的訪問次數。
Step2:編譯CounterServlet.java
打開命令提示符,進入%CATALINA_HOME%\webapps\ch02\src目錄,而後執行:
javac -d ..\WEB-INF\classes CounterServlet.java
在WEB-INF\classes\org\sunxin\ch02\servlet目錄中生成類文件CounterServlet.class。
Step3:部署CounterServlet
編輯WEB-INF目錄下的web.xml文件,添加對本例中的Servlet的配置
相關文章
相關標籤/搜索