1.web服務(wù)器(web server)和應(yīng)用服務(wù)器(appliction server)的區(qū)別是什么有决?
web服務(wù)器的任務(wù)是處理客戶端的http請(qǐng)求并響應(yīng)相對(duì)應(yīng)的html頁(yè)面。web服務(wù)器能理解http語(yǔ)言并運(yùn)行在http協(xié)議之上。Apache web服務(wù)器就是一種web服務(wù)器脚翘,此外能夠執(zhí)行servlet和jsp的容器我們稱之為servlet容器捕犬,比如tomcat哭靖。
應(yīng)用服務(wù)器提供一些額外的特性比如jms支持,事務(wù)管理的支持等等趟卸。所以我們說應(yīng)用服務(wù)器就是一個(gè)web服務(wù)器加上一些額外的功能以幫助開發(fā)者開發(fā)一些企業(yè)級(jí)應(yīng)用。
2.get和post方法的區(qū)別是什么氏义?
(1)get方法提交的參數(shù)會(huì)通過url傳遞锄列,而post提交的內(nèi)容是放在請(qǐng)求體中的。
(2)get傳送的數(shù)據(jù)量比較小惯悠,post傳送的數(shù)據(jù)量比較大邻邮,通常認(rèn)為不受限制。
(3)get方法不安全因?yàn)閷魉蛿?shù)據(jù)暴露在url上克婶,而post則不存在這個(gè)問題筒严。
(4)超鏈接和表單的默認(rèn)提交方式都是get。
3.MIME類型是什么情萤?
響應(yīng)頭的“content-type”值就是一個(gè)典型的MIME類型鸭蛙。那什么是mime類型呢?服務(wù)器發(fā)送mime類型給客戶端使其知道服務(wù)端返回的數(shù)據(jù)類型是什么筋岛。這幫助客戶端如何顯示數(shù)據(jù)娶视。一些常用的mime類型有text/html,text/html,application/xml等。
我們可以使用ServletContext對(duì)象的getMimeType(file)方法獲取一個(gè)文件正確的mime類型睁宰,然后使用這個(gè)類型去設(shè)置響應(yīng)頭的content type(即response.setContentType())肪获。當(dāng)需要從服務(wù)器下載文件時(shí)這種方法非常有用。
4.什么是web應(yīng)用勋陪,其目錄結(jié)構(gòu)是怎樣的贪磺?
web應(yīng)用就是一個(gè)可以運(yùn)行在服務(wù)器上的提供靜態(tài)和動(dòng)態(tài)內(nèi)容給客戶端瀏覽器的一個(gè)模型。目錄結(jié)構(gòu)如下:
5.servlet容器的任務(wù)有哪些诅愚?
servlet容器也叫web容器寒锚,比如tomcat。它的主要職責(zé)如下:
(1)提供通信支持(communication support):容器為web服務(wù)器和servlet/jsp提供了便捷的通信方式违孝。正是由于web容器刹前,我們不再需在服務(wù)端創(chuàng)建一個(gè)服務(wù)端socket對(duì)象監(jiān)聽、解析任何請(qǐng)求以及生成響應(yīng)雌桑。所有這些重要且復(fù)雜的工作統(tǒng)統(tǒng)由容器為我們完成喇喉,我們僅僅需要關(guān)注我們自己應(yīng)用的業(yè)務(wù)邏輯而已。
(2)生命周期和資源管理(lifecycle and resource management):容器管理所有servlet的生命周期校坑,它還負(fù)責(zé)加載servlet到內(nèi)存拣技,初始化servler千诬,執(zhí)行servlet中的方法以及銷毀servlet,容器同時(shí)還提供諸如JNDI(java命名與目錄服務(wù))的資源管理工具膏斤。
(3)多線程支持(multitheading support):容器為每個(gè)請(qǐng)求創(chuàng)建一個(gè)新的線程并當(dāng)請(qǐng)求結(jié)束時(shí)及時(shí)摧毀線程徐绑。servlet只有一個(gè)實(shí)例,容器并不會(huì)為每個(gè)請(qǐng)求生成單獨(dú)的servlet莫辨,這必然節(jié)省了時(shí)間和空間傲茄。
(4)支持jsp(jsp support):jsp跟普通java類還是有區(qū)別的,web容器對(duì)此也是提供支持的沮榜。每個(gè)jsp頁(yè)面在被容器編譯后會(huì)生成對(duì)應(yīng)的servlet盘榨,然后容器就像管理servlet一樣管理它們。
(5)多任務(wù)(miscellaneous task):web容器管理資源池蟆融,做內(nèi)存優(yōu)化草巡,運(yùn)行g(shù)c,提供安全配置振愿,提供多應(yīng)用的支持捷犹,熱部署,以及其他一些我們沒法看到的工作冕末。
6.ServletContext對(duì)象和ServletConfig對(duì)象的區(qū)別萍歉?
(1)每個(gè)servlet都會(huì)有自己獨(dú)有的servletConfig對(duì)象而servletContext對(duì)象是整個(gè)web應(yīng)用共享的。
(2)servletConfig提供servlet的初始化參數(shù)(init-param),僅該servlet可以訪問档桃。而servletContext提供的初始化參數(shù)整個(gè)web應(yīng)用的所有servlet都可以訪問枪孩。
(3)servletContext對(duì)象提供了setAttribute方法設(shè)置共享參數(shù),而servletConfig并沒有對(duì)應(yīng)的set方法藻肄。
7.RequestDispatcher是什么蔑舞?
RequestDispatcher接口用來將請(qǐng)求轉(zhuǎn)發(fā)給同一個(gè)應(yīng)用下的另一資源比如servlet,jsp嘹屯,html等(forward)攻询。當(dāng)然我們也可以將另一資源處理的結(jié)果包含進(jìn)來一起返回給客戶端(include).這個(gè)接口用于同一上下文環(huán)境下的servlet間的通訊。
8.PrintWriter和ServletOutPutStream類有什么區(qū)別州弟?
PrintWriter是字符流钧栖,ServletOutputStream是字節(jié)流∑畔瑁可以通過PrintWriter向?yàn)g覽器輸出字符數(shù)組或者是字符串拯杠。也可以通過ServletOutPutStream向?yàn)g覽器端輸出字節(jié)數(shù)組。
PrintWriter對(duì)象在servlet中可以通過response.getWriter()方法獲取
ServletOutputStream對(duì)象通過response.getOutputStream方法獲取啃奴。
9.在一個(gè)servlet能否同時(shí)獲取PrintWriter和ServletOutputStream對(duì)象潭陪。
不可以,如果同時(shí)獲取,將會(huì)拋出java.lang.IllegalStateException異常依溯。
10.在servlet中能否產(chǎn)生類似死鎖情況老厌?
可以的,你在doPost方法中調(diào)用doGet方法黎炉,在doGet方法中調(diào)用doPost方法梅桩,將產(chǎn)生死鎖(最終會(huì)拋出stackoverflow異常)。
11.servlet包裝類有什么用拜隧?
servletAPI提供了兩個(gè)包裝類:HttpServletRequestWrapper類和HttpServletResponseWrapper類,這些包裝類幫助開發(fā)者給出request和response的一般實(shí)現(xiàn)趁仙。我們可以繼承它們并選擇我們需要復(fù)寫的方法進(jìn)行復(fù)寫(包裝設(shè)計(jì)模式)洪添,而不用復(fù)寫所有的方法。
12.SingleThreadModel接口是什么雀费?
這個(gè)接口提供了線程安全機(jī)制干奢,它保證了同一時(shí)刻不可能有兩個(gè)線程并發(fā)執(zhí)行servlet的service方法。但是這個(gè)方法并沒有解決所有的線程安全問題盏袄,比如同一時(shí)刻兩個(gè)線程仍然可以訪問到session和靜態(tài)常量中的內(nèi)容忿峻。而且這個(gè)方法也讓servlet喪失多線程的優(yōu)勢(shì),所以在servlet2.4中這個(gè)方法被聲明為過時(shí)辕羽。
13.是否有必要重寫service方法逛尚?
一般情況下是沒有必要的,因?yàn)閟ervice方法會(huì)根據(jù)請(qǐng)求的類型(get刁愿、post等)將請(qǐng)求分發(fā)給doxxx方法去執(zhí)行绰寞。即使我們需要在處理請(qǐng)求之前需要做一些額外的事,我們也可以通過過濾器或監(jiān)聽器完成铣口。
14.Servlet是否線程安全滤钱?如何創(chuàng)建線程安全的servlet?
HttpServlet的init和destroy方法在servlet聲明周期中僅調(diào)用一次脑题,所以不用擔(dān)心它們的線程安全件缸。但是service方法以及doget,dopost等方法是存在線程安全問題的叔遂,因?yàn)閟ervlet容器為每一個(gè)客戶端請(qǐng)求都創(chuàng)建一個(gè)線程他炊,這些線程在同一時(shí)刻可能訪問同一個(gè)servlet的service方法,所以我們?cè)谑褂眠@些方法時(shí)務(wù)必小心掏熬。
如何創(chuàng)建線程安全的servlet佑稠?(SingleThreadModel方法不算)
1.盡量使用局部變量,減少全局變量的使用旗芬。
2.對(duì)于共享變量舌胶,加上關(guān)鍵字synchronized。
注:servlet中常見線程安全與不安全的對(duì)象:
線程安全:ServletRequest疮丛,ServletResponse
線程不安全:ServletContext幔嫂,HttpSession辆它。
對(duì)于ServletContext,我們應(yīng)盡量減少該對(duì)象中屬性的修改履恩。
而HttpSession對(duì)象在用戶會(huì)話期間存在锰茉,只能在處理屬于同一個(gè)Session的請(qǐng)求的線程中被訪問,因此Session對(duì)象的屬性訪問理論上是線程安全的切心。但是當(dāng)用戶打開多個(gè)同屬于一個(gè)進(jìn)程的瀏覽器窗口飒筑,在這些窗口的訪問屬于同一個(gè)Session,會(huì)出現(xiàn)多次請(qǐng)求绽昏,需要多個(gè)工作線程來處理請(qǐng)求协屡,可能造成同時(shí)多線程讀寫屬性
15.sevlet中的屬性域。
servlet提供了一些域?qū)ο蠓奖銉?nèi)部servlet之間的通信全谤,我們可以通過set/get方法為web應(yīng)用設(shè)置或取出屬性值肤晓。servlet提供3個(gè)域(和jsp區(qū)分開來):
1.request scope
2.session scope
3.application scope
分別由ServletRequest,HttpSession,ServletContext對(duì)象提供對(duì)應(yīng)的set/get/remove方法去操作者三個(gè)域。
注:這跟web.xml中為servletConfig(針對(duì)單個(gè)servlet)和servletContext(針對(duì)web應(yīng)用)定義的初始化參數(shù)不一樣认然。
16如何調(diào)用另一個(gè)web應(yīng)用的servlet/jsp等資源补憾?
不能使用RequestDispatcher類,因?yàn)檫@個(gè)類只能訪問本應(yīng)用本身的資源卷员∮遥可以使用Response的sendRediect(url)方法子刮,這個(gè)訪問會(huì)返回狀態(tài)碼302給瀏覽器然后請(qǐng)求一個(gè)新的url威酒。如果我們需要攜帶一些數(shù)據(jù),可以在response對(duì)象中加上cookie挺峡。
17.請(qǐng)求轉(zhuǎn)發(fā)(forward)和請(qǐng)求重定向(sendRediect)的區(qū)別葵孤?
轉(zhuǎn)發(fā)是服務(wù)器行為,重定向是客戶端行為橱赠。兩個(gè)動(dòng)作的工作流程如下:
轉(zhuǎn)發(fā)過程:客戶瀏覽器發(fā)送http請(qǐng)求----》web服務(wù)器接受此請(qǐng)求--》調(diào)用內(nèi)部的一個(gè)方法在容器內(nèi)部完成請(qǐng)求處理和轉(zhuǎn)發(fā)動(dòng)作----》將目標(biāo)資源發(fā)送給客戶尤仍;在這里,轉(zhuǎn)發(fā)的路徑必須是同一個(gè)web容器下的url狭姨,其不能轉(zhuǎn)向到其他的web路徑上去宰啦,中間傳遞的是自己的容器內(nèi)的request。在客戶瀏覽器路徑欄顯示的仍然是其第一次訪問的路徑饼拍,也就是說客戶是感覺不到服務(wù)器做了轉(zhuǎn)發(fā)的赡模。轉(zhuǎn)發(fā)行為是瀏覽器只做了一次訪問請(qǐng)求。
重定向過程:客戶瀏覽器發(fā)送http請(qǐng)求----》web服務(wù)器接受后發(fā)送302狀態(tài)碼響應(yīng)及對(duì)應(yīng)新的location給客戶瀏覽器--》客戶瀏覽器發(fā)現(xiàn)是302響應(yīng)师抄,則自動(dòng)再發(fā)送一個(gè)新的http請(qǐng)求漓柑,請(qǐng)求url是新的location地址----》服務(wù)器根據(jù)此請(qǐng)求尋找資源并發(fā)送給客戶。在這里location可以重定向到任意URL,既然是瀏覽器重新發(fā)出了請(qǐng)求辆布,則就沒有什么request傳遞的概念了瞬矩。在客戶瀏覽器路徑欄顯示的是其重定向的路徑,客戶可以觀察到地址的變化的锋玲。重定向行為是瀏覽器做了至少兩次的訪問請(qǐng)求的景用。
18.HttpServlet為什么聲明為抽象類?
httpServlet類雖然是抽象類但卻沒有抽象方法惭蹂,之所以這樣設(shè)計(jì)伞插,是因?yàn)閐oget,dopost等方法并沒有業(yè)務(wù)邏輯盾碗,開發(fā)者至少應(yīng)該重寫一個(gè)service中的方法蜂怎,這就是我們不能實(shí)例化HttpServlet的原因。
19.servlet的生命周期置尔?
servlet容器負(fù)責(zé)管理servlet的生命周期,servlet生命周期如下:
(1) 加載和實(shí)例化
Servlet 容器裝載和實(shí)例化一個(gè) Servlet氢伟。創(chuàng)建出該 Servlet 類的一個(gè)實(shí)例榜轿。
(2) 初始化
在 Servlet 實(shí)例化完成之后,容器負(fù)責(zé)調(diào)用該 Servlet 實(shí)例的 init() 方法朵锣,在處理用戶請(qǐng)求之前谬盐,來做一些額外的初始化工作。
(3) 處理請(qǐng)求
當(dāng) Servlet 容器接收到一個(gè) Servlet 請(qǐng)求時(shí)诚些,便運(yùn)行與之對(duì)應(yīng)的 Servlet 實(shí)例的 service() 方法飞傀,service() 方法再派遣運(yùn)行與請(qǐng)求相對(duì)應(yīng)的
doXX(doGet,doPost) 方法來處理用戶請(qǐng)求诬烹。
(4) 銷毀
當(dāng) Servlet 容器決定將一個(gè) Servlet 從服務(wù)器中移除時(shí) ( 如 Servlet 文件被更新 )砸烦,便調(diào)用該 Servlet 實(shí)例的 destroy() 方法,在銷毀該 Servlet 實(shí)例之前绞吁,
來做一些其他的工作幢痘。
其中,(1)(2)(4) 在 Servlet 的整個(gè)生命周期中只會(huì)被執(zhí)行一次家破。
1.servlet工作過程時(shí)序圖:
2.servlet生命周期流程圖:
20.servlet生命周期方法有哪些颜说?
共有3個(gè)方法:
public void init(ServletConfig config):
這個(gè)方法是由servlet容器調(diào)用用來初始化servlet的,這個(gè)方法在servlet生命周期中僅被調(diào)用一次汰聋。
public void service(ServletRequest request, ServletResponse response)
servlet容器為每個(gè)客戶端創(chuàng)建線程门粪,然后都會(huì)執(zhí)行service方法钩蚊,但執(zhí)行此方法前init方法必須已經(jīng)被執(zhí)行了拢蛋。
public void destroy()
servlet從servlet容器中被移除時(shí)會(huì)調(diào)用此方法,僅被調(diào)用一次灵疮。
21.我們?yōu)槭裁磻?yīng)該重寫無參的init方法(而不是有參的)?**
當(dāng)我們希望servlet在處理請(qǐng)求之前加載一些資源時(shí)措近,我們應(yīng)該重寫init方法溶弟。但是GenericServlet類中定義了兩個(gè)init方法:
public void init(ServletConfig config)
public void init()
官方推薦我們重寫無參的init方法,因?yàn)橥ㄟ^查看源碼我們可以知道瞭郑,其實(shí)有參的init方法會(huì)調(diào)用無參的init方法辜御,如果我們重寫有參的init方法,那么必須先執(zhí)行super.init(config),否則可能會(huì)產(chǎn)生空指針屈张。
22.什么是URL重寫擒权?
我們知道HttpSession是基于Cookie工作的,如果瀏覽器禁用Cookie將導(dǎo)致session失效阁谆。ServletAPI提供了一種URL重寫的機(jī)制用于處理這種情形碳抄。
我們只需調(diào)用HttpServletResponse對(duì)象的encodeURL方法即可,而且這種方法僅當(dāng)瀏覽器禁用cookie才會(huì)編碼场绿,否則返回原url剖效。當(dāng)我們希望攜帶session信息重定向到另一資源上時(shí),我們可以使用encodeRediectURL方法焰盗。
23.servlet API對(duì)cookie的支持?
cookie在c/s通信方面應(yīng)用很廣泛璧尸,并非java獨(dú)有。cookie是服務(wù)器端發(fā)給瀏覽器并在瀏覽器上保存的一段文本數(shù)據(jù)熬拒。
ServletAPI中的javax.servlet.http.Cookie類為cookie提供了支持爷光。HttpServletRequest 對(duì)象的getCookies方法從request中獲取cookie數(shù)組。HttpServletResponse對(duì)象的addCookie方法將一個(gè)cookie返回給瀏覽器澎粟。
24.如何當(dāng)session失效時(shí)喚醒一些對(duì)象蛀序?
可以讓這個(gè)對(duì)象實(shí)現(xiàn)javax.servlet.http.HttpSessionBindingListener接口,這是一個(gè)監(jiān)聽器活烙,有兩個(gè)方法:valueBound和valueUnbound方法徐裸,具體使用請(qǐng)查看文檔說明。
25.servlet過濾器的作用啸盏?
1.打印一些請(qǐng)求參數(shù)到日志中
2.授權(quán)請(qǐng)求訪問資源
3.在將請(qǐng)求提交給servlet之前倦逐,對(duì)request請(qǐng)求頭或請(qǐng)求體進(jìn)行一些格式化的處理
4.將響應(yīng)數(shù)據(jù)進(jìn)行壓縮再返回給瀏覽器。
5.解決亂碼問題宫补。
26.servlet監(jiān)聽器的作用檬姥?
監(jiān)聽客戶端的請(qǐng)求,服務(wù)器端的操作等粉怕。通過監(jiān)聽器健民,可以自動(dòng)激發(fā)一些操作,比如監(jiān)聽在線的用戶數(shù)量(當(dāng)增加一個(gè)HttpSession時(shí)贫贝,就自動(dòng)觸發(fā)sessionCreated(HttpSessionEvent se)方法秉犹,在這個(gè)方法中就可以統(tǒng)計(jì)在線人數(shù)了),另外還可以用來初始化一些資源蛉谜,比如數(shù)據(jù)庫(kù)連接池等(web.xml中配置的context-param只能是字符串不能使對(duì)象,這時(shí)就得使用ServletContextListener了崇堵,注意型诚,有讀者可能說ServletConext的setAttribute不是可以設(shè)置對(duì)象嗎?但是這是在servlet創(chuàng)建之后才能調(diào)用的方法鸳劳,如果希望web應(yīng)用一啟動(dòng)就產(chǎn)生初始參數(shù)必須使用監(jiān)聽器)狰贯。
27.web.xml中組件的加載順序
context-param -> listener -> filter -> servlet
而同個(gè)類型之間的實(shí)際程序調(diào)用的時(shí)候的順序是根據(jù)對(duì)應(yīng)的 mapping 的順序進(jìn)行調(diào)用的
28.如何處理servlet拋出的異常?
記住赏廓,不可以將異常信息日志顯示給瀏覽器涵紊。當(dāng)出現(xiàn)異常時(shí),可以返回主頁(yè)幔摸,或者顯示出錯(cuò)的原因摸柄。可以在web.xml中配置錯(cuò)誤頁(yè)面:
<error-page>
<error-code>404</error-code>
<location>/AppExceptionHandler</location>
</error-page>
<error-page>
<exception-type>javax.servlet.ServletException</exception-type>
<location>/AppExceptionHandler</location>
</error-page>
29.如何確保servlet在應(yīng)用啟動(dòng)之后被加載到內(nèi)存既忆?
通常情況下都是客戶端請(qǐng)求一個(gè)servlet驱负,這個(gè)servlet才會(huì)被加載到內(nèi)存,但對(duì)于某些很大加載很耗時(shí)的servlet我們希望應(yīng)用啟動(dòng)時(shí)就加載它們患雇,這時(shí)我們可以在web.xml文件中配置或者使用webServlet注解(servlet3.0)告訴容器系統(tǒng)一啟動(dòng)就加載:
<servlet>
<servlet-name>foo</servlet-name>
<servlet-class>com.foo.servlets.Foo</servlet-class>
<load-on-startup>5</load-on-startup>
</servlet>
load-on-startup節(jié)點(diǎn)中必須配置一個(gè)整數(shù)电媳,整數(shù)代表應(yīng)用一啟動(dòng)就會(huì)被加載,負(fù)數(shù)表示當(dāng)客戶端請(qǐng)求之后才加載庆亡,正數(shù)的值越小,說明越先被加載捞稿。
30.如何獲取資源在文件系統(tǒng)中的絕對(duì)路徑又谋?
getServletContext().getRealPath(path),path是以‘/’開頭的相對(duì)路徑娱局。
31.如何獲取服務(wù)器的信息彰亥?
getServletContext().getServerInfo()方法,一般返回服務(wù)器明衰齐,版本號(hào)任斋,比如:Apache Tomcat/6.0.37
32.如何在servlet中使用數(shù)據(jù)庫(kù)?
如果web應(yīng)用使用數(shù)據(jù)庫(kù)的地方很多耻涛,最好在ServletContextListener中初始化它废酷,并設(shè)置為context 屬性以便其他servlet使用。
33.如何在servlet中獲取客戶端的ip地址抹缕?
request.getRemoteAddr()方法
34.servlet3.0的重要特性澈蟆?
異步處理支持:有了該特性,Servlet 線程不再需要一直阻塞卓研,直到業(yè)務(wù)處理完畢才能再輸出響應(yīng)趴俘,最后才結(jié)束該 Servlet 線程睹簇。在接收到請(qǐng)求之后,Servlet 線程可以將耗時(shí)的操作委派給另一個(gè)線程來完成寥闪,自己在不生成響應(yīng)的情況下返回至容器太惠。針對(duì)業(yè)務(wù)處理較耗時(shí)的情況,這將大大減少服務(wù)器資源的占用疲憋,并且提高并發(fā)處理速度凿渊。
新增的注解支持:該版本新增了若干注解,用于簡(jiǎn)化 Servlet柜某、過濾器(Filter)和監(jiān)聽器(Listener)的聲明嗽元,這使得 web.xml 部署描述文件從該版本開始不再是必選的了。
可插性支持:熟悉 Struts2 的開發(fā)者一定會(huì)對(duì)其通過插件的方式與包括 Spring 在內(nèi)的各種常用框架的整合特性記憶猶新喂击。將相應(yīng)的插件封裝成 JAR 包并放在類路徑下剂癌,Struts2 運(yùn)行時(shí)便能自動(dòng)加載這些插件。現(xiàn)在 Servlet 3.0 提供了類似的特性翰绊,開發(fā)者可以通過插件的方式很方便的擴(kuò)充已有 Web 應(yīng)用的功能佩谷,而不需要修改原有的應(yīng)用。
HttpServletRequest 對(duì)文件上傳的支持:此前监嗜,對(duì)于處理上傳文件的操作一直是讓開發(fā)者頭疼的問題谐檀,因?yàn)?Servlet 本身沒有對(duì)此提供直接的支持,需要使用第三方框架來實(shí)現(xiàn)(file-upload)裁奇,而且使用起來也不夠簡(jiǎn)單桐猬。如今這都成為了歷史,Servlet 3.0 已經(jīng)提供了這個(gè)功能刽肠。
轉(zhuǎn)載自:https://blog.csdn.net/chdjj/article/details/18882973