1. 程式人生 > 其它 >07-javax.servlet.ServletContext

07-javax.servlet.ServletContext

接著上面筆記中的ServletConfig介面中最後一個方法,

我們新建一個web專案c-ServletContext,

該專案中的兩個Servlet實現類為AServlet和BServlet,

將init中的區域性變數ServletConfig物件賦值給一個私有的成員變數config,

在各自的service方法中用該物件呼叫ServletConfig介面中的獲取Servlet物件上下文的方法getServletContext分別在兩個實現類中獲取,並輸出到瀏覽器。其他配置就不贅述了。

web.xml檔案

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
         version="4.0">

    <servlet>
        <servlet-name>servletcontext1</servlet-name>
        <servlet-class>com.servlet.AServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>servletcontext1</servlet-name>
        <url-pattern>/a</url-pattern>
    </servlet-mapping>

    <servlet>
        <servlet-name>servletcontext2</servlet-name>
        <servlet-class>com.servlet.BServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>servletcontext2</servlet-name>
        <url-pattern>/b</url-pattern>
    </servlet-mapping>
</web-app>

兩個實現類中方法的程式碼如下

    private ServletConfig config = null;

    @Override
    public void init(ServletConfig servletConfig) throws ServletException {
        this.config = servletConfig;
    }

    @Override
    public ServletConfig getServletConfig() {
        return config;
    }

    @Override
    public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {

        ServletConfig config = getServletConfig();
        ServletContext application = config.getServletContext();
        System.out.println(application);
    }

    @Override
    public String getServletInfo() {
        return null;
    }

    @Override
    public void destroy() {

    }

部署執行,在瀏覽器輸入URL轉到index頁面,點選其中的兩個連線分別輸出兩個Servlet物件中獲取的ServletContext物件,可以看到執行視窗輸出如下
兩個Servlet物件輸出的兩個ServletContext物件記憶體地址相同,是同一個物件。並且該介面由Tomcat伺服器實現,儲存的地址是org.apache.catalina.core包下,實現類的類名是ApplicationContextFacade.java

結論:

--javax.servlet.ServetContext介面:
	1、Tomcat伺服器完成對這個介面的實現
	完整的類名為:org.apache.catalina.core.ApplicationContextFacade
	javaweb程式設計師無需關心這個實現類,只需要面向ServetContext介面呼叫介面中的方法就行了。
	
	2、ServletContext具體是什麼?什麼時候被建立?什麼時候被銷燬?建立幾個?
	--ServletContext翻譯為:Servlet上下文
	--一個webapp只有一個web.xml檔案,該檔案在伺服器啟動時被解析
	--一個webapp只有一個ServletContext物件,該物件也是在伺服器啟動階段被例項化
	--ServletContext物件在伺服器關閉時被銷燬
	--ServletContext物件對應的是web.xml檔案,也可以說這個物件在專案執行時是web.xml檔案的代表
	--ServletContext物件是所有Servlet物件周圍環境的代表
	【在同一個webapp中所有Servlet物件共享一個環境,也就是共享同一個ServletContext物件】
	--當所有使用者希望共享一個數據,可以將該資料存放到ServletContext物件中,
	但是放進ServletContext物件中的資料不建議涉及修改操作,因為該物件是多執行緒共享的,修改會有執行緒安全問題。
	
	3、ServletContext介面中常用的重點方法
	--Object getAttribute(String name)
	獲取ServletContext範圍中的資料,在底層該方法是呼叫了集合的get方法,Object value=map.get(key.value)
	--void removeAttribute(String name)
	移除ServletContext範圍中的資料,在底層該方法是呼叫了集合的remove方法,map.remove(key)
	--void setAttribute(String name, Object object)
	向ServletContext範圍中新增資料,在底層該方法是呼叫了集合的put方法,map.put(key,value)
	
	下面兩個方法和ServletConfig介面中的一樣,只不過獲取web.xml檔案中的資訊是在<servlet></servlet>標籤之外定義的上下文初始化引數標籤<context-param>標籤中的內容,具體xml檔案程式碼如下面所示。
	--String getInitParameter(String name)
	--Enumeration getInitParameterNames()
	
	
	--String getRealPath(String path)
	該方法是獲取檔案的絕對路徑,演示如下
	
	4、Servlet、ServletConfig和ServletContext之間的關係
	--一個Servlet物件對應一個ServletConfig物件
	--一個webapp中的所有Servlet物件共享一個ServletContext物件
	
	5、從測試將資料儲存到ServletContext範圍以及從中讀取的操作中
	我們知道ServletContext範圍可以跨使用者傳遞,不同使用者點選連線照樣可以獲取資料可以儲存資料。
