[Servlet]研究ServletContext對象

作者信息
作者姓名:金雲龍
個人網站:http://www.longestory.com
個人公衆帳號:搜索“longestory”或“龍哥有話說

ServletContext概述

ServletContext對象是Servlet三大域對象之一,每個Web應用程序都擁有一個ServletContext對象,該對象是Web應用程序的全局對象或者上下文。Tomcat服務器在啓動時,會自動創建一個ServletContext對象,在關閉時,會自動銷燬這個ServletContext對象。每個Web應用程序只擁有一個ServletContext對象,ServletContext對象可以在整個Web應用中共享數據資源。

下列是ServletContext提供的方法列表:

Method Summary
Object getAttribute(String name)
Enumeration getAttributeNames()
String getInitParameter(String name)
Enumeration getInitParameterNames()
String getMimeType(String file)
String getRealPath(String path)
String getServletContextName()
Enumeration getServletNames()
void log(String msg)
void removeAttribute(String name)
void setAttribute(String name, Object object)

獲取ServletContext對象

在自定義Servlet中有以下幾種方式獲取到ServletContext對象:

  • 通過ServletConfig對象的getServletContext()方法獲取。
  • 通過繼承GenericServlet類或HttpServlet類,調用GenericServlet類或HttpServlet類的getServletContext()方法獲取。

我們通過一個案例來討論一下。

  • 首先,創建一個自定義Servlet,用來獲取ServletContext對象。
public class AServlet extends GenericServlet {
    @Override
    public void service(ServletRequest req, ServletResponse res)
            throws ServletException, IOException {
        ServletConfig config = getServletConfig();
        ServletContext context1 = config.getServletContext();
        context1.log("這是通過ServletConfig對象獲取到的ServletContext對象.");
        ServletContext context2 = getServletContext();
        context2.log("這是通過繼承GenericServlet類獲取到的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">
  <servlet>
    <servlet-name>AServlet</servlet-name>
    <servlet-class>app.java.context.AServlet</servlet-class>
  </servlet>
  <servlet-mapping>
    <servlet-name>AServlet</servlet-name>
    <url-pattern>/servlet/AServlet</url-pattern>
  </servlet-mapping>
</web-app>

這裏寫圖片描述

  • 通過ServletContext對象的log(Stirng msg)方法,可以向控制檯打印信息。

配置全局初始化參數

在web.xml文件中,使用定義的初始化參數,只能在當前Servlet中使用,而其他Servlet是無權限訪問當前Servlet下配置的初始化參數的。而可以使用ServletContext在web.xml文件中配置全局初始化參數,這樣當前Web應用程序中的所有Servlet都可以訪問。

  • 在web.xml文件中使用<context-param>來定義全局初始化參數。
<?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>weixin</param-name>
    <param-value>longestory</param-value>
  </context-param>
  <servlet>
    <servlet-name>AServlet</servlet-name>
    <servlet-class>app.java.context.AServlet</servlet-class>
  </servlet>
  <servlet-mapping>
    <servlet-name>AServlet</servlet-name>
    <url-pattern>/servlet/AServlet</url-pattern>
  </servlet-mapping>
  <servlet>
    <servlet-name>BServlet</servlet-name>
    <servlet-class>app.java.context.BServlet</servlet-class>
  </servlet>
  <servlet-mapping>
    <servlet-name>BServlet</servlet-name>
    <url-pattern>/servlet/BServlet</url-pattern>
  </servlet-mapping>
</web-app>
  • 在兩個自定義Servlet中,分別利用ServletContext對象獲取全局初始化參數。
public class BServlet extends GenericServlet {
    @Override
    public void service(ServletRequest req, ServletResponse res)
            throws ServletException, IOException {
        ServletContext context = getServletContext();

        String weixin = context.getInitParameter("weixin");
        System.out.println(weixin);
    }
}

在自定義Servlet中,可以通過ServletContext對象的getInitParameter(String name)方法獲取對應參數名稱的全局初始化參數值,也可以通過ServletContext對象的getInitParameterNames()方法獲取所有全局初始化參數的名稱。

還可以通過ServletContext對象的getMineType(String file)方法根據文件擴展名獲取文件MIME類型。

public class BServlet extends GenericServlet {
    @Override
    public void service(ServletRequest req, ServletResponse res)
            throws ServletException, IOException {
        ServletContext context = getServletContext();

        String html = context.getMimeType("1.html");
        String css = context.getMimeType("2.css");
        String javascript = context.getMimeType("3.js");
        System.out.println("HTML的文件類型爲"+html+", CSS的文件類型爲"+css+", javascript的文件類型爲"+javascript);
    }
}

發佈Web應用程序,並啓動Tomcat服務器,在控制檯中打印:

HTML的擴展名爲text/html, CSS的擴展名爲text/css, javascript的擴展名爲application/javascript

ServletContext對象的getMineType(String file)方法會自動讀取Tomcat安裝目錄中conf目錄中的web.xml文件。

<?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">
    <mime-mapping>
        <extension>html</extension>
        <mime-type>text/html</mime-type>
</mime-mapping>
<mime-mapping>
    <extension>css</extension>
    <mime-type>text/css</mime-type>
</mime-mapping>
    <mime-mapping>
        <extension>js</extension>
        <mime-type>application/javascript</mime-type>
</mime-mapping>
</web-app>

多個Servlet共享數據

在同一個Web應用程序中,多個Servlet之間可以共享ServletContext對象中的數據信息。主要是通過ServletContext對象的setAttribute(String name, Object object)方法和getAttribute(String name)方法完成,下面我們來實現統計網站訪問次數的案例。

  • 創建一個VisitServlet用來獲取訪問次數,並存儲在ServletContext對象中。
public class VisitServlet extends HttpServlet {
    @Override
    public void init() throws ServletException {
        ServletContext context = getServletContext();
        context.setAttribute("times", 0);
    }
    public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        ServletContext context = getServletContext();

        int times = (Integer)context.getAttribute("times");
        times ++;
        context.setAttribute("times", times);
    }
    public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }
}
  • 創建一個ShowTimeServlet用來顯示訪問次數。
public class ShowTimeServlet extends HttpServlet {
    public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        ServletContext context = getServletContext();

