Servlet04 12.ServletConfig 12.1ServletConfig基本介紹 ServletConfig類是為Servlet程式配置信息的類 Servlet對象和ServletConfig對象都是由Tomcat負責創建 Servlet對象預設是第一次訪問的時候創建,Servlet ...
Servlet04
12.ServletConfig
12.1ServletConfig基本介紹
- ServletConfig類是為Servlet程式配置信息的類
- Servlet對象和ServletConfig對象都是由Tomcat負責創建
- Servlet對象預設是第一次訪問的時候創建,ServletConfig在Servlet對象創建的時候,就創建一個對應的ServletConfig對象
12.2ServletConfig作用
- 獲取Servlet程式的servlet-name的值
- 獲取初始化參數init-param
- 獲取ServletContext對象(上下文對象)
12.3ServletConfig應用實例
例子
需求:編寫DBServlet.java,完成如下功能
-
在web.xml配置連接mysql的用戶名和密碼
-
在DBServlet執行doGet()或者doPost()時,可以獲取到web.xml配置的用戶名和密碼
-
思路分析:
瀏覽器發送請求,Tomcat去創建DBServlet,DBServlet去web.xml文件中去獲取配置的參數,獲取的方法有兩種:一是使用dom4j,二是使用ServletConfig類
web.xml配置Servlet:
<!--配置DBServlet-->
<servlet>
<servlet-name>DBServlet</servlet-name>
<servlet-class>servlet.DBServlet</servlet-class>
<!--為該Servlet配置初始參數-->
<init-param>
<!--參數名-->
<param-name>username</param-name>
<!--參數值-->
<param-value>jack</param-value>
</init-param>
<init-param>
<param-name>pwd</param-name>
<param-value>123456</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>DBServlet</servlet-name>
<url-pattern>/db</url-pattern>
</servlet-mapping>
DBServlet:
package servlet;
import javax.servlet.*;
import javax.servlet.http.*;
import java.io.IOException;
public class DBServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request, response);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//在DBServlet執行doGet()或者doPost()時,可以獲取到web.xml配置的用戶名和密碼
//DBServlet的父類GenericServlet有方法getServletConfig()
/**
* 1.getServletConfig()是父類GenericServlet的
* 2.返回的ServletConfig對象是GenericServlet的private transient ServletConfig config
* 3.當一個屬性被transient修飾,表示該屬性不會被串列化(有些重要信息不希望保存到文件中)
*/
ServletConfig servletConfig = getServletConfig();
String username = servletConfig.getInitParameter("username");
String pwd = servletConfig.getInitParameter("pwd");
System.out.println("初始化參數username=" + username);
System.out.println("初始化參數pwd=" + pwd);
}
}
瀏覽器訪問DBServlet時,後臺輸出:
問題一:在doPost方法中可以得到servletConfig,在doGet方法也可以得到servletConfig,那麼這兩個servletConfig是同一個servletConfig嗎?
答:是同一個servletConfig。
先來看一個例子
在上述的DBServlet中重寫init方法,並且分別在init和doPost方法中輸出ServletConfig對象
package servlet;
import javax.servlet.*;
import javax.servlet.http.*;
import java.io.IOException;
public class DBServlet extends HttpServlet {
@Override
public void init(ServletConfig config) throws ServletException {
System.out.println("init()=" + config);
}
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request, response);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
ServletConfig servletConfig = getServletConfig();
System.out.println("doPost()=" + servletConfig);
String username = servletConfig.getInitParameter("username");
String pwd = servletConfig.getInitParameter("pwd");
System.out.println("初始化參數username=" + username);
System.out.println("初始化參數pwd=" + pwd);
}
}
redeployTomcat,在瀏覽器重新訪問DBServlet,會發現出現了500錯誤,這表明伺服器內部運行出現錯誤
查看控制台輸出,發現doPost方法竟然輸出了null
在DBServlet中的init方法加上語句super.init(config);
redeployTomcat,重新訪問瀏覽器,會發現訪問DBServlet成功,後臺輸出變正常了
問題二:這是為什麼呢?
我們先來梳理ServletConfig config的使用流程
-
當DBServlet對象初始化時,Tomcat會同時創建一個ServletConfig對象
-
如果DBServlet init()方法中調用了super.init(config);
-
就會調用父類GenericServlet的init方法:
public void init(ServletConfig config) throws ServletException { this.config = config; this.init(); }
這時就會把Tomcat創建的ServletConfig對象賦給GenericServlet的屬性config
-
因此如果要重寫init()方法,記住如果你想在其他方法通過getServletConfig()獲取ServletConfig,則一定要記住調用super.init(config);
回到問題二:
如果沒有把tomcat創建的ServletConfig,賦值給GenericServlet的屬性config。那麼GenericServlet的屬性config的值就為null,而doPost或者doGet方法通過getServletConfig()拿到的就是GenericServlet的屬性config,因此就會輸出null。
側面證實了方法中獲取的servletConfig是同一個對象(問題一)
因此上面的例子中,瀏覽器訪問DBServlet,發現出現了500錯誤的原因是,doPost方法中獲取了為null的ServletConfig對象中的屬性
13.ServletContext
13.1為什麼需要ServletContext
先來看一個需求:如果我們希望統計某個web應用的所有Servlet被訪問的次數,怎麼辦?
方案一:使用DB
方案二:使用ServletContext
13.2ServletContext基本介紹
-
ServletContext是一個介面,它表示Servlet上下文對象
-
一個web工程中,只有一個ServletContext對象實例
-
ServletContext對象是在web工程啟動的時候創建的,在web工程停止的時候銷毀
-
可以通過ServletConfig.getServletContext方法獲得對ServletContext對象的應用,也可以通過this.getServletContext()來獲得其對象的引用
-
由於一個web應用中的所有Servlet共用一個ServletContext對象,因此Servlet對象之間可以通過ServletContext對象來實現多個Servlet間的通信。ServletContext對象通常也被稱為域對象。
13.3ServletContext可以做什麼
-
獲取web.xml文件中配置的上下文參數context-param [信息和整個web應用相關,而不是屬於某個Servlet]
-
獲取當前的工程路徑,格式:/工程路徑
-
獲取工程部署後在伺服器硬碟上的絕對路徑
比如 D:\IDEA-workspace\servlet\out\artifacts\servlet_war_exploded
-
向Map一樣存取數據,多個Servlet共用數據
13.4應用實例
13.4.1應用實例1-獲取工程相關信息
需求如下:
- 獲取web.xml中配置的上下文參數context-param
- 獲取當前的工程路徑,格式:/工程路徑
- 獲取工程部署後在伺服器硬碟上的絕對路徑
配置ServletContext_: 在web.xml文件增加相關配置
<!--配置ServletContext_-->
<servlet>
<servlet-name>ServletContext_</servlet-name>
<servlet-class>com.li.servlet.servletcontext.ServletContext_</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>ServletContext_</servlet-name>
<url-pattern>/servletContext_</url-pattern>
</servlet-mapping>
<!--配置整個網站的信息-->
<context-param>
<param-name>website</param-name>
<param-value>http://www.lili.net</param-value>
</context-param>
<context-param>
<param-name>company</param-name>
<param-value>lili有限公司</param-value>
</context-param>
ServletContext_:
package com.li.servlet.servletcontext;
import javax.servlet.*;
import javax.servlet.http.*;
import java.io.IOException;
public class ServletContext_ extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request, response);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//獲取web.xml的context-parameter
//1.獲取到ServletContext對象
ServletContext servletContext = getServletContext();
//2.獲取website
String website = servletContext.getInitParameter("website");
String company = servletContext.getInitParameter("company");
System.out.println("website= " + website);
System.out.println("company= " + company);
//3.獲取項目的工程路徑
String contextPath = servletContext.getContextPath();
System.out.println("項目路徑= " + contextPath);// /servlet_demo
//4.得到項目發佈後真正的工作路徑
//這裡的斜杠/表示我們的項目發佈後的根路徑 D:\IDEA-workspace\servlet_demo\out\artifacts\servlet_demo_war_exploded
String realPath = servletContext.getRealPath("/");
System.out.println("項目發佈後的絕對路徑= " + realPath);
}
}
瀏覽器訪問ServletContext_:
後臺輸出:
13.4.2應用實例2-簡單的網站訪問次數統計器
需求:完成一個簡單的網站訪問次數統計器
不管使用什麼瀏覽器,每訪問一次Servlet,就增加1訪問次數,在後臺輸出,並將結果返回給瀏覽器顯示
WebUtils.java:
package com.li.servlet.servletcontext;
import javax.servlet.ServletContext;
public class WebUtils {
//該方法對訪問網站的次數累加,同時返回次數
public static Integer visitCount(ServletContext servletContext) {
//從servletContext獲取 visit_count 屬性 k-v
Object visit_count = servletContext.getAttribute("visit_count");
//判斷visit_count是否為空
if (visit_count == null) {//說明是第1次訪問網站
servletContext.setAttribute("visit_count", 1);
visit_count = 1;
} else {//說明是第二次或之後訪問
//visit_count+1
visit_count = Integer.parseInt(visit_count + "") + 1;
//再將其放回servletContext
servletContext.setAttribute("visit_count", visit_count);
}
return Integer.parseInt(visit_count + "");
}
}
Servlet01.java:
package com.li.servlet.servletcontext;
import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.*;
import java.io.IOException;
import java.io.PrintWriter;
@WebServlet(urlPatterns = {"/Servlet01"})
public class Servlet01 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request, response);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//獲取到ServletContext對象
ServletContext servletContext = getServletContext();
Integer visit_count = WebUtils.visitCount(servletContext);
//輸出顯示
response.setContentType("text/html;charset=utf-8");
PrintWriter writer = response.getWriter();
writer.print("<h1>該網站被訪問的次數是" + visit_count + "</h1>");
writer.flush();
writer.close();
}
}
Servlet02.java:
package com.li.servlet.servletcontext;
import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.*;
import java.io.IOException;
import java.io.PrintWriter;
@WebServlet(urlPatterns = {"/Servlet02"})
public class Servlet02 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request, response);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//獲取到ServletContext對象
ServletContext servletContext = getServletContext();
Integer visit_count = WebUtils.visitCount(servletContext);
//輸出顯示
response.setContentType("text/html;charset=utf-8");
PrintWriter writer = response.getWriter();
writer.print("<h1>該網站被訪問的次數是" + visit_count + "</h1>");
writer.flush();
writer.close();
}
}
redeployTomcat,在不同的瀏覽器分別訪問Servlet01和Servlet02: