最近面試,問了Servlet是什麼,當時也沒想那麼多,感覺知道怎麼用,用在那一層,用什麼語言實現,說下與JSP的區別就可以了,但是從面試的結果來看,面試官好像不是很認可,我們不能改變別人,只能讓自己無懈可擊,所以在網上書上找了些資料總結一下,感覺自己寫一下才是自己的東西。
一.什麼是Servlet
簡單的說Servlet使用Java語言實現的程序,運行於支持Java語言的Web服務器或者應用服務器中。Servlet先於JSP出現,提供和客戶端動態交互的功能。Servlet可以處理來自客戶端的HTTP請求,並生成響應返回給客戶端。
Servlet對於Web服務器而言,就好像是Java Applet對於Web瀏覽器,Servlet需要加在到Web服務器並在Web服務器內執行。
使用Servlet的基本流程如下:
客戶端通過HTTP提出請求。
Web服務器接受改請求並將其發給servlet。如果這個servlet尚未被加載,Web服務器將把它加載到Java虛擬機並且執行它。
Servlet將接收該HTTP請求執行某種處理。
Servlet將向Web服務器返回應答。
Web服務器將從servlet收到的應答發送給客戶端。
Java Servlet API 是Servlet容器(tomcat)和Servlet之間的接口,它定義了一個Servlet的各種方法,還定義了Servlet容器傳給Servlet的對象類,其中最重要的就是ServletRequest和ServletResponse。所以我們在編寫Servlet時,需要實現Servlet接口,按照其規定進行操作。
二.Servlet的優點:
1.可以移植性:
由於Servlet是用Java語言編寫的,因此它可以在不同的操作系統和服務器上移植。
2.安全:
Servlet也具有類型檢查特徵,並利用Java的垃圾收集和沒有指針的設計,使得Servlet避免了內存管理等問題。
3.高效:
Servlet加載執行後會常駐服務器內存中,當再次受到客戶端的請求時,服務器會產生新的線程而不是進程爲客戶端服務,這樣就提高了響應速度。
三.編寫Servlet
在前面,我們已經知道了Servlet是什麼,爲什麼需要Servlet?(爲了實現動態網頁,而不是顯示靜態網頁),tomcat和Servlet的關係?等問題。現在手動編寫一個Servlet。
1.創建一個MyServlet繼承HttpServlet,重寫doGet和doPost方法,也就是看請求的方法是get還是post,然後不同的處理方式來處理請求:
2.在Web.xml中配置MyServlet,爲什麼需要配置?讓瀏覽器發出的請求知道到達那個servlet,也就是讓tomcat將封裝好的request找到對應的servlet讓其使用。
配置四個東西:
配置之後,瀏覽器是如何通過我們配置的信息來找到對應的servlet的。
按照步驟,首先瀏覽器通過http://localhost:8080/test01/MyServlet來找到web.xml中的url-parttern,這就是第一步,匹配到了url-parttern後,就會找到第二步servlet的名字MyServlet,知道了名字,就可以通過Servlet-name找到第三步,到了第三步,也就能夠知道Servlet的位置了。然後到其中找到對應的處理方式進行處理。
3.實驗,驗證上面配置成功。
補充:
利用Eclipse創建MyServlet
1.右擊項目,在new選項中有直接新建servlet的選項。
2.配置MyServlet類中的信息
3.配置web.xml中的Servlet信息
4.查看MyServlet01類中的代碼和Web.xml,其中的配置跟手動的配置是一樣的,只是用圖形化界面,讓我們更方便的創建servlet而產生的。
四.Servlet的生命週期:
Servlet的生命週期可以概括爲以下幾個階段:
1)當客戶端第一次請求Servlet時,Servlet被加載到內存中,容器會創建Servlet實例,並調用其init()方法進行初始化工作。
2)容器創建請求對象和響應對象,然後調用Servlet的service()方法爲客戶端提供服務。
3)當Servlet不再被需要時,容器調用Servlet的destory()方法將Servlet實例銷燬。
當客戶端請求的Servlet已經存在於服務器內存時,容器會創建信的線程調用service()方法響應客戶端請求。在Servlet的整個生命週期中,init()方法和destory()方法只會被調用一次。
五.四個重點對象。ServletConfig;ServletContext;request;response
講解四大類:Servlet對象,ServletContext對象,request對象,response對象
ServletConfig對象
獲取途徑:getServletConfig();
功能:上面大概提及了下,能用到四個東西:
getServletName();//獲取servlet的名稱,也就是我們在web.xml中配置的servlet-name
getServletContext();//獲取ServletContext對象,該對象的作用看下面講解;
getInitParameter(String);//獲取在servlet中初始化參數的值。這裏注意與全局初始化參數的區分。這個獲取的知識在該servlet下的初始化參數。
getInitParameterNames();//獲取在Servlet中所有初始化參數的名字,也就是key值,可以通過key值,來找到各個初始化參數的value值。注意發揮的是枚舉類型。
注意:在上面我們所分析的源碼過程中,我們就知道,其實可以不用先獲得ServletConfig,然後在獲取各個參數,可以直接使用其它方法,比如上面我們用的ServletConfig().getServletName();可以直接寫成getServletName();而不用在獲取ServletConfig();了,原因就是在GenericServlet中,已經幫我們獲取了這些數據,我哦們只需要直接拿就行了。
ServletContext對象
獲取途徑:
getServletContext();getServletConfig().getServletContext();//這兩種獲取方式的區別就跟上面的解釋一樣,第一種是直接拿,在GenericServlet中已經幫我們用getServletConfig.getServletContext();拿到了ServletContext。我們只需要直接獲取就行了,第二種就相當於我們自己在獲取一遍,兩種讀是一樣的。
功能:tomcat爲每個web項目都創建一個ServletContext實例,tomcat在啓動時創建,服務器關閉時銷燬,在一個web項目中共享數據,管理web項目資源,爲整個web匹配公共信息等,通俗點講,就是一個web項目,就存在一個ServletContext實例,每個Servlet讀可以訪問到它。
1.web項目中共享數據,getAttribute(String name),setAttribute(String name,Object obj),removeAttribute(String name)
setAttribute(String name,Object obj)在web項目範圍內存放內容,以便讓在web項目中所有的servlet讀能訪問到。
getAttribute(String name)通過制定名稱獲得內容
removeAttribute(String name)通過制定名稱移除內容
2.整個web項目初始化參數//這個就是全局初始化參數,每個Servlet中都能獲取到該初始化值。
getInitParameter(String name) //通過指定名稱獲取初始化值
getInitParameterNames() //獲得枚舉類型
web.xml配置 整個web項目的初始化
3.獲取web項目資源
1)獲取web項目下指定資源的路徑:
getServletContext().getRealPath("/WEB-INF/web.xml");
2)獲取web項目下指定資源的內容,返回的是字節輸入流。InputStream.getResourceAsStream(java.lang.String path)
前提知識:需要了解流。
Request對象
request對象就是將請求文本封裝而成的對象,所以通過request能獲得請求文本中的宿友內容,請求頭,請求體,請求行。
1.請求行內容的獲取:
2.請求頭的獲取:
隨便百度一個東西,然後查看的請求頭,包括下面這些內容,稍作了解。
String getHeader(java.lang.String name)獲得指定頭內容String
System.out.println(req.getHeader("Accept-Language"));
3.請求體的獲取--請求參數的獲取
分爲兩種,一種get請求,一種post請求
get請求參數:http://localhost:8080/test01/MyServlet?username = jack & password = 1234
post請求參數:<form method = "post"><input type="text" name="username">
String request.getParameter(String)獲得指定名稱,一個請求參數值。
String[] request.getParameterValues(String)獲得指定名稱,一個請求參數值。
4.請求轉發
request.getRequestDispatcher(String path).forward(request,response);
//path:轉發後跳轉的頁面,這裏不管用不用“/”開頭,都是以web項目根開始,因爲這是請求轉發,請求 //轉發只侷限與在同一個web項目下使用,所以這裏一直都是從web項目根下開始的。
web項目根就是從該web項目名開始,所以我們請求轉發時,只需接着項目名後面需要訪問的路徑寫就行了。
特點:瀏覽器中的URL不會改變,也就是瀏覽器不知道服務器做了什麼,是服務器幫我們跳轉頁面的,並且 在轉發後的頁面,能夠繼續使用原先的request,因爲是原先的request,所以request域中的屬性都可 以繼續獲取到。
response對象
常用的一個方法:response.setHeader(java.lang.String name,java.lang.String value)
設置指定的頭,一般常用。
例如:設置每隔3秒就自動刷新一次,
response.setHeader("Refresh",3);
這樣可以看到現在時間的秒數,會發現每隔三秒就會自動刷新一次頁面。
這個最重要的一個就是重定向,其它的一些操作都被裝到response對象中了
重定向(頁面跳轉)
方式一:手動方案
response.setStatus(302); //狀態碼302就代表重定向
response.setHeader("location","http://www.baidu.com");
方式二:使用封裝好的,通過response.sendRedirect("http://www.baidu.com");
特點:
服務器告訴瀏覽器要跳轉的頁面,是瀏覽器主動跳轉的頁面,瀏覽器知道,瀏覽器中的地址欄url也會改變,是瀏覽 器重新發起一個請求到另外一個頁面,所以request是重新發起的,跟請求轉發不一樣。
注意:response.sendRendirect(path);
第一種:response.sendRedirect("/test01/MyServlet01"); //使用了“/”開頭,說明是從web站點根開始,所以需 要寫test01/MyServlet01
第二種:response.sendRedirect("MyServlet01"); //沒有使用"/"開頭,說明從web項目開始,那麼就無需寫 test01了。
重定向沒有任何侷限,可以重定向web項目內的任何路徑,也可以訪問別的web項目中的路徑,並且這裏就用"/"區分開來,如果使用了"/"開頭,就說明我要重新開始定位了,不訪問剛纔的web項目,自己寫項目名,如果沒有使用"/ "開始,那麼就知道是訪問剛纔那個web項目 下的servlet,就可以省略項目名了。就是這樣來區別的。
Servlet處理請求的流程:
1) 客戶端在瀏覽器的地址欄中輸入一個請求的URL,按回車後就向服務器端發起一個http request(由瀏覽器生成)。
2) 服務器端的Web Server首先接受到請求,並將請求轉交給容器,容器會根據請求的URL去調用客戶端要訪問的Servlet。
3) 容器會根據web.xml中對Servlet的描述去查找要訪問的Servlet,若找到,將此Servlet
裝載進虛擬機並實例化(第一次訪問),然後調用Servlet實例中的service方法處理請求,並分配一個線程去執行。
注: 當第二次去訪問同一個Servlet時,若容器判斷到該Servlet已經被裝載並實例化,
那麼容器就不會再去創建一個新的Servlet實例,直接調用原來那個Servlet實例中的service方法
來處理請求。
4) 若沒有查找到,直接返回一個404的錯誤代碼到客戶端,表示訪問的資源不存在。
Servlet處理響應:
設置HTTP狀態碼
設置HTTP響應頭
HttpServletResponse對象用於操縱響應的HTTP頭
目的用於告訴客戶端
–發送回來的內容的類型
–有多少內容正被髮送
常用的方法:
setContentType(String mimetype);
addCookie(Cookie c);
發送內容的服務器的類型
設置HTTP消息體
HttpServletResponse對象負責將信息返回給客戶端
HttpServletResponse對象只產生一個空的HTTP響應
傳回自定義的內容需要使用getWriter()或者getOutputStream()方法
–傳送普通文本
–傳送二進制內容
請求重定向和自動刷新頁面
重定向的原理:
使用sendRedirect(String URL)方法實現重定向,
在指定時間內自動刷新當前頁或到一個新的頁面
根據時間來控制響應
想在響應中有一個短時間的暫停
response.setHeader("Refresh", "time; URL=url" );
總結:
請求URL時HTTP發出了多個請求
狀態碼告訴瀏覽器發送的內容及格式狀態
Servlet API與容器進行通訊
HttpServletResponse定義的常量來避免直接使用整數
在通過PrintWriter對象發送任何內容之前先調用 HttpServletResponse的setStatus()方法
爲了讓Servlet發揮最大的效能,HttpServletResponse對象用於操縱響應的HTTP頭
getWrite()或者getOutputStream()方法傳送文本或者二進制內容給客戶端
sendRedirect方法實現重定向
HTTP響應頭“Refresh”會根據時間來控制響應