1.什么是servlet
servlet是一個(gè)Java類兵拢,是用來專門處理請求和響應(yīng)的翻斟,是部署在服務(wù)器上工作的小程序,之所以叫小程序说铃,是因?yàn)樗灰渴鹕先ゾ妥詣?dòng)運(yùn)行工作了可以處理事情了访惜。servlet 通常通過 HTTP(超文本傳輸協(xié)議)接收和響應(yīng)來自 Web 客戶端的請求嘹履。
HTTP:
★ HTTP是HyperText Transfer Protocol(超文本傳輸協(xié)議)的簡寫,傳輸HTML文件债热。
★ 用于定義WEB瀏覽器與WEB服務(wù)器之間交換數(shù)據(jù)的過程及數(shù)據(jù)本身的格式砾嫉。
2.操作步驟:
a.創(chuàng)建一個(gè)實(shí)現(xiàn)servlet接口的Java類(ServletDemo1)。
ServletDemo1爆紅是因?yàn)閷?shí)現(xiàn)了Servlet接口就需要重寫里面的方法窒篱。實(shí)現(xiàn)接口所定義的方法焕刮。
在service方法里添加輸出語句
@Override
public void service(ServletRequest arg0, ServletResponse arg1) throws ServletException, IOException {
// TODO Auto-generated method stub
System.out.println("執(zhí)行Servlet里的方法");
}
b.在web.xml中配置servlet的信息。
我們的目的就是讓用戶通過url來訪問我們的剛剛實(shí)現(xiàn)了servlet接口的類墙杯,然后在這個(gè)類里面做一些處理配并。但是我們的類是寫在src中,然后編譯成字節(jié)碼.class文件是存放在WEB-INF中的高镐,我們部署應(yīng)用的時(shí)候就把WEB-INF的東西部署到服務(wù)器上溉旋,而WEB-INF文件中的東西是不允許外部訪問的,所以如果想要訪問的這個(gè)類(嚴(yán)格意義上說是這個(gè)類生成的字節(jié)碼文件)嫉髓,我們就需要通過一些配置來告訴服務(wù)器某個(gè)URL地址是用來訪問某個(gè)類的观腊。這就是我們?yōu)槭裁匆渲脀eb.xml的原因。(服務(wù)器Tomcat啟動(dòng)后加載項(xiàng)目最先掃描執(zhí)行web.xml文件)
web.xml主要代碼:
<servlet>
<!-- 一般把類名首字母變小寫作為servlet-name-->
<servlet-name>ServelDemo1</servlet-name>
<servlet-class>com.szy.web.servlet.ServelDemo1</servlet-class>
</servlet>
這里的訪問邏輯是算行,我們在瀏覽器輸入localhost:8080/應(yīng)用名/demo1后梧油,它就會找到中相應(yīng)的url(在中),然后根據(jù)這個(gè)url找到對應(yīng)的叫servletDemo1州邢,然后就在這個(gè)節(jié)點(diǎn)里再找到該對應(yīng)的婶溯。至此,就自動(dòng)找到這個(gè)類偷霉,去執(zhí)行相應(yīng)的任務(wù)了迄委。
<servlet>
<servlet-name>servelDemo1</servlet-name>
<servlet-class>com.cms.Demo1.Service.ServelDemo1</servlet-class>
<!-- 2,填數(shù)字越小優(yōu)先級越高类少,越先執(zhí)行叙身,讓該servlet在服務(wù)器啟動(dòng)時(shí)就創(chuàng)建,不建議寫零 -->
<load-on-startup>2</load-on-startup>
</servlet>
<!-- 給Servlet映射一個(gè)可訪問的URI :http://localhost:8080/項(xiàng)目名/demo1即可通過servelDemo1映射到ServelDemo1訪問該類-->
<servlet-mapping>
<servlet-name>servelDemo1</servlet-name>
<url-pattern>/demo1</url-pattern>
</servlet-mapping>
com.szy.web.servlet.ServelDemo1路徑的獲得操作如下圖:
執(zhí)行結(jié)果:
瀏覽器顯示空白頁面但是控制臺輸出了ServletDemo1類里的執(zhí)行結(jié)果硫狞。
3.Servlet的生命周期
此接口定義了初始化 servlet 的方法 init()信轿、為請求提供服務(wù)的方法 service()和從服務(wù)器移除 servlet 的方法 destroy()。這些方法稱為生命周期方法残吩,它們是按以下順序調(diào)用的:
a .初始化階段 :
構(gòu)造 servlet财忽,然后使用 init 方法將其初始化。
b.響應(yīng)客戶請求階段:
處理來自客戶端的對 service 方法的所有調(diào)用泣侮。
c.終止階段:
從服務(wù)中取出 servlet即彪,然后調(diào)用 destroy 方法銷毀它,最后進(jìn)行垃圾回收并終止它活尊。
除了生命周期方法之外隶校,此接口還提供了 getServletConfig 方法和 getServletInfo 方法漏益,servlet 可使用前一種方法獲得任何啟動(dòng)信息,而后一種方法允許 servlet 返回有關(guān)其自身的基本信息深胳,比如作者绰疤、版本和版權(quán)。
package com.szy.web.servlet;
import java.io.IOException;
import javax.servlet.Servlet;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
public class ServelDemo1 implements Servlet {
public ServelDemo1() {
// 實(shí)例化方法
}
@Override
public void init(ServletConfig arg0) throws ServletException {
// 初始化
}
@Override
public void service(ServletRequest arg0, ServletResponse arg1) throws ServletException, IOException {
// 服務(wù)
System.out.println("執(zhí)行Servlet里的方法");
}
@Override
public void destroy() {
//銷毀
}
@Override
public ServletConfig getServletConfig() {
// TODO Auto-generated method stub
return null;
}
@Override
public String getServletInfo() {
// TODO Auto-generated method stub
return null;
}
}
注意:
Servlet何時(shí)被創(chuàng)建:
★ 默認(rèn)情況下舞终,當(dāng)WEB客戶第一次請求訪問某個(gè)Servlet的時(shí)候轻庆,WEB容器將創(chuàng)建這個(gè)Servlet的實(shí)例。
★ 當(dāng)web.xml文件中如果<servlet>元素中指定了<load-on-startup>子元素時(shí)敛劝,Servlet容器在啟動(dòng)web服務(wù)器時(shí)榨了,將按照順序創(chuàng)建并初始化Servlet對象。
★ 在web.xml文件中攘蔽,某些Servlet只有<serlvet>元素,沒有<servlet-mapping>元素呐粘,這樣我們無法通過url的方式訪問這些Servlet满俗,這種Servlet通常會在<servlet>元素中配置一個(gè)<load-on-startup>子元素,讓容器在啟動(dòng)的時(shí)候自動(dòng)加載這些Servlet并調(diào)用init()方法作岖,完成一些全局性的初始化工作唆垃。
4.servlet的三種創(chuàng)建方式
Servlet --> GenericServlet --> HttpServlet -->我們定義的繼承HttpServlet的類
曾祖父 爺爺 爸爸 孫子
方法如下:
a. 實(shí)現(xiàn)javax.servlet.Servlet接口(參見:編寫一個(gè)servlet程序)
要實(shí)現(xiàn)此接口,還可以編寫一個(gè)擴(kuò)展 javax.servlet.GenericServlet 的一般 servlet痘儡,或者編寫一個(gè)擴(kuò)展 javax.servlet.http.HttpServlet 的 HTTP servlet辕万。
b. 繼承javax.servet.GenericServlet類(適配器模式)
只需重寫抽象 service 方法,因?yàn)樗锩嬷挥幸粋€(gè)抽象方法沉删。
c. 繼承javax.servlet.http.HttpServlet類(模板方法設(shè)計(jì)模式)
我們自己寫Servlet的時(shí)候渐尿,處理請求的時(shí)候?qū)崿F(xiàn)Service()就好。不重寫Service()方法矾瑰,而是重寫doGet和doPost2個(gè)方法砖茸,在HttpServlet抽象類中,已經(jīng)實(shí)現(xiàn)了Service方法了殴穴,在有請求進(jìn)來Servlet的時(shí)候首先從請求中獲取到請求提交的方式凉夯,所以我們直接重寫doGet和doPost方法就好。通常來說不確定是什么請求的情況下采幌,默認(rèn)是Get請求劲够,在doGet和doPost中實(shí)現(xiàn)一個(gè)就夠了,如果方法的實(shí)現(xiàn)寫在
HTTP的請求方式包括DELETE,GET,OPTIONS,POST,PUT和TRACE,在HttpServlet類中分別提供了相應(yīng)的服務(wù)方法,它們是,doDelete(),doGet(),doOptions(),doPost(), doPut()和doTrace().
項(xiàng)目開發(fā)一般都用這種方式創(chuàng)建Servlet;
第一步:創(chuàng)建Servlet類文件
Ctrl+N休傍;輸入Servlet:
第二步:輸入類名
第三步:映射路徑的名字征绎,默認(rèn)為類名,可點(diǎn)擊Edit編輯
第三步:勾選需要重寫的方法:都默認(rèn)勾選Doget和Dopost方法磨取,點(diǎn)擊Finish:
繼承HttpServlet后不要重寫service的方法炒瘸,因?yàn)閟ervice方法里包含調(diào)用doget跟dopost的方法淤堵,重寫了那兩方法不執(zhí)行就作廢了
第五步:檢查生成的類和Web.xml的Servlet配置信息
package com.cms.Demo1.Service;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* Servlet implementation class ServletDemo4
*/
public class ServletDemo4 extends HttpServlet {
private static final long serialVersionUID = 1L;
/**
* @see HttpServlet#HttpServlet()
*/
public ServletDemo4() {
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.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>
<display-name>ServletDemo4</display-name>
<servlet-name>ServletDemo4</servlet-name>
<servlet-class>com.cms.Demo1.Service.ServletDemo4</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>ServletDemo4</servlet-name>
<url-pattern>/ServletDemo4</url-pattern>
</servlet-mapping>
注意:查看GenericServlet 的源碼包導(dǎo)Tomcat的源碼包,apache-tomcat-7.0.81-src.zip顷扩。Outline的窗口帶三角的說明是繼承過來重寫的方法拐邪,沒有的才是自己本身的。
servet映射細(xì)節(jié)
通配符* 代表任意字符串
url-pattern: *.do 以.字符串的請求都可以訪問 注:不要加/
url-pattern: /* 任意字符串都可以訪問
url-pattern: /action/ 以/action開頭的請求都可以訪問
匹配規(guī)則:
優(yōu)先級:從高到低
絕對匹配--> /開頭匹配 --> 擴(kuò)展名方式匹配
如果url-pattern的值是/隘截,表示執(zhí)行默認(rèn)映射扎阶。所有資源都是servlet
5. Servlet的線程安全
★ 單實(shí)例:每次訪問多線程
★ 解決線程安全問題的最佳辦法,不要寫全局變量婶芭,而寫局部變量东臀。
★ Servlet的線程安全問題只有在大量的并發(fā)訪問時(shí)才會顯現(xiàn)出來,并且很難發(fā)現(xiàn)犀农,因此在編寫Servlet程序時(shí)要特別注意惰赋。
★ servlet處于服務(wù)器進(jìn)程中濒募,它通過多線程方式運(yùn)行其service方法禽最,一個(gè)實(shí)例可以服務(wù)于多個(gè)請求,并且其實(shí)例一般不會銷毀,所以你的項(xiàng)目中如果只有一個(gè)servlet,那么web容器就只會創(chuàng)建一個(gè)實(shí)例净宵。所以其默認(rèn)非線程安全孟害,如果需要線程安全需要指明拒炎。
6.ServletConfig
作用:
★ 可以獲取servlet配置信息
★ 可以獲得ServletContext對象
6.1Servlet配置信息的獲取:
當(dāng)servlet配置了初始化參數(shù)后挨务,web容器在創(chuàng)建servlet實(shí)例對象時(shí)击你,會自動(dòng)將這些初始化參數(shù)封裝到ServletConfig對象中,并在調(diào)用servlet的init方法時(shí)谎柄,將ServletConfig對象傳遞給servlet丁侄。進(jìn)而,程序員通過ServletConfig對象就可以得到當(dāng)前servlet的初始化參數(shù)信息朝巫。
web.xml绒障。只要有ServletConfig對象就能調(diào)用getInitParameter方法。
<servlet>
<display-name>servletDemo4</display-name>
<servlet-name>ServletDemo4</servlet-name>
<servlet-class>com.cms.Demo1.Service.ServletDemo4</servlet-class>
<!-- 初始化參數(shù) -->
<init-param>
<param-name>encoding</param-name>
<param-value>GBK</param-value>
</init-param>
</servlet>
獲取配置信息:GBK
package com.cms.Demo1.Service;
import java.io.IOException;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* Servlet implementation class ServletDemo4
*/
public class ServletDemo4 extends HttpServlet {
private ServletConfig config;//config對象專門操作配置文件信息
@Override
public void init(ServletConfig config) throws ServletException {
// TODO Auto-generated method stub
this.config = config;
}
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String encoding = config.getInitParameter("encoding");//獲得配置文件中的信息
System.out.println(encoding);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
總結(jié):
這樣做的好處是:如果將數(shù)據(jù)庫信息捍歪、編碼方式等配置信息放在web.xml中户辱,如果以后數(shù)據(jù)庫的用戶名、密碼改變了糙臼,則直接很方便地修改web.xml就行了庐镐,避免了直接修改源代碼的麻煩。
獲取Servlet配置信息的方式(關(guān)鍵得到ServletConfig對象):
方式一:
方式二:
方式三:
7. ServletContext
ServletContext: 代表的是整個(gè)應(yīng)用变逃。一個(gè)應(yīng)用只有一個(gè)ServletContext對象必逆。單實(shí)例。
ServletContext與ServletConfig的區(qū)別:
作用:
a. 作為 域?qū)ο螅涸谝欢ǚ秶鷥?nèi)(當(dāng)前應(yīng)用),使多個(gè)Servlet共享數(shù)據(jù)名眉。
★ 域?qū)ο螅涸谝粋€(gè)可以被看見的范圍內(nèi)共享數(shù)據(jù)用到對象
★ 作用范圍:整個(gè)web應(yīng)用范圍內(nèi)共享數(shù)據(jù)
★ 生命周期:當(dāng)服務(wù)器啟動(dòng)web應(yīng)用加載后創(chuàng)建出ServletContext對象后粟矿,域產(chǎn)生。當(dāng)web應(yīng)用被移除出容器或服務(wù)器關(guān)閉损拢,隨著web應(yīng)用的銷毀域銷毀陌粹。
常用方法:
void setAttribute(String name,object value);//向ServletContext對象的map中添加數(shù)據(jù)
Object getAttribute(String name);//從ServletContext對象的map中取數(shù)據(jù)
void rmoveAttribute(String name);//根據(jù)name去移除數(shù)據(jù)
把數(shù)據(jù)添加到ServletContext的map里:
package com.cms.Demo1.Service;
import java.io.IOException;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* Servlet implementation class ServletDemo5
*/
public class ServletDemo5 extends HttpServlet {
/**
* @see HttpServoGet(HttpServletRequest request, HttpServletResponse response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//通過GenericServlet類 繼承的的getServletContext()方法得到ServletContext對象
ServletContext application = this.getServletContext();//輸完this.getServletContext() 后Ctrl+回車,對象ServletContext通常用application(應(yīng)用)表示福压。
//向ServletContext添加一個(gè)鍵值對
application.setAttribute("name", "value");
}
/**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
取出:
package com.cms.Demo1.Service;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* Servlet implementation class ServletDemo6
*/
public class ServletDemo6 extends HttpServlet {
/**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String name = (String) this.getServletContext().getAttribute("name");
System.out.println(name);
if(name==null){
System.out.println("你無權(quán)訪問");
}
System.out.println();
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
b. 獲取全局配置信息:
web.xml文件:
String類型--getInitParameter(String name) //根據(jù)配置文件中的key得到value
Java文件:
c.獲取資源路徑:
String getRealPath(String path);//根據(jù)資源名稱得到資源的絕對路徑.
可以得到當(dāng)前應(yīng)用任何位置的任何資源掏秩。
注意:
getRealPath的路徑是參考部署后(publish)的文件路徑
'/'代表當(dāng)前項(xiàng)目部署后的根目錄:D:\apache-tomcat-7.0.52\webapps\webService
實(shí)現(xiàn)Servlet的轉(zhuǎn)發(fā):
注意:
RequestDispatcher getRequestDispatcher(String path) ;//參數(shù)表示要跳轉(zhuǎn)到哪去