1、測試String getInitParameter(String name)和Enumeration getInitParameterNames()方法,xml檔案中上下文配置引數如下
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
         version="4.0">

    <!--web.xml檔案中配置上下文引數,該資訊在伺服器啟動階段解析xml檔案時自動封裝到ServletContext物件中-->
    <context-param>
        <param-name>username</param-name>
        <param-value>admin</param-value>
    </context-param>
    <context-param>
        <param-name>password</param-name>
        <param-value>123</param-value>
    </context-param>

    <servlet>
        <servlet-name>servletcontext1</servlet-name>
        <servlet-class>com.servlet.AServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>servletcontext1</servlet-name>
        <url-pattern>/a</url-pattern>
    </servlet-mapping>

    <servlet>
        <servlet-name>servletcontext2</servlet-name>
        <servlet-class>com.servlet.BServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>servletcontext2</servlet-name>
        <url-pattern>/b</url-pattern>
    </servlet-mapping>
</web-app>
service方法中的程式碼
  @Override
    public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {

        ServletConfig config = getServletConfig();
        ServletContext application = config.getServletContext();
        //System.out.println(application);

        //ServletContext介面中獲取所有上下文初始化引數的name的方法
        Enumeration<String> names = application.getAttributeNames();
        //遍歷集合,並獲取上下文初始化引數name對應的value
        while (names.hasMoreElements()){
            String name = names.nextElement();
            String value = application.getInitParameter(name);
            System.out.println(name+" = "+value);
        }
    }

結果如下

測試String getRealPath(String path)方法,獲取檔案絕對路徑
    @Override
    public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {

        ServletConfig config = getServletConfig();
        ServletContext application = config.getServletContext();
        //System.out.println(application);

        //ServletContext介面中獲取所有上下文初始化引數的name的方法
        Enumeration<String> names = application.getInitParameterNames();
        //遍歷集合,並獲取上下文初始化引數name對應的value
        while (names.hasMoreElements()){
            String name = names.nextElement();
            String value = application.getInitParameter(name);
            System.out.println(name+" = "+value);
        }

        //獲取檔案絕對路徑方法
        //下面這樣寫必須webapp根路徑(即WEB-INF目錄上一級)下有該檔案
        String absolutePath = application.getRealPath("/index.html");
    }

結果

測試void setAttribute(String name, Object object)和Object getAttribute(String name)方法,新建一個entity包,裡面先新建一個實體使用者類,程式碼如下
package com.entity;

public class User {

    private String usercode;

    private  String username;

    public String getUsercode() {
        return usercode;
    }

    public void setUsercode(String usercode) {
        this.usercode = usercode;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }
    

}
我們在AServlet類的service方法中用void setAttribute(String name, Object object)方法向ServletContext新增User物件中成員變數的資料。程式碼如下
        //建立User物件,並且給成員變數賦值
        User user = new User();
        user.setUsercode("12335");
        user.setUsername("高比例");
        
        //給ServletContext範圍儲存資料
        application.setAttribute("userObj",user);
我們在***BServlet***類的service方法中用Object getAttribute(String name)方法向ServletContext物件用name獲取資料。

具體程式碼如下

        //ServletContext物件範圍中讀取資料
        Object value = application.getAttribute("usercode");
        servletResponse.getWriter().print(value);//向瀏覽器中輸出資料
寫好後部署專案執行,進入索引頁,當我們點即測試AServlet後返回頁面再點選測試BServlet,可以看到如下結果輸出
先點擊向ServletContext範圍儲存資料的資源的執行結果,再點選獲取資料的資源類執行結果,可以得到如下輸出結果
以上操作順序相反,當先點選下面連接獲取不到資料,因為還沒有存,得到如下執行結果