servlet詳解
Servlet對映路徑
Servlet配置
<!-- 配置一個servlet -->
<!-- servlet的配置 -->
<servlet>
<!-- servlet的內部名稱,自定義。儘量有意義 -->
<servlet-name>FirstServlet</servlet-name>
<!-- servlet的類全名: 包名+簡單類名 -->
<servlet-class>gz.itcast.a_servlet.FirstServlet</servlet-class>
</servlet>
<!-- servlet的對映配置 -->
<servlet-mapping>
<!-- servlet的內部名稱,一定要和上面的內部名稱保持一致!! -->
<servlet-name>FirstServlet</servlet-name>
<!-- servlet的對映路徑(訪問servlet的名稱) -->
<url-pattern>/first</url-pattern>
</servlet-mapping>
Servlet精確匹配和模糊匹配
精確匹配和模糊匹配該注意的問題
1)url-pattern要麼以 / 開頭,要麼以*開頭。 例如, itcast是非法路徑。
2)不能同時使用兩種模糊匹配,例如 /itcast/*.do是非法路徑
3)當有輸入的URL有多個servlet同時被匹配的情況下:
匹配原則:
3.1 精確匹配優先。(長的最像優先被匹配)
3.2 以字尾名結尾的模糊url-pattern優先順序最低!!!
Servlet預設路徑
servlet的預設路徑(<url-pattern>/</url-pattern>
)是在tomcat伺服器內建的一個路徑(在conf\web.xml中)。該路徑對應的是一個DefaultServlet(預設Servlet)。這個預設的Servlet的作用是用於解析web應用的靜態資原始檔。
問題: URL輸入http://localhost:8080/day10/index.html 如何讀取文件?
1)到當前day10應用下的web.xml檔案查詢是否有匹配的url-pattern。
2)如果沒有匹配的url-pattern,則交給tomcat的內建的DefaultServlet處理
3)DefaultServlet程式到day10應用的根目錄下查詢是存在一個名稱為index.html的靜態檔案。
4)如果找到該檔案,則讀取該檔案內容,返回給瀏覽器。
5)如果找不到該檔案,則返回404錯誤頁面。
結論:
Tomcat先找動態資源,再找靜態資源。
Servlet生命週期
Servlet程式的生命週期由tomcat伺服器控制的!
四個重要方法
來看一下HttpServlet的繼承結構
其中,HttpServelt繼承了GenericServlet類,而GenericServlet類實現了Servlet介面。
再看看Servlet介面:
這說明HttpServlet裡面一定有這五個方法。
其中,Tomcat一定會執行的有以下四個方法:
(1)構造方法: 建立servlet物件的時候呼叫。預設情況下,第一次訪問servlet的時候建立servlet物件 只呼叫1次。證明servlet物件在tomcat是單例項的。
(2)init方法: 建立完servlet物件的時候呼叫。只呼叫1次。
(3)service方法: 每次發出請求時呼叫。呼叫n次。
(4)destroy方法: 銷燬servlet物件的時候呼叫。停止伺服器或者重新部署web應用時銷燬servlet物件只呼叫1次。
例子:
package gz.itcast.c_life;
import java.io.IOException;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class LifeDemo extends HttpServlet {
/**
* 1.構造方法
*/
public LifeDemo(){
System.out.println("1.servlet物件被建立了。");
}
/**
* 2.init方法
*/
@Override
public void init(ServletConfig config) throws ServletException {
System.out.println("2.init方法被呼叫");
}
/**
* 3.service方法
*/
@Override
public void service(ServletRequest req, ServletResponse res)
throws ServletException, IOException {
System.out.println("3.service方法被呼叫");
}
/**
* 4.destroy方法
*/
@Override
public void destroy() {
System.out.println("4.servlet物件銷燬了");
}
}
執行效果:
多次訪問地址:
關閉Tomcat:
時序圖演示
以FirstServlet為例:
Servlet自動載入
預設情況下,第一次訪問servlet的時候建立servlet物件。如果servlet的構造方法或init方法中執行了比較多的邏輯程式碼,那麼導致使用者第一次訪問sevrlet的時候比較慢。
改變servlet建立物件的時機: 提前到載入web應用的時候!!!
在LifeDemo中加入<load-on-startup>1</load-on-startup>
即可,其中1表示載入的Servlet順序,這個值越大,載入順序越低
<servlet>
<servlet-name>LifeDemo</servlet-name>
<servlet-class>gz.itcast.c_life.LifeDemo</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
啟動Tomcat如下:
有參和無參的init方法
GenericServlet有兩個init方法,其中一個是Sun公司實現的,另一個留給開發者自己覆蓋實現。
已實現的init方法會呼叫未實現的init()
例子:
public class InitDemo extends HttpServlet {
/**
* 有引數的init方法
* 該方法是servlet的生命週期方法,一定會被tomcat伺服器呼叫
*/
/**
* 注意:如果要編寫初始程式碼,不需要覆蓋有引數的init方法
*/
// @Override
// public void init(ServletConfig config) throws ServletException {
// System.out.println("有引數的init方法");
// }
/**
* 無引數的init方法
* 該方法是servlet的編寫初始化程式碼的方法。是Sun公司設計出來專門給開發者進行覆蓋,然後在裡面編寫servlet的初始邏輯程式碼的方法。
*/
@Override
public void init() throws ServletException {
System.out.println("無引數的init方法");
}
}
Servlet多執行緒併發問題
servlet物件在tomcat伺服器是單例項多執行緒的。
因為servlet是多執行緒的,所以當多個servlet的執行緒同時訪問了servlet的共享資料,如成員變數,可能會引發執行緒安全問題。
解決辦法:
1)把使用到共享資料的程式碼塊進行同步(使用synchronized關鍵字進行同步)
2)建議在servlet類中儘量不要使用成員變數。如果確實要使用成員,必須同步。而且儘量縮小同步程式碼塊的範圍。(哪裡使用到了成員變數,就同步哪裡!!),以避免因為同步而導致併發效率降低。
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* servlet的多執行緒併發問題,模擬多使用者訪問同一個網站地址,統計訪問量
* @author APPle
*
*/
public class TheradDemo extends HttpServlet {
int count = 1;//共享變數
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html;charset=utf-8");
synchronized (TheradDemo.class) {//鎖物件必須唯一。建議使用類物件
System.out.println("你現在是當前網站的第"+count+"個訪客"); //執行緒1執行完 , 執行緒2執行
count++;
}
}
}
ServletConfig物件
作用
主要是用於載入servlet的初始化引數。在一個web應用可以存在多個ServletConfig物件(一個Servlet對應一個ServletConfig物件)
如何建立和得到
建立時機: 在建立完servlet物件之後,在呼叫init方法之前建立。
得到物件: 直接從有引數的init方法中得到!!!
ServletConfig的API:
java.lang.String getInitParameter(java.lang.String name) 根據引數名獲取引數值
java.util.Enumeration getInitParameterNames() 獲取所有引數
ServletContext getServletContext() 得到servlet上下文物件
java.lang.String getServletName() 得到servlet的名稱
例子
web.xml:
<servlet>
<servlet-name>ConfigDemo</servlet-name>
<servlet-class>gz.itcast.f_config.ConfigDemo</servlet-class>
<!-- 初始引數: 這些引數會在載入web應用的時候,封裝到ServletConfig物件中 -->
<init-param>
<param-name>path</param-name><!-- 配置檔案訪問路徑 -->
<param-value>e:/b.txt</param-value>
</init-param>
<init-param>
<param-name>BBB</param-name>
<param-value>BBB's value</param-value>
</init-param>
<init-param>
<param-name>CCCC</param-name>
<param-value>CCCC's value</param-value>
</init-param>
</servlet>
package gz.itcast.f_config;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.Enumeration;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class ConfigDemo extends HttpServlet {
/**
* 以下兩段程式碼GenericServlet已經寫了,我們無需編寫!!
*/
/*private ServletConfig config;*/
/**
* 1)tomcat伺服器把這些引數會在載入web應用的時候,封裝到ServletConfig物件中
* 2)tomcat伺服器呼叫init方法傳入ServletConfig物件
*/
/*@Override
public void init(ServletConfig config) throws ServletException {
this.config = config;
}*/
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
/**
* 讀取servlet的初始引數
*/
String path = this.getServletConfig().getInitParameter("path");//GenericServlet有個getServletConfig方法
File file = new File(path);
//讀取內容
BufferedReader br = new BufferedReader(new FileReader(file));
String str = null;
while( (str=br.readLine())!=null ){
System.out.println(str);
}
//查詢當前servlet的所有初始化引數
Enumeration<String> enums = this.getServletConfig().getInitParameterNames();
while(enums.hasMoreElements()){
String paramName = enums.nextElement();
String paramValue = this.getServletConfig().getInitParameter(paramName);
System.out.println(paramName+"="+paramValue);
}
//得到servlet的名稱
String servletName = this.getServletConfig().getServletName();
System.out.println(servletName);
}
}
ServletContext物件
作用
ServletContext物件 ,叫做Servlet的上下文物件。表示一個當前的web應用環境。一個web應用中只有一 個ServletContext物件,每個ServletConfig中都有一個ServletContext物件。
如何建立和得到
建立時機:載入web應用時建立ServletContext物件。//Tomcat伺服器啟動時載入
得到物件: 從ServletConfig物件的getServletContext方法得到(每個ServletConfig中都有一個ServletContext物件。)
核心API
例項
- 得到web應用路徑
public class ContextDemo1 extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//1.得到ServletContext物件
//ServletContext context = this.getServletConfig().getServletContext();
ServletContext context = this.getServletContext(); //(推薦使用)
//2.得到web應用路徑 /day10
/**
* web應用路徑:部署到tomcat伺服器上執行的web應用名稱
*/
String contextPath = context.getContextPath();
System.out.println(contextPath);// /day10
/**
* 案例:應用到請求重定向
*/
response.sendRedirect(contextPath+"/index.html");
}
}
- 得到Web應用的初始化引數
web.xml
<!-- 配置web應用引數 -->
<context-param>
<param-name>AAA</param-name>
<param-value>AAA's value</param-value>
</context-param>
<context-param>
<param-name>BBB</param-name>
<param-value>BBB's value</param-value>
</context-param>
<context-param>
<param-name>CCC</param-name>
<param-value>CCC's value</param-value>
</context-param>
public class ContextDemo2 extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//得到ServletContext物件
ServletContext context = this.getServletContext();
System.out.println("引數"+context.getInitParameter("AAA"));
Enumeration<String> enums = context.getInitParameterNames();
while(enums.hasMoreElements()){
String paramName = enums.nextElement();
String paramValue =context.getInitParameter(paramName);
System.out.println(paramName+"="+paramValue);
}
}
}
- 域物件使用
作用是用於儲存資料,獲取資料。可以在不同的動態資源之間共享資料。
ServletContext域物件:作用範圍在整個web應用中有效!!!
public class ContextDemo3 extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//1.得到域物件
ServletContext context = this.getServletContext();
//2.把資料儲存到域物件中
//context.setAttribute("name", "eric");
context.setAttribute("student", new Student("jacky",20));
System.out.println("儲存成功");
}
}
public class ContextDemo4 extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//1.得到域物件
ServletContext context = this.getServletContext();
//2.從域物件中取出資料
//String name = (String)context.getAttribute("name");
Student student = (Student)context.getAttribute("student");
//System.out.println("name="+name);
System.out.println(student);
}
}
4、轉發和重定向
轉發:
/**
* 轉發(效果:跳轉頁面)
* @author APPle
*
*/
public class ForwardDemo1 extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
/**
* 儲存資料到request域物件
*/
request.setAttribute("name", "rose");
//轉發
/**
* 注意:不能轉發當前web應用以外的資源。
*/
/*RequestDispatcher rd = this.getServletContext().getRequestDispatcher("/GetDataServlet");
rd.forward(request, response);*/
this.getServletContext().getRequestDispatcher("/GetDateServlet").forward(request, response);
}
}
重定向:
public class RedirectDemo1 extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
/**
* 儲存資料到request域物件
*/
request.setAttribute("name", "rose");
//重定向
/**
* 注意:可以跳轉到web應用內,或其他web應用,甚至其他外部域名。
*/
//response.sendRedirect("/day09/adv.html");
response.sendRedirect("/day10/GetDataServlet");
}
}
轉發和重定向的區別:
1)轉發
a)位址列不會改變
b)轉發只能轉發到當前web應用內的資源
c)可以在轉發過程中,可以把資料儲存到request域物件中
2)重定向
a)位址列會改變,變成重定向到地址。
b)重定向可以跳轉到當前web應用,或其他web應用,甚至是外部域名網站。
c)不能再重定向的過程,把資料儲存到request中。
相關文章
- Servlet、HTTP詳細解釋!ServletHTTP
- Java Web(5)-Servlet詳解(下)JavaWebServlet
- Java Web(5)-Servlet詳解(上)JavaWebServlet
- JavaWeb中的Tomcat,Servlet詳解JavaWebTomcatServlet
- JavaWeb三大元件之Servlet詳解JavaWeb元件Servlet
- Servlet簡介及其生命週期詳解Servlet
- Java Servlet詳解(體系結構+註解配置+生命週期)JavaServlet
- 走進JavaWeb技術世界4:Servlet 工作原理詳解JavaWebServlet
- 超詳細的Servlet教程,10分鐘帶你認識servletServlet
- Servlet 常見的註解Servlet
- 簡單瞭解什麼是ServletServlet
- servlet的url-pattern匹配規則詳細描述Servlet
- Servlet系列:(一)servlet原理剖析Servlet
- Servlet 規範和 Servlet 容器Servlet
- 96.Servlet Servlet生命週期Servlet
- Servlet第二篇【Servlet呼叫圖、Servlet細節、ServletConfig、ServletContext】ServletContext
- 解決javax.servlet.jsp.JspException cannot be resolved to a typeJavaServletJSException
- JavaWeb——ServletJavaWebServlet
- Servlet概述Servlet
- JavaWEB - ServletJavaWebServlet
- Servlet3:從根源瞭解並解決編碼問題Servlet
- 【IDEA】HTML通過servlet3.0註解名提交表單到servlet類找不到頁面的問題IdeaHTMLServlet
- Servlet操作OracleServletOracle
- Servlet 新手教程Servlet
- Servlet-HelloWorldServlet
- Servlet筆記Servlet筆記
- Servlet_6Servlet
- Servlet 規範Servlet
- 初學ServletServlet
- Servlet入門Servlet
- Java之ServletJavaServlet
- Servlet 如何工作Servlet
- Servlet5—IDEA專案配置,解決no artifacts的warningsServletIdea
- 淺嘗Spring註解開發_Servlet3.0與SpringMVCServletSpringMVC
- Servlet3.0新特性-非同步處理Servlet、FilterServlet非同步Filter
- Day91.Servlet基本內容① -Servlet、jsp和表示式ServletJS
- Servlet連線OracleServletOracle
- servlet再次總結Servlet
- Servlet是什麼?Servlet