一.servlet容器
1,容器就是你的程序運行時需要的環境。Tomcat是Servlet的運行環境,即一個Servlet容器。
2,Servlet容器的作用是負責處理客戶請求,當客戶請求來到時,Servlet容器獲取請求,然後調用某個Servlet,並把Servlet的執行結果返回給客戶。
3,Servlet容器的工作過程是:當客戶請求某個資源時,Servlet容器使用ServletRequest對象把客戶的請求信息封裝起來,然後調用Java Servlet API中定義的Servlet的一些生命週期方法,完成Servlet的執行,接着把Servlet執行的要返回給客戶的結果封裝到 ServletResponse對象中,最後Servlet容器把客戶的請求發送給客戶,完成爲客戶的一次服務過程。每一個Servlet的類都執行 init()、service()、destory()三個函數的自動調用,在啓動時調用一次init()函數用以進行參數的初始化,在服務期間每當接收到對該Servlet的請求時都會調用Service()函數執行該Servlet的服務操作,當容器銷燬時調用一次destory()函數。
二.生命週期
- 1.加載——創建servlet對象,調用構造器
所謂加載是指servlet加載進JVM運行,在如下兩種情況下會進行對象實例化。
第一種情況:
當請求到達容器時,容器查找該servlet對象是否存在,如果不存在,纔會創建實例。
第二種情況:
容器在啓動時,或者新部署了某個應用時,會檢查web.xml當中,servlet是否有 load-on-starup配置。如果有,則會創建該servlet實例。load-on-starup參數值越小,優先級越高(最小值爲0,優先級最高)。
- 2.初始化——init():
在Servlet的生命週期中,僅執行一次init()方法。它是在服務器裝入Servlet時執行的,負責初始化Servlet對象。無論有多少客戶機訪問Servlet,都不會重複執行init()。
- 3.就緒/調用——服務service():
Servlet的核心,負責響應客戶的請求。
每當一個客戶請求一個HttpServlet對象,該對象的Service()方法就要調用,而且傳遞給這個方法一個“請求”(ServletRequest)對象和一個“響應”(ServletResponse)對象作爲參數。HttpServlet中實現了service()方法,將請求ServletRequest、ServletResponse 強轉爲HttpRequest 和 HttpResponse,並依據請求方式來調用doGet()或者doPost()方法,因此默認的服務功能只需要重寫doGET和doPOST方法。
- 4.銷燬——destroy():
僅執行一次,在服務器端停止且卸載Servlet時執行該方法。當Servlet對象退出生命週期時,負責釋放佔用的資源。一個Servlet在運行service()方法時可能會產生其他的線程,因此需要確認在調用destroy()方法時,這些線程已經終止或完成。
三.servlet在web.xml中配置
web.xml中
<!-- 聲明Servlet對象 -->
<servlet>
<!-- 指定Servlet對象的名稱 -->
<servlet-name>name</servlet-name>
<!-- 指定Servlet對象的完整位置,包含包名和類名 -->
<servlet-class>com.demo.FirstServlet</servlet-class>
</servlet>
<!-- 映射Servlet -->
<servlet-mapping>
<!--<servlet-name>與上面<Servlet>標籤的<servlet-name>元素相對應,不可以隨便起名 -->
<servlet-name>name</servlet-name>
<!-- 話用於映射訪問URL -->
<url-pattern>/test</url-pattern>
</servlet-mapping>
FirstServlet. java中:
注意,此文件的完整路徑是com.demo.FirstServlet
public class FirstServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
/**
* @see HttpServlet#HttpServlet()
*/
public FirstServlet() {
super();
// TODO Auto-generated constructor stub
}
/**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
response.setContentType("text/html");
response.setCharacterEncoding("GBK");
PrintWriter out=response.getWriter();
out.print("<HTML>");
out.println("<HEAD><TITLE>Servlet實例</TITLE></HEAD>");
out.println("<BODY>");
out.println("servlet實例");
out.println("</BODY>");
out.println("</HTML>");
out.flush();
out.close();
response.getWriter().append("Served at: ").append(request.getContextPath());
}
/**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
doGet(request, response);
}
}
進行地址映射目的是爲了使用servlet,它的工作過程是:
輸入地址:http://localhost:8080/ test,通過它找到映射文件內部的文件名name,通過name找到對應的< servlet-name>name< /servlet-name>,然後定位到這個FirstServlet文件:com.demo.FirstServlet
由此可見,< servlet-name>name< /servlet-name>中的名字name不一定一定要與servlet的文件名“FirstServlet.java”一致,它只是在對web.xml文件配置的時候我們對servlet應用名字的定義,通過< servlet-class>com.demo.FirstServlet我們就可以定位到這個servlet文件。
四.ServletConfig
ServletConfig代表當前Servlet在web.xml中的配置信息
在Servlet的配置文件中,可以使用一個或多個< init-param>標籤爲servlet配置一些初始化參數。
當servlet配置了初始化參數後,web容器在創建servlet實例對象時,會自動將這些初始化參數封裝到ServletConfig對象中,並在調用servlet的init方法時,將ServletConfig對象傳遞給servlet。進而,程序員通過ServletConfig對象就可以得到當前servlet的初始化參數信息。
<servlet>
<servlet-name>ServletConfigTest</servlet-name>
<servlet-class>com.demo.servlet.ServletConfigTest</servlet-class>
<init-param>
<param-name>name</param-name>
<param-value>value</param-value>
</init-param>
<init-param>
<param-name>encode</param-name>
<param-value>utf-8</param-value>
</init-param>
</servlet>
public void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {
ServletConfig config = this.getServletConfig(); //拿到init方法中的ServletConfig對象
// --獲取當前Servlet 在web.xml中配置的名稱(用的不多)
String sName = config.getServletName();
System.out.println("當前Servlet 在web.xml中配置的名稱:"+sName);
// --獲取當前Servlet中配置的初始化參數(只能獲取一個)經常用到
String value = config.getInitParameter("name");
System.out.println(value);
// --獲取當前Servlet中配置的初始化參數(全部獲取)經常用到
Enumeration enumration = config.getInitParameterNames();
while(enumration.hasMoreElements()){
String name = (String) enumration.nextElement();
String value = config.getInitParameter(name);
System.out.println(name+":"+value);
}
}
五.ServletContext
WEB容器在啓動時,它會爲每個WEB應用程序都創建一個對應的ServletContext對象,它代表當前web應用。
ServletConfig對象中維護了ServletContext對象的引用,可以通過ServletConfig.getServletContext方法獲得ServletContext對象。
由於一個WEB應用中的所有Servlet共享同一個ServletContext對象,因此Servlet對象之間可以通過ServletContext對象來實現通訊。ServletContext對象通常也被稱之爲context域對象。
1.做爲域對象可以在整個web應用範圍內設置共享數據。
public void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {
ServletContext context = this.getServletContext();
context.setAttribute("name", "value");
}
2.獲取WEB應用的初始化參數
web.xml中
<context-param>
<param-name>name</param-name>
<param-value>value></param-value>
</context-param>
servlet文件:
public void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {
ServletContext context = this.getServletContext(); // 得到上下文對象
// 獲取單個的Context裏面的初始化參數
String value = context.getInitParameter("name");
System.out.println(value);
//一次性獲取Context裏所有的初始化參數
Enumeration enumeration = context.getInitParameterNames();
while (enumeration.hasMoreElements()) {
String name = (String) enumeration.nextElement();
String value = context.getInitParameter(name);
System.out.println(name + ";" + value);
}
}
六.RequestDispatcher實現Servlet的轉發
請求重定向:(兩次請求兩次響應)這種重定向的方法,將導致客戶端瀏覽器的請求URL跳轉。從瀏覽器中的地址欄中可以看到新的URL地址,作用類似於上面設置HTTP響應頭信息的實現。
請求轉發:(一次請求一次響應,來實現資源流轉)
public void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {
RequestDispatcher dispatcher = this.getServletContext().getRequestDispatcher("/servlet/ServletTest2");//拿到轉發器dispatcher(參數中寫虛擬路徑)
dispatcher.forward(request, response); // 執行完這一行代碼後,將會跳到ServletTest2中去執行。
}