一? servlet概述
狹義的Servlet指javax.servlet包中的一個接口,而廣義的Servlet則是指實現了這個接口的類。一個Servlet應用有一個或多個Servlet程序。
Jsp是在傳統的HTML代碼中插入java程序段(Scriplet)與jsp標記(tag).
servlet應用需要在servlet容器中運行,典型容器如Jetty、Tomcat 運行servlet應用。在一個容器中可以同時運行Servlet與靜態內容。
servlet API 主要由以下幾個工具包:
1.javax.Servlet? 其中包含Servlet和Servlet容器之間契約的類和接口
2.javax.Servlet.http 其中包含定義HTTP Servlet(采用了HTTP協議的Servlet)和Servlet容器之間契約的類和接口。
3.avax.servlet.annotation,其中包含標注Servlet、Filter、Listener的標注。它還為被標注元件定義元數據。
javax.servlet.descriptor,其中包含提供程序化登錄web應用程序的配置信息的類型。
二? Servlet接口
其中的方法包括:
? ? ? ? 1.init(ServletConfig config)? 當該Servlet被一次請求時,調用該方法,此后不再調用。參數傳入的是Servlet的配置信息
? ? ? ? 2.service(ServletRequest req,ServletResponse res) 每當請求Servlet時,Servlet容器就會調用這個方法。編寫代碼時,假設Servlet要在這里? 被請求。第一次請求Servlet時,Servlet容器調用init方法和Service方法。后續的請求將只調用Service方法。
? ? ? ? 3.destroy() 當要銷毀Servlet時,Servlet容器就會調用這個方法。當要卸載應用程序,或者當要關閉Servlet容器時,就會發生這種情況。一般會在這個方法中編寫清除代碼。
? ? ? 4. ServletConfig getServletConfig() 這個方法會返回由Servlet容器傳給init方法的ServletConfig
? ? ?5. String getServletInfo() 這個方法會返回Servlet的描述。
ServletRequest接口 封裝請求數據
1. Object getAttribute(String name)? 返回以name為名字的屬性的值,如果不存在,返回null
2. Enumeration getAttributeNames(); 返回請求中所有可用的屬性的名字。返回一個枚舉集合
3. void removeAttribute(String name); 移除請求中名字為name的屬性
4. void setAttribute(String key,Object val); 在請求中保存一個鍵值對。
5. getCharacterEncoding() 返回請求正文使用的字符編碼的名字
6. int getContentLength() 以字節為單位,返回請求正文的長度。
7. String getContentType() 返回正文的MIME類型
8. ServletInputStream getInputStream()
9. BufferedReader getReader()
10.String getLocalAddr() 返回接收到請求的網絡接口的IP地址。
11.String getRemoteAddr() 返回發送請求的客戶端或最后一個代理服務器的IP地址
12. String getRemoteHost() 返回發送請求的客戶端或者最后一個代理服務器的完整限定名
13. String getLocalName() 返回接收到請求的IP接口的主機名
14. int getLocalPort() 返回接收到請求的網絡接口的IP端口號
?15. int getRemotePort() 返回發送請求的客戶端或最后一個代理服務器的IP源端口。
16? String getParameter(String name) 返回請求中name參數的值,如果name參數有多個值,該方法返回值列表中的第一個值。如果請求中沒有找到該參數,返回null
17 Enumeration getParameterNames() 返回請求中包含的所有的參數的名字。
18 String[] getParameterValues(String name); 返回請求中name參數所有的值
19 String getProtocal() 返回請求使用的協議的名字和版本 例如: HTTP/1.1
20. RequestDispatcher getRequestDispatcher(String path) 返回RequestDispather對象,作為path所定位的資源的封裝。
21. String getServerName()? 返回請求發送到服務器的主機名
?22 int getServerPort() 返回請求發送到服務器的端口號
23. setCharacterEncoding(String env) 覆蓋在請求正文中所使用的字符編碼的名字。(鏈接:http://www.lxweimin.com/p/d718a5f4a850)
ServletResponse接口,用來封裝響應數據
flushBuffer()? ? ? ? ? ? ?強制把任何在緩存中的內容發送到客戶端
int getBufferSize()? ? ? ? ? 返回實際用于響應的緩存的大小,如果沒有使用緩存,這個方法返回0
String getCharacterEncoding() 返回響應中發送的正文所使用的字符編碼(MIME字符集)
String getContentType()返回響應中發送的正文所使用的MIME類型
ServletOutputStream getOutputStream()
PrintWriter getWriter()
boolean isCommitted()? ? ? 返回一個布爾值,指示是否已經提交了響應。
void reset()? ? ? ? ? ? ? ? 清除在緩存中的任何數據,包括狀態代碼和消息報頭。
void resetBuffer()? ? ? ? ? 清除在緩存中的響應內容,保留狀態代碼和消息包頭。
void setBufferSize(int size) 設置響應正文的緩存大小。
void setCharacterEncoding(String charset) 設置發送到客戶端的響應的字符編碼
void setContentLength(int len) 設置內容正文的長度
void setContentType(String type)? 設置要發送到客戶端的響應的內容類型。例如:"text/html;charset=UTF-8"
ServletConfig
Servlet容器使用ServletConfig對象在Servlet初始化期間向它傳遞配置信息,一個ServletConfig對象。
String getInitParameter(String name); 返回名字為name的初始化參數的值,初始化參數在web.xml配置文件中進行配置。
Enumeration getInitParameterNames()? 返回Servlet所有初始化參數的名字的枚舉集合。
ServletContext getServletContext() 返回Servlet上下文對象的引用。
String getServletName() 返回Servlet實例的名字,這個名字是web應用程序的部署描述符中指定。
編寫一個Servlet實際上就是編寫一個實現了javax.servlet.Servlet接口的類。
GenericServlet
如果要編寫一個通用的Servlet,只需要從GenericServlet繼承,并且實現抽象方法service();
String getInitParameter(String name)
Enumeration getInitParameterNames();
ServletContext getServletContext()
init(ServletConfig config)
HttpServlet
在絕大多數的網絡應用中,都是客戶端通過HTTP協議去訪問服務器端的資源我們編寫的Servlet也主要是應用于HTTP協議的請求和響應,為了快速開發應用于HTTP協議的Servlet類,sun公司在javax.servlet.http包中給我們提供了一個抽象類HttpServlet,它繼承自GenericServlet類,用于創建適合WEB站點的HTTP Servlet
public void service(ServletRequest req,ServletResponse res);
protected void service(HttpServletRequest req,HttpServletResponse resp)
針對HTTP1.1定義的7種請求方法GET,POST,HEAD,PUT,DELETE,TRACE,OPTION,
HttpServlet提供了7個處理方法
doGet(HttpServletRequest req,HttpServletResponse resp)
doPost(HttpServletRequest req,HttpServletResponse resp)
......
當容器接受到一個針對HttpServlet對象的請求時,調用該對象中的方法順序如下:
調用公共的service()方法
在公共的service()方法中,首先將參數類型轉換為HttpServletRequest和HttpServletResponse,然后調用保護的service()方法,將轉換后的對象作為參數傳遞進去
在保護的service方法中,首先調用HttpServletRequest對象的getMethod方法,獲取HTTP請求方法的名稱,然后根據請求方法的類型,調用相應的doXxx()方法
HttpServletRequest
繼承自javax.servlet.servletRequest,在該接口中新增的方法如下:
String getContextPath() 返回請求URI中表示請求上下文的部分,上下文路徑是請求URI的開始部分
Cookie[] getCookies() 返回客戶端在此次請求中發送的所有的Cookie對象
String getHeader(String name) 返回名字為name的請求報頭的值
Enumeration getHeaderNames() 返回此次請求中包含的所有的報頭名字的枚舉集合
Enumeration getHeaders(String name) 返回名字為name的請求報頭的所有值的枚舉集合
String getMethod() 返回此次請求所使用的HTTP方法的名字
String getServletPath() 返回請求URI中調用Servlet的部分
HttpSession getSession() 返回和此次請求相關聯的Session
HttpSession getSession(boolean create)? 返回此次請求相關聯的Session,如果沒有給客戶端分配Session,并且create參數為true,則創建一個新的Session,如果為false,此次請求沒有一個有效的HttpSession,返回null
HttpServletResponse
該接口繼承ServletResponse,新增的方法入下
addCookie(Cookie cookie)
addHeader(String name,String value);
boolean containsHeader(String name)
encodeRedirectURL(String url)?
使用SessionID 對于重定向的url編碼,以便用于sendRedirect()方法中
encodeURL(String url)? ? ? ? ? ? 使用SessionID 指定的url編碼
sendRedirect(String location)? ? ? 發送一個臨時的重定向響應到客戶端,讓客戶端訪問新的url
(鏈接:http://www.lxweimin.com/p/d718a5f4a850)
ServletConfig接口
當Servlet容器初始化Servlet時,Servlet容器會給Servlet的init方法傳入一個ServletConfig對象。ServletConfig封裝了通過@WebServlet注解或者部署描述符(關于@WebServlet注解和部署描述符的內容會在后面的文章中講到)傳給Servlet的配置信息。這樣傳入的每一條信息就叫一個初始參數。一個初始參數有key和value兩個元素。可以使用getServletConfig來獲取傳遞給Servlet的ServletConfig。
為了從Servlet內部獲取到初始參數的值,要在Servlet容器傳給Servlet的init方法的ServletConfig中調用getInitParameter方法。ServletConfig還提供了另一個很有用的方法:getServletContext。利用這個方法可以從Servlet內部獲取ServletContext。
(鏈接:http://www.lxweimin.com/p/136fb6bf9ed6)
4.ServletContext接口
ServletContext表示Servlet應用程序的上下文,且每一個應用程序只有一個上下文。在將一個應用程序同時部署到多個容器的分布式環境中,每臺Java虛擬機上的Web應用都會有一個ServletContext對象。
通過在ServletConfig中調用getServletContext方法,可以獲得ServletContext。有了ServletContext,就可以共享從應用程序中的所有資料處訪問到的信息,并且可以動態注冊Web對象。ServletContext將對象保存在一個內部Map中。保存在ServletContext中的對象被稱作屬性。
鏈接:http://www.lxweimin.com/p/136fb6bf9ed6
Cookie
Cookie是由Web服務器保存在用戶瀏覽器上的小文本文件,它可以包含有關用戶的信息。無論何時用戶鏈接到服務器,Web站點都可以訪問cookie信息。Cookie作為HTTP? header的一部分,其傳輸由HTTP協議控制。此外,你還可以控制cookie的有效時間。
可以通過傳遞name和value兩個參數給Cookie類的構造函數來創建一個cookie:
Cookie cookie = new Cookie(name, value);
創建完一個Cookie對象后,你可以使用setMaxAge方法設置maxAge屬性,這個屬性決定cookie何時過期。
要將cookie發送到瀏覽器,需要調用HttpServletResponse的add方法。
服務端若要讀取瀏覽器提交的cookie,可以通過HttpServletRequest接口的getCookies方法,該方法返回一個Cookie數組,若沒有cookies則返回null。你需要遍歷整個數組來查詢某個特定名稱的cookie。
目前,還沒有通過名稱來獲取cookie的方法來幫助簡化工作。此外,也沒有一個直接的方法來刪除一個cookie,你只能創建一個同名的cookie,并將maxAge 屬性設置為0,并添加到HttpServletResponse接口中,就像下面這樣:
Cookie cookie = new Cookie("userName", "");
cookie.setMaxAge(0);
response.addCookie(cookie);
現在我們來編寫一個使用cookie來幫助統計用戶訪問某一頁面次數的Servlet:
package com.mc.hello;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class CookieDemoServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setCharacterEncoding("UTF-8");
response.setContentType("text/html");
PrintWriter out = response.getWriter();
int count = 0;
Cookie[] cookies = request.getCookies();
if(cookies != null) {
for (Cookie cookie : cookies) {
if(cookie.getName().equals("VisitCount")) {
count = Integer.parseInt(cookie.getValue());
break;
}
}
}
count++;
out.print("這是你第" + count + "次訪問這個頁面");
Cookie cookie = new Cookie("VisitCount", "" + count);
response.addCookie(cookie);
}
}
在web.xml中的配置:
cookiecom.mc.hello.CookieDemoServletcookie/cookie
在瀏覽器地址欄中輸入http://localhost:8080/HelloWorld/cookie即可看到如下頁面:
顯示訪問次數的頁面
每刷新一次這個頁面,訪問次數都會增加一次。但是當我們關閉瀏覽器,然后再次打開瀏覽器,并輸入這個頁面的URL時,頁面上顯示的訪問次數還是一次。這是因為我們沒有設置cookie的過期時間,當我們關閉瀏覽器的時候cookie就過期了。這里我們將這個cookie的過期時間設置為3分鐘:
Cookie cookie = new Cookie("VisitCount", "" + count);
cookie.setMaxAge(3 * 60);
response.addCookie(cookie);
這樣一來,3分鐘之內,無論我們是否關閉瀏覽器,cookie都不會過期。
Session 接口
Session是另一種記錄客戶狀態的機制,與Cookie將客戶狀態保存在客戶端瀏覽器中的形式不同,Session將客戶狀態保存在服務器上。客戶端瀏覽器訪問服務器的時候,服務器把客戶端信息以某種形式記錄在服務器上。客戶端瀏覽器再次訪問時只需要從該Session中查找該客戶的狀態即可。
HttpSession接口是Java對Session機制的實現規范,它位于javax.servlet.http包中。
HttpSession對象在用戶第一次訪問網站的時候自動被創建,你可以通過調用HttpServletRequest的getSession方法獲取該對象。getSession有兩個重載方法:
HttpSession getSession()
HttpSession getSession(boolean create)
沒有參數的getSession方法會返回當前的HttpSession,若當前沒有,則創建一個返回。getSession(false)返回當前HttpSession,如當前會話不存在,則返回null。getSession(true)與沒有參數的getSession方法一致,也是返回當前HttpSession,若當前沒有,則創建一個。
可以通過HttpSession的setAttribute方法將值放入HttpSession,該方法簽名如下:
void setAttribute(String name, Object value)
調用setAttribute方法時,若傳入的name參數此前已經使用過,則會用新值覆蓋舊值。
通過調用HttpSession的getAttribute方法可以取回之前放入的對象,該方法的簽名如下:
Object getAttribute(String name)
注意,所有保存在HttpSession的數據不會被發送到客戶端。
可以通過調用HttpSession的getId方法來讀取Session的ID。Servlet容器為每個HttpSession生成唯一的標識,并為這個標識創建一個名為JSESSIONID的cookie。在后續的請求中,瀏覽器會將標識提交給服務端,這樣服務器就可以識別該請求是由哪個用戶發起的。
下面是幾種使Session失效的方法:
在項目的部署描述文件中進行設置:
1
該Session會在最后一次訪問一分鐘后失效
直接在應用服務器中設置。如果是tomcat,可以在tomcat目錄下conf/web.xml中找到元素,tomcat默認設置是30分鐘,只要修改這個值即可。
對HttpSession調用setMaxInactiveInterval方法來設定其超時時間:
void setMaxInactiveInterval(int seconds)
對HttpSession調用invalidate方法強制使會話過期。
下面我們編寫程序來創建一個Session:
package com.mc.hello;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
@WebServlet(urlPatterns = { "/mysession" })
public class SessionDemoServlet extends HttpServlet {
private static final long serialVersionUID = 36L;
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setCharacterEncoding("UTF-8");
response.setContentType("text/html");
PrintWriter out = response.getWriter();
HttpSession session = request.getSession();
session.setAttribute("name", "maconn");
Cookie[] cookies = request.getCookies();
if(cookies != null) {
for (Cookie cookie : cookies) {
out.print(cookie.getName() + " = " + session.getId());
}
}
else
out.print("no cookie");
}
}
第一次打開頁面,由于之前此時還不存在Session,也就不存在JSESSIONID對應的cookie,此時網頁上會顯示"no cookie"。再次刷新頁面,就會看到Session對應的JSESSIONID。
鏈接:http://www.lxweimin.com/p/95849fa7be53