一淀零、Http方法:
- POST,GET,HEAD,TRACE,PUT,DELETE,OPTIONS,CONNECT(servlet API沒有處理doConnect()的機制幌氮,所以HttpServlet沒有doConnect())
MIME類型:響應(yīng)首部的值父虑。MIME類型告訴瀏覽器要接收的數(shù)據(jù)是什么類型恋捆。MIME類型值與HTTP請求首部的Accept所列的值有關(guān)妒峦。
Web服務(wù)器只提供靜態(tài)頁面杏节,動態(tài)內(nèi)容由其他應(yīng)用提供唯竹。
二乐导、容器的作用
- 通信支持。容器能提供方法讓servlet與web服務(wù)器對話浸颓,無需自己建立ServletSocket物臂、監(jiān)聽端口、創(chuàng)建流等产上。容器自己知道自己與web服務(wù)器之間的協(xié)議棵磷,所以只需要在servlet中實現(xiàn)業(yè)務(wù)邏輯。
- 生命周期管理晋涣。容器控制著servlet的生死仪媒,它負責(zé)加載類、實例化和初始化servlet谢鹊、調(diào)用servlet方法算吩,并使servlet實例能夠被垃圾回收。
- 多線程支持佃扼。容器會自動為接收到的每個servlet請求創(chuàng)建一個新的Java線程偎巢。針對某個客戶請求。如果servlet已經(jīng)運行完相應(yīng)的HTTP服務(wù)方法松嘶,這個線程就會結(jié)束艘狭。但仍需考慮同步問題。
- 生命方式實現(xiàn)安全翠订。
- JSP支持。容器負責(zé)把JSP代碼翻譯成Java遵倦。
三尽超、URL映射到servlet方法
- 部署描述文件(DD)。
<servlet>內(nèi)部名映射到完全限定類名梧躺。
<servlet-mapping>內(nèi)部名映射到公共URl名似谁。
- 注解傲绣。
四、容器處理請求過程
1.用戶點擊一個鏈接(指向的是非靜態(tài)頁面)巩踏,瀏覽器將請求數(shù)據(jù)發(fā)給容器秃诵。
2.容器創(chuàng)建兩個對象:HttpServletResponse和HttpServletRequest
3.容器根據(jù)請求中的URL找到正確的servlet,為這個請求創(chuàng)建或分配一個線程塞琼,并把請求和響應(yīng)對象傳遞給servlet菠净。
4.容器調(diào)用servlet的service()方法,根據(jù)請求的不同彪杉,service()方法調(diào)用doGet()或doPost()方法毅往。
5.doGet()生成動態(tài)頁面,并把頁面填入響應(yīng)對象派近。
6.線程結(jié)束攀唯,容器把響應(yīng)對象轉(zhuǎn)換成HTTP響應(yīng),把它返回給客戶渴丸,然后刪除請求和響應(yīng)對象侯嘀。
有請求分派時:
5.為請求對象增加一個屬性,供JSP使用谱轨。(request.setAttribute())
6.servlet把請求轉(zhuǎn)發(fā)給JSP残拐。
7.JSP從請求對象得到回答,為容器生成一個頁面碟嘴。
8.容器把頁面返回溪食。
五、servlet&JSP中的MVC(模型-視圖-控制器)
把業(yè)務(wù)邏輯從servlet抽出來放在模型中娜扇。
- 模型错沃。可重用的普通Java類雀瓢。只有模型與數(shù)據(jù)庫通信枢析。
- 控制器(servlet)。從請求獲得用戶輸入刃麸,告訴模型自行更新醒叁,并讓視圖得到更新的模型狀態(tài)。
- 視圖(JSP)泊业。從控制器得到模型的狀態(tài)把沼。獲得用戶輸入并提交給控制器。
六吁伺、J2EE&web容器&EJB組件
- 一個完全兼容的J2EE應(yīng)用服務(wù)器必須包括一個web容器和一個EJB容器饮睬。
- Tomcat只是一個web容器,不是完整的J2EE應(yīng)用服務(wù)器篮奄。
- 如今捆愁,EJB都作為完整的J2EE服務(wù)器的一部分割去,但獨立的web容器仍存在。
- 獨立的web容器通常配置為與一個HTTP web服務(wù)器(如Apache)協(xié)作昼丑,但tomcat本身就可以作為一個基本的HTTP服務(wù)器呻逆,但功能方面沒有Apache健壯。所以通常非EJB web應(yīng)用會結(jié)合使用Apache和Tomcat菩帝。
【注】
Apache是設(shè)計服務(wù)于靜態(tài)web頁面的web服務(wù)器咖城。
Tomcat是一個Servlet/Jsp容器,它同時也作為一個web服務(wù)器使用胁附。Tomcat = ( Web Server + Servlet container + JSP environment )酒繁,因為我們知道JSP也是轉(zhuǎn)譯為Servlet的,Tomcat接收請求之后控妻,如果是JSP頁面的話州袒,Tomcat里面的JSP引擎可以將JSP轉(zhuǎn)換為Servlet類。
七弓候、應(yīng)用服務(wù)器和web服務(wù)器的區(qū)別
- 應(yīng)用服務(wù)器就是提供應(yīng)用的服務(wù)器郎哭,這里的應(yīng)用有很多,比如java應(yīng)用菇存,ruby 應(yīng)用夸研,或者 c#應(yīng)用。應(yīng)用服務(wù)器也提供了http服務(wù)依鸥,比如tomcat亥至。
- web服務(wù)器就是提供了web功能的服務(wù)器,主要就是http服務(wù)贱迟,包括圖片的下載等一系列和web相關(guān)的姐扮。優(yōu)點是在處理靜態(tài)信息上。例如一些靜態(tài)的html衣吠,圖片等其他靜態(tài)的東西茶敏。
Tomcat&Apache
Tomcat服務(wù)器是一個免費的開放源代碼的Web應(yīng)用服務(wù)器。因為Tomcat技術(shù)先進缚俏、性能穩(wěn)定且免費惊搏,所以深受Java愛好者的喜愛并得到了部分軟件開發(fā)商的認可,成為目前比較流行的Web應(yīng)用服務(wù)器忧换。
到目前為止恬惯,Tomcat一直被認為是Servlet/JSP API的執(zhí)行器,也就所謂的Servlet容器包雀。然而宿崭,Tomcat并不僅僅如此,它還提供了JNDI和JMX API的實現(xiàn)機制才写。盡管如此葡兑,Tomcat仍然還不能算是應(yīng)用服務(wù)器,因為它不提供大多數(shù)J2EE API的支持赞草。
Tomcat是提供一個支持Servlet和JSP運行的容器讹堤。Servlet和JSP能根據(jù)實時需要,產(chǎn)生動態(tài)網(wǎng)頁內(nèi)容厨疙。而對于Web服務(wù)器來說洲守, Apache僅僅支持靜態(tài)網(wǎng)頁,對于支持動態(tài)網(wǎng)頁就會顯得無能為力沾凄;Tomcat則既能為動態(tài)網(wǎng)頁服務(wù)梗醇,同時也能為靜態(tài)網(wǎng)頁提供支持。盡管它沒有通常的Web服務(wù)器快撒蟀、功能也不如Web服務(wù)器豐富叙谨,但是Tomcat逐漸為支持靜態(tài)內(nèi)容不斷擴充。大多數(shù)的Web服務(wù)器都是用底層語言編寫如C保屯,利用了相應(yīng)平臺的特征手负,因此用純Java編寫的Tomcat執(zhí)行速度不可能與它們相提并論。
一般來說华嘹,大的站點都是將Tomcat與Apache的結(jié)合罕模,Apache負責(zé)接受所有來自客戶端的HTTP請求卧檐,然后將Servlets和JSP的請求轉(zhuǎn)發(fā)給Tomcat來處理。Tomcat完成處理后统捶,將響應(yīng)傳回給Apache,最后Apache將響應(yīng)返回給客戶端柄粹。
八喘鸟、servlet周期與方法
與servlet有關(guān)的所有一切(除了JSP)都在javax.servlet和javax.servlet.http中。
不存在——>初始化
容器要加載類镰惦,調(diào)用servlet的無參數(shù)構(gòu)造函數(shù)迷守,并調(diào)用servlet的init()方法,從而初始化servlet旺入。
servlet接口方法:init(可能覆蓋)兑凿,service(不覆蓋),destroy
- init總是在第一個service調(diào)用之前完成茵瘾,在servlet的一生中只調(diào)用一次礼华。
- 容器運行多個線程來處理對一個servlet的多個請求。
- 若應(yīng)用分布在多個JVM上拗秘,則每個JVM都有一個servlet實例圣絮。
ServletConfig對象和ServletContext
ServleConfig:
- 每個servlet都有一個ServletConfig對象
- 用于向servlet傳遞部署時信息
- 用于訪問ServletContext
ServletContext
- 每個Web有一個
- 用于訪問Web應(yīng)用參數(shù)
容器實現(xiàn)HttpServletRequest和HttpServletResponse接口。
九雕旨、Get和POST的區(qū)別
- POST有體扮匠。
- 安全性捧请。使用GET時,參數(shù)數(shù)據(jù)會顯示在瀏覽器的輸入欄中(URL后面用棒搜?分隔)
- 書簽疹蛉。GET請求可以建立書簽。POST則不能力麸。
- 冪等可款。GET是冪等的,不會對服務(wù)器做出任何改變克蚂;POST是非冪等的闺鲸,是一個更新,可使用POST體的數(shù)據(jù)來修改服務(wù)器(更新數(shù)據(jù)庫)埃叭。
【注】HTTP中的GET是冪等的摸恍,但是你可以在servlet中實現(xiàn)一個非冪等的doGet方法。
<form method="POST" action="action.beer"> // 默認是GET請求
十游盲、請求
從請求對象可以得到參數(shù)误墓,客戶的平臺和瀏覽器信息,與請求相關(guān)的益缎,與客戶相關(guān)的會話谜慌,請求的HTTP方法,請求的輸入流莺奔。
String client = request.getHeader("User-Agent");
Cookie[] cookies = cookie(request.getCookies();
HttpSession session = request.getSession();
String method = request.getMethod();
InputStream input = request.getInputStream();
十一欣范、響應(yīng)
返回類型(MIME)和輸出
ServletResponse接口只提供了兩個流:ServletOutputStream(字節(jié))和PrintWriter(字符)。
PrintWriter實際上包裝了ServletOutputStream令哟。
PrintWriter writer = response.getWriter();
writer.println("字符");
ServletOutputStream out = response.getOutputStream();
out.write();
十二恼琼、重定向和請求分派
重定向是讓瀏覽器完成工作。
請求分派是在服務(wù)端做工作屏富。(客戶并不關(guān)心是誰做出響應(yīng))
// 重定向
respons.sendRedirect("URL");
// 請求分派
RequestDispatcher view = request.getRequestDispatcher("result.jsp");
view.forward(request.response);
十三晴竞、servlet初始化參數(shù)
容器從DD讀出servlet初始化參數(shù),并把這些參數(shù)交給ServletConfig狠半,然后把ServletConfig傳遞給servlet的init()方法噩死。
servlet初始化參數(shù)只能讀取一個,就是在容器初始化servlet的時候神年。
【注】若初始化參數(shù)的值經(jīng)常變化已维,最好讓servlet從一個文件或者數(shù)據(jù)庫得到值,但這種方法意味著每次servlet代碼運行時都會有更多的開銷已日,而不是只在初始化的時候才有垛耳。
【過程】
1.容器為這個servlet讀取部署描述文件,包括servlet初始化參數(shù)(<init-param>)
2.容器為這個servlet創(chuàng)建一個新的ServletConfig實例。
- 容器為每個servlet初始化參數(shù)創(chuàng)建一個String名/值對堂鲜。(來自DD的初始化參數(shù))
- 容器向ServletConfig提供名/值初始化參數(shù)的引用栈雳。
- 容器創(chuàng)建servlet類的一個新實例。
- 容器調(diào)用servletdeinit()方法泡嘴,傳入ServletConfig引用甫恩。
十四逆济、請求屬性(針對一個servlet)
請求對象設(shè)置屬性(名/值對酌予,值可以是任何對象,若是對象需要判斷是否為空)奖慌,得到請求的任何servlet和JSP都能使用這些屬性抛虫。
request.setAttribute("styles",result);
十五、上下文初始化參數(shù)(針對整個web應(yīng)用)(<context-param>简僧,不在<servlet>元素內(nèi))
應(yīng)用中所有的servlet和JSP都能訪問上下文初始化參數(shù)建椰,而不必為每個servlet都配置DD。
Web應(yīng)用初始化過程:
- 容器讀取DD岛马,對應(yīng)每個<Context-param>創(chuàng)建一個名/值對棉姐。
- 容器創(chuàng)建ServletContext的一個新實例。
- 容器為ServletContext提供上下文初始化參數(shù)各個名/值對的引用啦逆。
- 在一個Web應(yīng)用中部署的各個servlet和JSP都能訪問同一個ServletContext伞矩。
【注】
- 如果應(yīng)用是分布式的,那么每個JVM有一個ServletContext夏志。
- 上下文參數(shù)最常見的用途是存儲數(shù)據(jù)庫查找名乃坤。
十六.監(jiān)聽者(ServletContextListener)(8個)
1.上下文事件監(jiān)聽者
作用:監(jiān)聽ServletContext的初始化和撤銷。在應(yīng)用為客戶提供服務(wù)之前運行一些代碼沟蔑。如讀取上下文參數(shù)湿诊,創(chuàng)建一個對象并把這個對象設(shè)置為ServletContext屬性,以便servlet獲取瘦材。
上下文參數(shù)只能是String厅须。若servlet想共享某個對象,就需要用監(jiān)聽者食棕。
用法:
- 創(chuàng)建一個監(jiān)聽者類朗和,實現(xiàn)ServletContextListener接口。把它放在WEB-INF/classes目錄中宣蠕,并在部署文件中放<listener>元素告訴容器例隆。
- 屬性類,有監(jiān)聽者類創(chuàng)建抢蚀,并在監(jiān)聽者類中設(shè)置在ServletContext屬性中镀层。
十七、屬性作用域:上下文、請求唱逢、會話
分別有ServletContext吴侦、ServletRequest、HttpSession接口處理坞古。
方法:
Object getAttribute(String name)
void setAttribute(String name,Object value)
void removeAttribute(String name)
Enumeration getAttributeNames()
1.上下文(希望整個應(yīng)用程序共享备韧,如數(shù)據(jù)庫連接,email地址)
- 不是線程安全的痪枫。因為每個servlet都可以訪問织堂,所以多個servlet則有多個線程,請求是并發(fā)處理的奶陈,不論這些請求指向同一個servlet還是不同的servlet易阳。
- 同步問題。對servlet加鎖(對其doGet()或doPost()方法)只能保證servlet一次只能運行一個線程吃粒,但不能保證其他servlet或JSP訪問這個屬性潦俺。對于上下文加鎖才能保證同步。
(synchronized(getServletContext()){
getServletContext().setAttribute();
}
2.會話(與客戶會話有關(guān)的資源和數(shù)據(jù)徐勃,如購物車)
- 不是線程安全的(一個客戶同時做出多個請求:當(dāng)你打開一個新的瀏覽器窗口事示,并創(chuàng)建同一個請求,此時新建一個servlet)
- 同步僻肖。
synchronized(session){
session.setAttribute();
}
【注】同步時要讓同步塊盡可能小肖爵。
3.請求(將模型信息從控制器傳遞給視圖)
- 線程安全的。
【注】
如果需要線程安全檐涝,就不要使用實例變量遏匆,因為servlet的所有線程都可以處理實例變量,(實現(xiàn)了SingleThreadModel或者同步服務(wù)方法可以谁榜,但是會導(dǎo)致性能很差)幅聘,所以servlet的實例變量都是final。
servlet只有一個實例窃植,但可以有多個線程帝蒿,若希望多個線程都能訪問某個值,可以將其聲明為服務(wù)方法中的局部變量或者在合適的作用域中使用屬性巷怜。