深入理解Servlet原理
Servlet介紹:
1. 如何返回一個(gè)網(wǎng)頁:?a. 靜態(tài)網(wǎng)頁
? ? >新聞頁、百度百科
? ? >服務(wù)器保存一份HTML,直接返回給瀏覽器即可
?b. 動(dòng)態(tài)網(wǎng)頁
? ? >淘寶、QQ空間、微博
? ? >服務(wù)器保存一個(gè)組件,通過它動(dòng)態(tài)拼一個(gè)HTML
? ? >在Java中這個(gè)組件就是Servlet
2. Servlet特征:
? a. Servlet是服務(wù)器端組件,必須保存在服務(wù)器上。
? b. Servlet可以動(dòng)態(tài)拼資源(HTML/IMG等),即處理HTTP協(xié)議。
? c. Servlet必須滿足Sun的規(guī)范。
? d. Servlet是什么:Servlet是Sun推出的,用來在服務(wù)器端處理HTTP協(xié)議的組件。
服務(wù)器:
1. 名稱:Java 服務(wù)器、Java Web 服務(wù)器、Servlet 容器;
2. 本質(zhì):是一個(gè)軟件,需要安裝在硬件上才能用和瀏覽器是平級(jí)的關(guān)系;
3. 舉例:Tomcat(Apache)、JBOSS、WebLogic、WebSphere。
Tomcat使用:
1. 啟動(dòng)Tomcat:
? ?-Linux:打開/tomcat/bin,終端輸入命令./startup.sh
? ?-Windows:打開/tomcat/bin,雙擊startup.bat
2. 關(guān)閉Tomcat:
? ?-Linux:打開/tomcat/bin,終端輸入命名./shutdown.sh
? ?-Windows:打開/tomcat/bin,雙擊shutdown.bat
Servlet開發(fā)步驟:
1.創(chuàng)建WEB項(xiàng)目
? >目錄:webapp/WEB-INF/web.xml
2.導(dǎo)入jar包
? >通過maven導(dǎo)入jar包,搜javaee
? >使用服務(wù)器自帶的jar包,右鍵項(xiàng)目->target runtime->勾選tomcat
3.創(chuàng)建Servlet
? >實(shí)現(xiàn)Servlet接口
? >也可以繼承HttpSevlet,此類已實(shí)現(xiàn)了Servlet接口
? >實(shí)現(xiàn)/重寫service(),在此方法內(nèi)動(dòng)態(tài)拼HTML
4.注冊(cè)Servlet
? >注冊(cè)Servlet,并聲明別名
? >通過別名,給此Servlet注冊(cè)網(wǎng)名(以/開頭)
5.部署項(xiàng)目
? >在Servers下選擇Tomcat,右鍵Add and Remove
? >在彈出框內(nèi)左側(cè)選中項(xiàng)目,雙擊移動(dòng)到右側(cè)
? >部署:就是拷貝
6.訪問Servlet
? >啟動(dòng)Tomcat
? >瀏覽器輸入地址 http://ip:port/項(xiàng)目名/Servlet網(wǎng)名
7.重新部署
? >修改代碼后,需要重新部署并重啟Tomcat才有效
? >點(diǎn)擊Servers下面的Tomcat7,右鍵publish
? >可以手動(dòng)關(guān)閉Tomcat,再啟動(dòng)它
? >也可以等待Eclipse自動(dòng)重啟Tomcat(Reloading...)
Servlet執(zhí)行原理:
HTTP協(xié)議:
1. 什么是HTTP協(xié)議:它規(guī)定了瀏覽器和服務(wù)器如何通信,以及通信時(shí)的數(shù)據(jù)格式。
2. 如何通信:
? >建立連接
? >發(fā)送請(qǐng)求
? >接收響應(yīng)
? >關(guān)閉連接
3. 數(shù)據(jù)格式:
?a. 請(qǐng)求數(shù)據(jù)包
? ?>請(qǐng)求行:請(qǐng)求方式、Servlet網(wǎng)名、協(xié)議類型
? ?>消息頭:數(shù)據(jù)的描述信息
? ?>實(shí)體內(nèi)容:瀏覽器發(fā)送給服務(wù)器的數(shù)據(jù)
?b. 響應(yīng)數(shù)據(jù)包
? ?>狀態(tài)行:協(xié)議類型、狀態(tài)碼、狀態(tài)
? ?>消息頭:數(shù)據(jù)的描述信息
? ?>實(shí)體內(nèi)容:服務(wù)器給瀏覽器發(fā)送的數(shù)據(jù)
4. 對(duì)開發(fā)的要求
? -通信的方式已經(jīng)由瀏覽器和服務(wù)器完成;
? -請(qǐng)求數(shù)據(jù)的打包由瀏覽器實(shí)現(xiàn);
? -響應(yīng)數(shù)據(jù)的打包由服務(wù)器實(shí)現(xiàn);
? -開發(fā)需要提供瀏覽器發(fā)送給服務(wù)器的數(shù)據(jù),以及服務(wù)器返回的數(shù)據(jù);
? -服務(wù)器通過request對(duì)象接收請(qǐng)求數(shù)據(jù);
? -服務(wù)器通過response對(duì)象向?yàn)g覽器發(fā)送數(shù)據(jù);
注冊(cè)案例:
1. form的action屬性要寫上Servlet的訪問路徑(網(wǎng)名);
2. 在表單空間上,使用name屬性給該控件的數(shù)據(jù)命名,可以調(diào)用request的getParameter("name的指")來獲取值;
3. radio和checkbox需要設(shè)置value屬性的值,就是要傳遞給服務(wù)器的具體的值;
Servlet原理圖:
請(qǐng)求方式:
1. 介紹:瀏覽器向服務(wù)器發(fā)送數(shù)據(jù)的方式;
2. GET:
? >默認(rèn)情況下所有的請(qǐng)求都是GET請(qǐng)求
? >采用路徑傳參,即通過路徑攜帶參數(shù)
? >傳參過程中參數(shù)可見,隱私性差
? >因?yàn)槁窂酱笮∮邢拗?#xff0c;所以能夠傳遞的參數(shù)很小
3. POST:
? >method="post"
? >采用實(shí)體內(nèi)容傳參
? >在傳參的過程中,路徑上看不到參數(shù),隱私性好
? >實(shí)體內(nèi)容專門用于傳遞數(shù)據(jù),因此大小不受限制
4. 使用場(chǎng)景:
? >瀏覽器向服務(wù)器索取(查詢)數(shù)據(jù)用GET請(qǐng)求
? >瀏覽器向服務(wù)器提交(保存)數(shù)據(jù)用POST請(qǐng)求
解決亂碼問題:
重定向:
?1. 格式:res.sendRedirect("findEmp");//findEmp是網(wǎng)名
?2. 原理圖如下:
項(xiàng)目路徑:
URI和URL:
1. 狹義(Java):? ?- URI:絕對(duì)路徑;
? ?- URL:完整路徑;
? ?- URL包含了URI;
2. 廣義(Java/.net/php):
? ?- URI:資源的名稱;
? ?- URL:資源的真名;
? ?- URI包含了URL; ?
Servlet路徑的配置方式及用途:
1. 精確匹配(/test):? ? - 只有這唯一的路徑可以可以訪問此Servlet
? ? - 該Servlet只能處理一個(gè)請(qǐng)求?
2. 通配符(/*):
? ? - 所有的路徑都是可以訪問此Servlet
? ? - 該Servlet可以處理所有請(qǐng)求
3. 后綴匹配(*.test):
? ? - 所有以.test為后綴的路徑都可以訪問此Servlet
? ? - 該Servlet可以處理很多請(qǐng)求
注:
? a. 必須先通過規(guī)范約定正確的路徑;
? b. 按照規(guī)范判斷路徑,處理請(qǐng)求。對(duì)于不滿足規(guī)范的路徑,認(rèn)為是用戶輸入的錯(cuò)誤路徑,統(tǒng)一報(bào)錯(cuò);
Servlet生命周期:
1. 第1、2、4步只能執(zhí)行一次,第3步可以執(zhí)行多次;2. 因?yàn)镾ervlet被Tomcat自動(dòng)創(chuàng)建一次,因此它在Tomcat內(nèi)是單例的(只有1個(gè)實(shí)例),即Servlet滿足單例模式;
3. 默認(rèn)情況下,首次訪問Servlet時(shí),Tomcat會(huì)創(chuàng)建它,也可以修改配置文件web.xml,使得Tomcat啟動(dòng)時(shí)就直接創(chuàng)建Servlet;
4. 啟動(dòng)時(shí)創(chuàng)建Servlet,數(shù)字1代表創(chuàng)建的次序:<load-on-startup>1</load-on-startup>;
ServletConfig和ServletContext:
1. Context:上下文,理解為環(huán)境。環(huán)境可以給其內(nèi)部的個(gè)體提供資源。從編程的角度來說可以給內(nèi)部的對(duì)象提供數(shù)據(jù); 2. ServletConfig:它是Servlet的私有環(huán)境,可以為某一個(gè)Servlet提供數(shù)據(jù); 3. ServletContext:它是Servlet的公有環(huán)境,可以為所有Servlet提供數(shù)據(jù); 4. 使用ServletConfig和ServletContext給Servlet預(yù)置數(shù)據(jù),不用寫單獨(dú)的配置文件,直接使用web.xml即可;另外這兩個(gè)對(duì)象可以在初始化Servlet之前自動(dòng)讀取web.xml中的預(yù)置數(shù)據(jù); 5. Servlet特殊用法: ? ? - 可以使用此對(duì)象存取一些變量; ? ? - 即在程序運(yùn)行階段隨時(shí)向此對(duì)象存取數(shù)據(jù); ? ? - 獲取對(duì)象:ServletContext ctx = getServletContext(); ? ? - 取:ctx.getAttribute("user"); ? ? - 存:ctx.setAttribute("user","admin"); ?6.?通常在Tomcat啟動(dòng)時(shí),都要調(diào)用某Servlet重寫init(ServletConfig config)方法,專門用來在此階段初始化項(xiàng)目所需要的一些變量。使用案例:
1. ServletConfig案例: ? a. 配置文件web.xml <servlet><servlet-name>login</servlet-name><servlet-class>web.LoginServlet</servlet-class><!-- 給當(dāng)前Servlet預(yù)置一個(gè)數(shù)據(jù) --><init-param><param-name>maxOnline</param-name><param-value>2000</param-value></init-param></servlet><servlet-mapping><servlet-name>login</servlet-name><url-pattern>/login</url-pattern></servlet-mapping> ? b. 在Servlet類中讀取參數(shù) /*** 1.Tomcat在創(chuàng)建此Servlet后,會(huì)自動(dòng)創(chuàng)建ServletConfig對(duì)象。* 2.Tomcat會(huì)調(diào)用此對(duì)象,讀取web.xml中給當(dāng)前Servlet所配置的參數(shù)。* 3.Tomcat會(huì)自動(dòng)調(diào)用init方法,并傳入已創(chuàng)建好的ServletConfig對(duì)象。* 歸納:調(diào)用init方法前,創(chuàng)建config并讀取數(shù)據(jù)。在init及其后面的方法內(nèi)可以使用config。*/@Overridepublic void init(ServletConfig config) throws ServletException {super.init(config);String mo = config.getInitParameter("maxOnline");System.out.println(mo);}@Overrideprotected void service(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {//從web.xml中讀取參數(shù)ServletConfig cfg = getServletConfig();String mo = cfg.getInitParameter("maxOnline");System.out.println(mo);}2. ServletContext案例:
? a.?配置文件web.xml
<!-- 給所有的Servlet預(yù)置一個(gè)數(shù)據(jù)。1.Tomcat啟動(dòng)時(shí)會(huì)自動(dòng)創(chuàng)建ServletContext對(duì)象。2.Tomcat調(diào)用context讀取此參數(shù)。由于這件事是在調(diào)用Servlet之前完成的,所以在service()中可以通過context讀取參數(shù)。--><context-param><param-name>size</param-name><param-value>10</param-value></context-param><servlet><servlet-name>findDept</servlet-name><servlet-class>web.FindDeptServlet</servlet-class></servlet><servlet-mapping><servlet-name>findDept</servlet-name><url-pattern>/findDept</url-pattern></servlet-mapping>? b.?在Servlet類中讀取參數(shù)
@Override protected void service(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {//從web.xml中讀取分頁條件ServletContext ctx = getServletContext();String size = ctx.getInitParameter("size");//分頁查詢System.out.println(size); }線程安全:
1. 成員變量:
? ? - 成員變量存于堆內(nèi);
? ? - 堆內(nèi)數(shù)據(jù)只有一份;
? ? - 多線程共用一份數(shù)據(jù);
? ? - 存在并發(fā)問題;
2. 局部變量:
? ? - 成員變量存于棧內(nèi);
? ? - 棧內(nèi)數(shù)據(jù)是多份;
? ? - 每個(gè)線程都有一份自己的數(shù)據(jù);
? ? - 沒有并發(fā)問題;
3. 解決方案:
? ?- 不用成員;
? ?- 枷鎖synchronized (this) {//TODO};
HttpServlet:
1. 自定義的類繼承HttpServlet類,重寫service方法,Tomcat將HttpServletRequest,HttpServletResponse傳入此方法: public class TestServlet extends HttpServlet {@Overrideprotected void service(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {super.service(req, res);}//... } 2. 調(diào)用父類,并將HttpServletRequest、HttpServletResponse兩個(gè)參數(shù)傳入: public class HttpServlet {public void service(ServletRequest request, ServletResponse response) throws ServletException, IOException {HttpServletRequest req = (HttpServletRequest) request;HttpServletResponse res= (HttpServletResponse) response;this.service(req, res);}public void service(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {String m = req.getMethod();if(m.equals("GET")) {doGet(req, res);}else if(m.equals("POST")) {doPost(req, res);}} private void doPost(HttpServletRequest req, HttpServletResponse res) {// TODO}private void doGet(HttpServletRequest req, HttpServletResponse res) {// TODO}//... } 3. doGet()和doPost()默認(rèn)的代碼直接拋出了異常,為了強(qiáng)制開發(fā)者去重寫他們。 若要調(diào)用它們,就必須重寫;4. service()內(nèi)去掉super.service()的目的就是不掉用它們,從而避免異常;
總結(jié)
以上是生活随笔為你收集整理的深入理解Servlet原理的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【详解】EL表达式和JSTL标签库的使用
- 下一篇: 基于SSH保险业务管理系统的设计与实现