        int times = (Integer)context.getAttribute("times");

        response.setContentType("text/html;charset=utf-8");
        PrintWriter out = response.getWriter();
        out.println("<h1>VisitServlet共被訪問了"+times+"次</h1>");
    }
    public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }
}
  • 配置web.xml文件中有關Servlet信息。
<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">
  <servlet>
    <servlet-name>VisitServlet</servlet-name>
    <servlet-class>app.java.context.VisitServlet</servlet-class>
  </servlet>
  <servlet>
    <servlet-name>ShowTimeServlet</servlet-name>
    <servlet-class>app.java.context.ShowTimeServlet</servlet-class>
  </servlet>
  <servlet-mapping>
    <servlet-name>VisitServlet</servlet-name>
    <url-pattern>/visit</url-pattern>
  </servlet-mapping>
  <servlet-mapping>
    <servlet-name>ShowTimeServlet</servlet-name>
    <url-pattern>/show</url-pattern>
  </servlet-mapping>
</web-app>

這裏寫圖片描述

讀取Web工程中資源文件

讀取工程中的資源文件,Java中的IO流其實就可以完成,下面使用Java中的IO流完成讀取資源文件。

  • 首先在Web工程中,創建四個資源文件。
    • 在Web工程的根目錄下創建1.txt。
    • 在Web工程的WebRoot目錄下創建2.txt。
    • 在Web工程的WebRoot目錄的WEB-INF目錄下創建3.txt。
    • 在Web工程的src目錄下創建4.txt。
  • 創建一個Java文件用於讀取上述的四個資源文件。
public class ReaderFileTest {
    // 編寫readfile()方法完成資源文件的讀取工作.
    public static void readfile(String fileName) throws Exception{
        BufferedReader reader = new BufferedReader(new FileReader(fileName));
        String line;
        while ((line = reader.readLine()) != null) {
            System.out.println(line);
        }
        reader.close();
    }

    public static void main(String[] args) throws Exception {
        // 讀取1.txt
        String filename1 = "1.txt";
        readfile(filename1);
        // 讀取2.txt
        String filename2 = "WebRoot/2.txt";
        readfile(filename2);
        // 讀取3.txt
        String filename3 = "WebRoot/WEB-INF/3.txt";
        readfile(filename3);
        // 讀取4.txt
        String filename4 = "src/4.txt";
        readfile(filename4);
    }
}
  • 運行該Java文件會在控制檯打印響應信息。

這裏寫圖片描述

如果要想利用Servlet API的內容來讀取Web工程中的資源文件,又要如何來做呢?ServletContext對象的getRealPath()方法可以來完成此項工作。

  • 創建一個自定義Servlet,使用ServletContext對象的getRealPath()方法來完成讀取資源文件。
public class ReadFileServlet extends HttpServlet {
    public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        response.setContentType("text/html;charset=utf-8");
        OutputStream out = response.getOutputStream();
        /*
         *  讀取1.txt
         *   * 因爲1.txt資源文件在Web工程的根目錄.
         *   * Web工程的WebRoot目錄發佈到Tomcat服務器.
         *   * 所以,1.txt資源文件是不會發布到Tomcat服務器的,Servlet無法讀取.
         */
        // 讀取2.txt
        String filename2 = getServletContext().getRealPath("/2.txt");
        InputStream in2 = new FileInputStream(new File(filename2));
        IOUtils.copy(in2, out);
        // 讀取3.txt
        String filename3 = getServletContext().getRealPath("/WEB-INF/3.txt");
        InputStream in3 = new FileInputStream(new File(filename3));
        IOUtils.copy(in3, out);
        // 讀取4.txt
        String filename4 = getServletContext().getRealPath("/WEB-INF/classes/4.txt");
        InputStream in4 = new FileInputStream(new File(filename4));
        IOUtils.copy(in4, out);
    }
    public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }
}
  • 發佈Web應用程序到Tomcat服務器,並啓動Tomcat服務器。
  • 打開瀏覽器,在地址欄中分別輸入http://localhost:8080/08_servlet/read,在控制檯打印相關信息。

這裏寫圖片描述

除了可以使用ServletContext對象的getRealPath()方法之外,還可以使用ServletContext對象的getResourceAsStream()方法來完成讀取資源文件的工作。

public class ReadFileServlet extends HttpServlet {
    public void doGet(HttpServletRequest request, HttpServletResponse 
response) throws ServletException, IOException {
        InputStream in = getServletContext().getResourceAsStream("/WEB-INF/classes/4.txt");
        IOUtils.copy(in, out);
    }

    public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }
}

還有一種通用的方法:利用Class類的getResource()方法也可以完成讀取資源文件的工作。

public class ReadFileServlet extends HttpServlet {
    public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 利用類加載器讀取Web工程的資源文件
        String filename = ReadFileServlet.class.getResource("/4.txt").getFile();
        InputStream in = new FileInputStream(new File(filename));
        IOUtils.copy(in, out);
    }

    public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }
}

轉載說明:請註明作者及原文鏈接,謝謝!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章