一、概述
Servlet(Server Applet)豁护,全稱Java Servlet哼凯,是用Java編寫的服務(wù)器端程序。主要功能在于交互式地瀏覽和修改數(shù)據(jù)择镇,生成動態(tài)Web內(nèi)容挡逼。
狹義的Servlet是指Java語言實現(xiàn)的一個接口;廣義的Servlet是指任何實現(xiàn)了這個Servlet接口的類腻豌。一般情況下將Servlet理解為后者家坎。
Servlet運(yùn)行于支持Java的應(yīng)用服務(wù)器中,原理上Servlet可以響應(yīng)任何類型的請求吝梅,但絕大多數(shù)情況下Servlet只用來擴(kuò)展基于HTTP協(xié)議的Web服務(wù)器虱疏。
提供了Servlet功能的服務(wù)器,叫做Servlet容器苏携。Servlet必須部署在Servlet容器中才能使用做瞪。常見的容器包括:Tomcat、WebLogic等右冻。
二装蓬、工作流程
- 客戶端發(fā)送請求到服務(wù)器。
- 根據(jù)web.xml文件的配置纱扭,查找url對應(yīng)的Servlet類牍帚。
- 服務(wù)器啟動并調(diào)用Servlet,Servlet根據(jù)客戶端請求生成響應(yīng)內(nèi)容并將其傳給服務(wù)器乳蛾。
- 服務(wù)器將響應(yīng)返回給客戶端暗赶。
三鄙币、生命周期
Servlet沒有main()方法,不能獨立運(yùn)行蹂随,由Servlet引擎控制和調(diào)度十嘿。
針對客戶端的多次Servlet請求,通常服務(wù)器只會在第一次請求的時候創(chuàng)建一個Servlet實例對象岳锁,并駐留在內(nèi)存中绩衷,直到Web容器退出時,該實例對象才會被銷毀浸锨。
- Web容器調(diào)用init()方法初始化Servlet唇聘。該方法在Servlet實例的生命周期里只調(diào)用一次版姑≈眩可以傳遞一個實現(xiàn)ServletConfig接口的對象給它,這個對象使Servlet能夠讀取web.xml文件里使用<init-param>標(biāo)簽定義的初始參數(shù)剥险。
- 調(diào)用service()方法處理不同類型的請求聪蘸。該方法使用HttpServletRequest請求對象和HttpServletResponse響應(yīng)對象作為參數(shù)。根據(jù)請求的方式調(diào)用適當(dāng)?shù)姆椒▉硖幚碚埱螅ㄈ鏳oGet或doPost等)表制。
- 調(diào)用destroy()方法銷毀Servlet健爬。該方法在Servlet實例的生命周期里只調(diào)用一次。
四么介、體系結(jié)構(gòu)
Servlet編程需要用到j(luò)avax.servlet和javax.servlet.http兩個包下面的類和接口娜遵。接口javax.servlet.servlet定義了所有servlet必須實現(xiàn)的方法。所有servlet程序必須實現(xiàn)該接口或繼承實現(xiàn)了該接口的類壤短。為了實現(xiàn)該接口设拟,可以繼承javax.servlet.GenericServlet或javax.servlet.http.HttpServlet類。
接口javax.servlet.servlet定義的方法:
public void init(ServletConfig config)
public ServletConfig getServletConfig()
public String getServletInfo()
public void service(ServletHttpRequest req, ServletHttpResponse res)
public void destroy()
主要的類和接口包括:
javax.servlet.ServletConfig
javax.servlet.ServletException
javax.servlet.ServletContext
javax.servlet.GenericServlet
javax.servlet.http.HttpServlet
javax.servlet.http.HttpServletRequest
javax.servlet.http.HttpServletResponse
javax.servlet.http.HttpSession
javax.servlet.http.Cookie
五久脯、請求和響應(yīng)
Web服務(wù)器會對收到的每一次客戶端http請求纳胧,分別創(chuàng)建一個用于代表請求的request對象和代表響應(yīng)的response對象。要獲取客戶端提交的數(shù)據(jù)需要通過request帘撰,要想容器輸出數(shù)據(jù)需要通過response跑慕。
1、請求
HttpServletRequest對象代表客戶端的請求摧找,當(dāng)客戶端通過HTTP協(xié)議訪問服務(wù)器時核行,HTTP請求頭中的所有信息都封裝在此對象中。為了獲取請求參數(shù)蹬耘,需要調(diào)用HttpServletRequest對象的getParameter()方法芝雪,并且將要獲取的輸入?yún)?shù)的id傳遞給該方法。
2婆赠、響應(yīng)
HttpServletResponse對象代表服務(wù)器的響應(yīng)绵脯,該對象封裝了向客戶端發(fā)送數(shù)據(jù)佳励、發(fā)送響應(yīng)頭、發(fā)送響應(yīng)狀態(tài)碼的方法蛆挫。為了發(fā)送內(nèi)容給客戶端赃承,需要使用從HttpServletResponse對象獲取的PrintWriter對象,任何寫到這個對象的內(nèi)容都會被寫進(jìn)outputstream里悴侵,并會把內(nèi)容發(fā)送到客戶端瞧剖。
為了獲取配置文件中的初始化參數(shù),可以調(diào)用getServletConfig().getInitParameter("name")方法可免。
六抓于、配置
進(jìn)行Servlet的配置有兩種方法:
- 通過web.xml配置文件
- 使用注解@WebServlet(name=””, urlPatterns=””)
1、web.xml
雖然web.xml對于web工程來說并不是必須的浇借,為了能夠輕松應(yīng)對可能面對的各種復(fù)雜情況捉撮,使用web.xml進(jìn)行工程配置還是很有必要的。通常是創(chuàng)建在工程的WEB-INF目錄下妇垢,用來配置歡迎頁巾遭、servlet、listener闯估、filter等信息灼舍。
web.xml中能夠使用的標(biāo)簽,是由模式文件定義的涨薪,而模式文件則由Sun公司(現(xiàn)已被Oracle收購)來定義悬赏。在每個web.xml文件的根元素<web-app>中揭斧,必須標(biāo)明使用哪個模式文件鸠儿。
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
version="3.1">
訪問網(wǎng)站時涛贯,默認(rèn)顯示的第一個頁面叫做歡迎頁面,一般情況下由首頁做為歡迎頁面光督⊙艟啵可以設(shè)置多個歡迎頁面,按照設(shè)置順序依次查找结借。如果頁面存在就顯示該頁面筐摘,不再繼續(xù)查找。如果頁面不存在船老,則返回404錯誤咖熟。
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
可以通過異常類型或錯誤碼來設(shè)置錯誤處理頁面。
<error-page>
<exception-type>java.lang.Exception<exception-type>
<location>/exception.jsp<location>
</error-page>
<error-page>
<error-code>404</error-code>
<location>/error.jsp</location>
</error-page>
可以設(shè)置servlet以及servlet與URL的映射柳畔。servlet的定義必須在servlet映射之前進(jìn)行設(shè)置馍管。
<servlet>
<servlet-name>test-servlet</servlet-name>
<servlet-class>com.demo.TestServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>test-servlet</servlet-name>
<url-pattern>/test</url-pattern>
</servlet-mapping>
還可以設(shè)置會話的失效時間,以分鐘為單位薪韩。
<session-config>
<session-timeout>60</session-timeout>
</session-config>
web.xml中元素的加載順序:<context-param> -> <listener> -> <filter> -> <servlet>确沸。同類型元素之間根據(jù)mapping的順序進(jìn)行調(diào)用捌锭。
還有一些其他常用的元素:
- <display-name>定義web應(yīng)用的名稱
- <description>聲明web應(yīng)用的描述信息
- <context-param>聲明應(yīng)用范圍內(nèi)的初始化參數(shù)
2、注解@WebServlet
在Java5以后罗捎,提供了資源注入(即注解)的方式观谦,可以直接在servlet類注解配置信息,而不需要通過web.xml進(jìn)行配置桨菜。
@WebServlet(urlPatterns={"/test"})
public class TestServlet extends HttpServlet {
......
}
七豁状、監(jiān)聽器
為了創(chuàng)建一個基于容器事件的監(jiān)聽器,必須創(chuàng)建一個實現(xiàn)ServletContextListener接口的類倒得。該類必須實現(xiàn)contextInitialized()和contextDestroyed()兩個方法泻红。這兩個方法都需要ServletContextEvent作為參數(shù),并且在每次初始化或關(guān)閉容器時都會被自動調(diào)用霞掺。
注冊監(jiān)聽器除了通過web.xml和使用@WebListener注解外谊路,還可以使用ServletContext里定義的addListener()方法。
常用的監(jiān)聽器類:
javax.servlet.ServletRequestListener
javax.servlet.ServletRequestAttributeListener
javax.servlet.ServletContextListener
javax.servlet.ServletContextAttributeListener
javax.servlet.HttpSessionListener
javax.servlet.HttpSessionAttributeListener
八根悼、過濾器
Web過濾器在給定的URL被訪問時凶异,對請求進(jìn)行預(yù)處理,會在Servlet調(diào)用前被調(diào)用挤巡。很多情況下,使用過濾器是很有用的酷麦,如執(zhí)行日志矿卑、驗證、或其他不需要與用戶交互的后臺服務(wù)等沃饶。
過濾器必須實現(xiàn)javax.servlet.Filter接口母廷,該接口包含了init()、destroy()糊肤、doFilter()方法琴昆。init和destroy方法會被容器調(diào)用,doFilter方法用來在過濾器類里實現(xiàn)邏輯任務(wù)馆揉。
為了配置過濾器业舍,可以使用@WebFilter注解或在web.xml文件中使用<filter>和<filter-mapping>注冊。<filter>的定義必須在<filter-mapping>進(jìn)行設(shè)置升酣。
九舷暮、轉(zhuǎn)發(fā)和重定向
轉(zhuǎn)發(fā)請求時不重定向客戶端的URL,即瀏覽器地址欄的URL不會改變噩茄。ServletContext已經(jīng)內(nèi)置實現(xiàn)轉(zhuǎn)發(fā)的方法下面,調(diào)用getRequestDispatcher()方法獲取用來轉(zhuǎn)發(fā)請求的對象。調(diào)用該方法時绩聘,需要傳遞包含處理轉(zhuǎn)發(fā)請求的Servlet名稱的字符串沥割。獲取RequestDispatcher對象后耗啦,傳遞HttpServletRequest和HttpServletResponse對象給轉(zhuǎn)發(fā)方法forward()。
RequestDispatcher rd = servletContext.getRequestDispatcher("/NextServlet");
rd.forward(request, response);
當(dāng)特定URL被訪問時机杜,可以把瀏覽器的URL重定向到另外一個芹彬,即URL會改變。需要調(diào)用HttpServletResponse對象的sendRedirect()方法叉庐,傳遞重定向后的URL字符串舒帮。
httpServletResponse.sendRedirect("/anotherURL");
十、Cookie與Session
用戶打開瀏覽器陡叠,點擊多個超鏈接玩郊,訪問服務(wù)器多個Web資源,關(guān)閉瀏覽器枉阵,整個過程稱之為一個會話译红。保存會話數(shù)據(jù)有兩種方式:使用Cookie或Session。
1兴溜、Cookie
客戶端技術(shù)侦厚,程序把每個用戶的數(shù)據(jù)以cookie的形式寫給用戶各自的瀏覽器,當(dāng)訪問服務(wù)器中的Web資源時拙徽,會帶著用戶各自的數(shù)據(jù)刨沦。
Cookie可以看做是保存在客戶端的鍵值對數(shù)據(jù),當(dāng)使用瀏覽器打開應(yīng)用時膘怕,可以對這些數(shù)據(jù)進(jìn)行讀寫想诅。為了創(chuàng)建cookie,需要實例化一個javax.servlet.http.Cookie對象岛心,并為它分配鍵值来破,可以設(shè)置屬性來配置cookie。
Cookie cookie = new Cookie("sessionId","123456789");
cookie.setHttpOnly(true);
response.addCookie(cookie);
讀取服務(wù)端的cookie信息:
Cookie[] cookies = request.getCookies();
for(Cookie cookie : cookies){
......
}
2忘古、Session
服務(wù)器端技術(shù)徘禁,服務(wù)器為每個用戶的瀏覽器創(chuàng)建一個獨享的HttpSession對象,當(dāng)訪問服務(wù)器的Web資源時髓堪,把各自的數(shù)據(jù)放在各自的session中送朱。
通過請求獲取session對象:
HttpSession session = request.getSession(boolean create);
如果當(dāng)前請求不屬于任何會話,而且create參數(shù)為true旦袋,則創(chuàng)建一個會話骤菠,否則返回null。如果為false的時候疤孕,那就和不帶參數(shù)的getSession()等價了商乎。
獲取session對象之后,就可以直接使用它進(jìn)行各種操作了祭阀。
// 將value對象以name名稱綁定到會話
public void setAttribute(String name, Object value)
// 取得name的屬性值鹉戚,如果屬性不存在則返回null
public object getAttribute(String name)
// 從會話中刪除name屬性鲜戒,如果不存在不會執(zhí)行,也不會拋出錯誤
public void removeAttribute(String name)
// 返回和會話有關(guān)的枚舉值
public Enumeration getAttributeNames()
// 使會話失效抹凳,同時刪除屬性對象
public void invalidate()
// 用于檢測當(dāng)前用戶是否為新的會話
public Boolean isNew()
// 返回會話創(chuàng)建時間
public long getCreationTime()
// 返回在會話時間內(nèi)web容器接收到客戶最后發(fā)出的請求的時間
public long getLastAccessedTime()
// 返回在會話期間內(nèi)客戶請求的最長時間遏餐,單位是秒
public int getMaxInactiveInterval()
// 允許客戶客戶請求的最長時間
public void setMasInactiveInterval(int seconds)
// 返回當(dāng)前會話的上下文環(huán)境,ServletContext對象可以使Servlet與web容器進(jìn)行通信
ServletContext getServletContext()
// 返回會話期間的識別號
public String getId()
十一赢底、上傳和下載
1失都、上傳文件
首先要將enctype屬性的值設(shè)置成multipart/form-data,讓表單提交的數(shù)據(jù)以二進(jìn)制編碼的方式提交幸冻,在接收此請求的Servlet中用二進(jìn)制流來獲取內(nèi)容粹庞,就可以取得上傳文件的內(nèi)容,從而實現(xiàn)文件的上傳洽损。
2庞溜、下載文件
通過HttpServletResponse.setContentType方法設(shè)置響應(yīng)類型Content-Type頭字段的值,讓瀏覽器無法使用某種方式或激活某個程序來處理的MIME類型碑定。
response.setContentType("application/x-msdownload");
通過HttpServletResponse.setHeader方法設(shè)置響應(yīng)頭Content-Disposition的值流码。
response.setHeader("Content-Disposition", "attachment;filename=\"" + filename + "\"");
調(diào)用HttpServletRespnse.getOutputStream方法返回的ServletOutputStream對象來向客戶端寫入附件文件的內(nèi)容。
InputStream inputStream = new FileInputStream(file);
ServletOutputStream ouputStream = response.getOutputStream();
byte b[] = new byte[1024];
while((n = inputStream.read(b)) != -1) {
ouputStream.write(b, 0, n);
}