一、簡介
最近看原始碼,涉及servlet這一塊。藉此對servlet及相關原始碼等知識進行回顧和介紹。通常說的servlet開發其實是一種開發動態網頁的解決方案,它包含實現javax.servlet.Servlet介面的servlet程式和解析servlet程式的servlet引擎(即是servlet容器,如tomcat等)。servlet程式是在伺服器端執行的。
二、servlet結構
一個servlet是一個在web伺服器執行的小程式。
2.1 servlet依賴包
servlet開發依賴包為javax.servlet-api.jar,通常servlet容器中會有(如tomcat),因此打包一般在編譯器使用。
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>compile</scope>
</dependency>
2.2 servlet流程
graph TB
request -->|請求| servletContainer(servlet容器/引擎)
servletContainer -->|呼叫| servletApi(servlet api)
servlet程式 -->|實現| servletApi
servlet引擎和servlet程式透過servlet api通訊,流程為:servlet程式實現servlet api介面,外界請求到servlet容器時,servlet容器透過servlet引擎,呼叫servlet api,實現對servlet程式的呼叫。
2.3 servlet註冊
servlet程式是在web.xml中註冊的,包含servlet名稱、servlet實現類、servlet請求地址,格式如下
<servlet>
<servlet-name>servletName</servlet-name>
<servlet-class>servlet實現類</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>servletName</servlet-name>
<url-pattern>servlet匹配地址</url-pattern>
</servlet-mapping>
2.3.1 servlet註冊位置
通常servlet是在應用程式的web.xml中註冊,但其實在servlet容器中(如tomcat), 在conf/web.xml還有個全域性的註冊(所有應用程式均可使用,控制全域性的跳轉)。
2.3.2 servlet匹配地址
servlet請求地址可以是固定的一個,也可採用萬用字元來匹配多個地址,不過採用萬用字元只能有兩種格式:
*.副檔名,此時 *前面不能有分割符 / ,這種方式的匹配優先順序最低,如: *.html 匹配.html結尾的地址;
以分割符/開頭並以*結尾的,如: /stu/ *,匹配所有/stu/開頭的地址;
servlet匹配地址採用最具體原則,地址匹配越具體,越優先容易匹配,其中 *.副檔名 模式的匹配優先順序最低。
2.3.3 預設servlet
預設servlet位於servlet容器中的conf/web.xml中,如果servlet匹配地址為/,則該servlet為預設servlet,當外界請求地址找不到servlet匹配地址時,就會走預設servlet。通常訪問靜態資源(如圖片、html等)時,走的就是預設servlet,即此時不在需要單獨配置servlet。
<servlet>
<servlet-name>default</servlet-name>
<servlet-class>org.apache.catalina.servlets.DefaultServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
2.4 servlet類載入
servlet類載入並非完全的雙親委派模式,略有不同,改為當前類載入器優先,目的是對不同web應用間相互隔離(比如不同web應用依賴不同版本的同類jar包,需要相互隔離),這裡以tomcat中類載入為例,其類載入器有:
graph BT
system --- bootstrap
common --- system
webapp1 --- common
webapp2 --- common
webappx --- common
2.4.1 bootstrap
bootstrap類載入器(包含jvm載入器和ExtClassLoader)用於載入jvm核心包(rt.jar)和系統擴充套件目錄下的包(<java_home>/jre/lib/ext)。
2.4.2 sytem
system類載入器(通常為AppClassLoader)載入classpath環境變數設定的指定目錄中的類。實際使用(tomcat啟動指令碼,$CATALINA_HOME/bin/catalina.sh)中會忽略原有環境變數的設定,而改為載入$CATALINA_HOME/bin/bootstrap.jar、$CATALINA_HOME/bin/tomcat-juli.jar、commons-daemon.jar等jar包。
2.4.3 cmmon
common類載入器載入tomcat內部類和所用webapp 共享的類($CATALINA_HOME/lib).
2.4.4 webapp
webapp類載入器用於載入當前webapp應用程式下的/Web-INF/classes和/Web-INF/lib目錄中的class檔案和jar包。webapp類載入器僅對當前web應用程式可見。
2.4.5 完整類載入流程
當有類載入需求時,優先在當前應用程式的webapp類載入器載入,若沒有,再使用雙親委派,委託common類載入器,commont類載入器接著委託system類載入器,若system類載入器失敗,才由common類載入器載入,若common類載入器還是載入失敗,則拋異常。
2.5 servlet生命週期
2.5.1 servlet初始化
一個servlet在其生命週期中只會初始化一次,同一個servlet也只會有一個例項。但servlet內的service(HttpServletRequest req, HttpServletResponse resp)方法會被多次呼叫,每次請求會新生成HttpServletRequest和HttpServletResponse例項。同一個servlet只有一個servlet物件,因此需要注意多執行緒安全問題。
2.5.2 servlet建立多個例項
servlet實現javax.servlet.SingleThreadModel介面後,可建立多個servlet例項(構成servlet例項池,每次請求使用一個)來處理請求,此時每個請求單獨對用一個servlet例項(顯然不存在併發引起的問題),當然該介面已經標記為@deprecated(過時),不在推薦使用,而推薦使用多執行緒同步來處理問題。使用示例如下:
import javax.servlet.SingleThreadModel;
import javax.servlet.http.HttpServlet;
public class SingleServlet extends HttpServlet implements SingleThreadModel {
}
三、servlet主要類
servlet主要類圖如下:
接下來將分別介紹。
3.1 ServletContext類
每個web應用程式都是一個獨立的Servlet容器,都有一個ServletContext物件。ServletContext定義了一組和servlet容器通訊的方法(比如獲取servlet容器初始化引數,這樣就不需要在應用程式中寫死,而是一個變數),ServletContext物件存在於ServletConfig物件中,當每個Servlet初始化時,ServletContext會隨著ServletConfig提供給每個Servlet。
package javax.servlet;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Enumeration;
import java.util.EnumSet;
import java.util.EventListener;
import java.util.Map;
import java.util.Set;
import javax.servlet.descriptor.JspConfigDescriptor;
//ServletContext定義了一組和servlet容器通訊的方法,每個web應用程式都有獨立的ServletContext,
//在每個Servlet初始化時,會隨著ServletConfig提供給每個Servlet
public interface ServletContext {
//返回web應用程式的context路徑,也就是在<tomcat_home>/conf/server.xml中context元素path的值
public String getContextPath();
//返回指定路徑(容器中其他web應用程式的ServletContext,路徑必須以/開頭)的ServletContext,沒有或沒許可權則返回null
public ServletContext getContext(String uripath);
//返回Servlet api的主版本,如3.0則返回3
public int getMajorVersion();
//返回Servlet api的次版本,如3.0則返回0
public int getMinorVersion();
//返回servlet容器支援的servlet主版本
public int getEffectiveMajorVersion();
//返回servlet容器支援的servlet次版本
public int getEffectiveMinorVersion();
//返回指定檔案的mime型別(如text/html、image/gif)
public String getMimeType(String file);
//返回指定路徑下的所有資源地址(檔案或目錄,不遞迴獲取)
public Set<String> getResourcePaths(String path);
//返回給定地址的url,地址必須以/開頭並會被解析為相對當前context root路徑, 或者
public URL getResource(String path) throws MalformedURLException;
//返回指定資源的InputStream
public InputStream getResourceAsStream(String path);
//返回RequestDispatcher物件,作為對給定路徑資源的包裝。
//RequestDispatcher可用於forward請求或者在response響應中包含動態或靜態資源
public RequestDispatcher getRequestDispatcher(String path);
//返回作為對給定名稱servlet包裝的RequestDispatcher
public RequestDispatcher getNamedDispatcher(String name);
//在servlet日誌檔案中記錄資訊
public void log(String msg);
//在servlet日誌檔案中記錄資訊,包含堆疊資訊
public void log(String message, Throwable throwable);
//返回給定虛擬地址的真實完整地址,如:/index.html返回http://localhost:8080/index.html
public String getRealPath(String path);
//返回執行的servlet的servlet容器名稱和版本資訊
public String getServerInfo();
//返回指定名稱的context初始化引數
public String getInitParameter(String name);
//返回context初始化引數名稱集合
public Enumeration<String> getInitParameterNames();
//在ServletContext中設定context初始化引數,若已經存在指定名稱的context初始化引數,則失敗,返回false(@since Servlet 3.0)
public boolean setInitParameter(String name, String value);
//返回在servlet容器中給定名稱的屬性值
public Object getAttribute(String name);
//返回ServletContest中屬性名稱集合
public Enumeration<String> getAttributeNames();
//在ServletContext中設定屬性值,如果已經存在則覆蓋
public void setAttribute(String name, Object object);
//在ServletContext中移除屬性
public void removeAttribute(String name);
//返回應用名稱,即display-name值
public String getServletContextName();
//在ServletContext中新增servlet(@since Servlet 3.0)
public ServletRegistration.Dynamic addServlet(
String servletName, String className);
//在ServletContext中新增servlet例項(@since Servlet 3.0)
public ServletRegistration.Dynamic addServlet(
String servletName, Servlet servlet);
//在ServletContext中新增servlet(@since Servlet 3.0)
public ServletRegistration.Dynamic addServlet(String servletName,
Class <? extends Servlet> servletClass);
//根據類例項例項化servlet
public <T extends Servlet> T createServlet(Class<T> clazz)
throws ServletException;
//獲取指定名稱的servlet註冊資訊ServletRegistration(@since Servlet 3.0)
public ServletRegistration getServletRegistration(String servletName);
//以map形式獲取所有ServletRegistration物件
public Map<String, ? extends ServletRegistration> getServletRegistrations();
//在servlet context中新增Filter(@since Servlet 3.0)
public FilterRegistration.Dynamic addFilter(
String filterName, String className);
//在servlet context中新增Filter例項(@since Servlet 3.0)
public FilterRegistration.Dynamic addFilter(
String filterName, Filter filter);
//在servlet context中新增Filter(@since Servlet 3.0)
public FilterRegistration.Dynamic addFilter(String filterName,
Class <? extends Filter> filterClass);
//根據類例項例項化Filter
public <T extends Filter> T createFilter(Class<T> clazz)
throws ServletException;
//返回給定名稱的Filter註冊資訊FilterRegistration (@since Servlet 3.0)
public FilterRegistration getFilterRegistration(String filterName);
//以map形式返回所用的Filter註冊資訊FilterRegistration (@since Servlet 3.0)
public Map<String, ? extends FilterRegistration> getFilterRegistrations();
//返回SessionCookieConfig物件
public SessionCookieConfig getSessionCookieConfig();
//設定session跟蹤方式(@since Servlet 3.0)
public void setSessionTrackingModes(Set<SessionTrackingMode> sessionTrackingModes);
//返回預設session跟蹤方式(@since Servlet 3.0)
public Set<SessionTrackingMode> getDefaultSessionTrackingModes();
//返回有效的session跟蹤方式(@since Servlet 3.0)
public Set<SessionTrackingMode> getEffectiveSessionTrackingModes();
//新增監聽器EventListener
public void addListener(String className);
//新增監聽器EventListener
public <T extends EventListener> void addListener(T t);
//新增監聽器EventListener
public void addListener(Class <? extends EventListener> listenerClass);
//根據類名例項化監聽器EventListener
public <T extends EventListener> T createListener(Class<T> clazz)
throws ServletException;
//獲取在web.xml和web-fragment.xml中的jsp config
public JspConfigDescriptor getJspConfigDescriptor();
//獲取載入ServletContext的類載入器
public ClassLoader getClassLoader();
//宣告角色(在isUserInRole使用)
public void declareRoles(String... roleNames);
//獲取ServletContext部署在邏輯主機上的配置的名稱
public String getVirtualServerName();
}
3.2 ServletConfig介面
ServletConfig為servlet配置物件,用於在servlet容器初始化servlet時傳遞資訊。介面定義如下:
package javax.servlet;
import java.util.Enumeration;
//servlet配置物件,用於在servlet容器初始化servlet時傳遞資訊
public interface ServletConfig {
//返回當前servlet例項的名稱
public String getServletName();
//返回ServletContext的引用
public ServletContext getServletContext();
//返回ServletContext的引用
public String getInitParameter(String name);
//返回當前servlet例項所有的初始化引數名稱
public Enumeration<String> getInitParameterNames();
}
示例(僅列出關鍵程式碼): web.xml中servlet配置如下:
<servlet>
<servlet-name>stuServlet</servlet-name>
<servlet-class>servlet.StuServlet</servlet-class>
<init-param>
<param-name>stuId</param-name>
<param-value>001</param-value>
</init-param>
<init-param>
<param-name>stuName</param-name>
<param-value>apple</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>stuServlet</servlet-name>
<url-pattern>/stuServlet</url-pattern>
</servlet-mapping>
StuServlet.java
package servlet;
import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Enumeration;
public class StuServlet extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
/**************** ServletConfig ******************/
ServletConfig servletConfig = getServletConfig();
//返回當前servlet例項的名稱
String servletName = servletConfig.getServletName(); //stuServlet
//返回ServletContext的引用
ServletContext servletContextFromConfig = servletConfig.getServletContext();
//返回當前servlet例項指定名稱的初始化引數值
String stuId = servletConfig.getInitParameter("stuId"); //001
//返回當前servlet例項所有的初始化引數名稱
Enumeration<String> initParamNames = servletConfig.getInitParameterNames(); //stuId,stuName
}
}
3.3 Servlet介面
servlet是在web server端執行的java小程式,是所有Servlet需要實現的介面,定義了所有servlet必須實現的方法,方法包含服務請求、從服務中移除servlet以及servlet的整個生命週期(init、service、destroy)。接收和響應來自web客戶端的請求。介面定義如下:
package javax.servlet;
import java.io.IOException;
//Servlet介面定義了所有Servlet必須實現的方法
public interface Servlet {
//servlet初始化時呼叫的初始化方法,只會被呼叫一次,且在接收任意請求前完成初始化
public void init(ServletConfig config) throws ServletException;
//返回ServletConfig的引用
public ServletConfig getServletConfig();
//由servlet容器呼叫,對請求進行響應,需要注意多執行緒呼叫的情況(對臨界資源的訪問)
public void service(ServletRequest req, ServletResponse res)
throws ServletException, IOException;
public String getServletInfo();
//servlet容器呼叫,表示從容器中移除servlet,只會被呼叫一次,,此時呼叫service方法的所有執行緒都退出或超時了
public void destroy();
}
3.4 GenericServlet抽象類
GenericServlet抽象類是對Servlet介面和ServletConfig介面的預設實現,類定義如下:
public abstract class GenericServlet
implements Servlet, ServletConfig, java.io.Serializable
{
//具體實現方法在此略過,同實現介面一樣
}
3.5 HttpServlet類
HttpServlet提供了抽象類,用於子類建立http servlet。同時子類必須重寫doGet、doPost、doPut、doDelete、init、destory中至少一個方法,用於管理servlet生命週期中持有的資源。通常不需要重寫public service方法,對於doOption和doTrace方法也不需要重寫。servlet通常在多執行緒中執行,需要考慮臨界資源的同步訪問。HttpServlet類定義如下:
package javax.servlet.http;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Method;
import java.text.MessageFormat;
import java.util.Enumeration;
import java.util.Locale;
import java.util.ResourceBundle;
import javax.servlet.*;
//HttpServlet提供了抽象類,用於子類建立http servlet
public abstract class HttpServlet extends GenericServlet
{
//由server(透過service方法呼叫)呼叫,用於處理get請求(也支援head請求)。使用時需要重寫該方法
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException{}
//返回HttpServletRequest物件最近修改時間,時間為子1970年1月1日到現在的毫秒數。如果不知道,則返回負數
protected long getLastModified(HttpServletRequest req) {}
//接收來自service方法的head請求並處理(重寫只需要設定response headers)
protected void doHead(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException{}
//由server(透過service方法呼叫)呼叫,用於處理post請求。可一次性發送無長度限制的資料
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException{}
//由server(透過service方法呼叫)呼叫,用於處理put請求。客戶端可放置檔案到伺服器
protected void doPut(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException{}
protected void doDelete(HttpServletRequest req,
HttpServletResponse resp)
throws ServletException, IOException{}
//由server(透過service方法呼叫)呼叫,用於處理option請求
protected void doOptions(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException{}
//由server(透過service方法呼叫)呼叫,用於處理trace請求。通常用於debug
protected void doTrace(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException{}
//接收來自公開方法service(ServletRequest req, ServletResponse res)的請求,並分發給doXX方法處理
protected void service(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException
{
String method = req.getMethod();
if (method.equals(METHOD_GET)) {
long lastModified = getLastModified(req);
if (lastModified == -1) {
// servlet doesn't support if-modified-since, no reason
// to go through further expensive logic
doGet(req, resp);
} else {
long ifModifiedSince = req.getDateHeader(HEADER_IFMODSINCE);
if (ifModifiedSince < lastModified) {
// If the servlet mod time is later, call doGet()
// Round down to the nearest second for a proper compare
// A ifModifiedSince of -1 will always be less
maybeSetLastModified(resp, lastModified);
doGet(req, resp);
} else {
resp.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
}
}
} else if (method.equals(METHOD_HEAD)) {
long lastModified = getLastModified(req);
maybeSetLastModified(resp, lastModified);
doHead(req, resp);
} else if (method.equals(METHOD_POST)) {
doPost(req, resp);
} else if (method.equals(METHOD_PUT)) {
doPut(req, resp);
} else if (method.equals(METHOD_DELETE)) {
doDelete(req, resp);
} else if (method.equals(METHOD_OPTIONS)) {
doOptions(req,resp);
} else if (method.equals(METHOD_TRACE)) {
doTrace(req,resp);
} else {
//
// Note that this means NO servlet supports whatever
// method was requested, anywhere on this server.
//
String errMsg = lStrings.getString("http.method_not_implemented");
Object[] errArgs = new Object[1];
errArgs[0] = method;
errMsg = MessageFormat.format(errMsg, errArgs);
resp.sendError(HttpServletResponse.SC_NOT_IMPLEMENTED, errMsg);
}
}
//將請求發給protected service處理,通常該方法不需要重寫
@Override
public void service(ServletRequest req, ServletResponse res)
throws ServletException, IOException{}
}
3.6 ServletRequest介面
ServletRequest介面定義了一個包含使用者請求資訊的物件給servlet的service方法。ServletRequest提供的資料包括引數名稱和值、屬性、輸入流。介面定義如下:
package javax.servlet;
import java.io.*;
import java.util.*;
//定義了一個包含使用者請求資訊的物件給servlet的service方法。ServletRequest提供的資料包括引數名稱和值、屬性、輸入流
public interface ServletRequest {
//獲取屬性資訊,沒有則返回null
public Object getAttribute(String name);
//返回屬性名稱集合
public Enumeration<String> getAttributeNames();
//返回請求body的字元編碼,如果沒有指定則返回null
public String getCharacterEncoding();
//設定請求body的字元編碼,且設定必須在讀取引數或讀取使用getReader()操作前,否則不生效
public void setCharacterEncoding(String env) throws UnsupportedEncodingException;
//返回請求body的位元組長度,或者當長度不確定或超出了int的最大長度,則返回-1
public int getContentLength();
//返回請求body的位元組長度,或者當長度不確定,則返回-1
public long getContentLengthLong();
//返回請求body的mine type,如果不確定,則返回null
public String getContentType();
//獲取請求bode的資料二進位制流的ServletInputStream
public ServletInputStream getInputStream() throws IOException;
//返回指定引數的值,當引數有多個值時,則返回讀取到的第一個值。對於請求body中的資料,則不能使用該方法,應該使用getInputStream或getReader
public String getParameter(String name);
//返回引數名稱集合,沒有則返回空集合
public Enumeration<String> getParameterNames();
//返回指定引數的值陣列,沒有則返回null
public String[] getParameterValues(String name);
//返回引數map,key為引數名稱,value為引數值
public Map<String, String[]> getParameterMap();
//返回請求使用的協議版本號,如:HTTP/1.1
public String getProtocol();
//返回請求使用的schema,如:http、https、ftp
public String getScheme();
//返回請求傳送的伺服器主機名稱,即是Host頭中:前面值
public String getServerName();
//返回請求傳送的埠號,即是Host頭中:後面的值
public int getServerPort();
//以BufferedReader方式讀取請求體body中字元資料
public BufferedReader getReader() throws IOException;
//返回客戶端或最後一個發出請求的代理的ip
public String getRemoteAddr();
返回客戶端或最後發出請求的代理的完整合規的名稱
public String getRemoteHost();
//在request中設定屬性
public void setAttribute(String name, Object o);
//移除request中的屬性
public void removeAttribute(String name);
//返回客戶端將接收內容的方言(如zh_CN)
public Locale getLocale();
//返回客戶端將接收內容的方言集合(如zh_CN、zh)
public Enumeration<Locale> getLocales();
//請求是使用安全通道(如https)
public boolean isSecure();
//返回RequestDispatcher物件,它作為對給定路徑上資源的包裝,它可用於請求重定向或在相應中包含靜態或動態資源
public RequestDispatcher getRequestDispatcher(String path);
//返回客戶端或發請求的最後代理的埠號
public int getRemotePort();
//返回接收請求的介面的ip主機名(如:ip6-localhost)
public String getLocalName();
//返回接收請求的介面的ip地址
public String getLocalAddr();
//返回接收請求的介面的埠號
public int getLocalPort();
//獲取最後發出的ServletRequest的ServletContext
public ServletContext getServletContext();
//將請求轉為非同步模式,同時初始化它的AsyncContext(包含有ServletRequest和ServletResonse),並返回AsyncContext
public AsyncContext startAsync() throws IllegalStateException;
public AsyncContext startAsync(ServletRequest servletRequest,
ServletResponse servletResponse)
throws IllegalStateException;
//檢查請求是否已經裝為非同步模式
public boolean isAsyncStarted();
//檢查請求是否支援非同步模式
public boolean isAsyncSupported();
//獲取AsyncContext
public AsyncContext getAsyncContext();
//返回DispatcherType(如:REQUEST)
public DispatcherType getDispatcherType();
}
3.7 HttpServletRequest介面
HttpServletRequest繼承自ServletRequest介面,提供了關於http servlet請求資訊。介面定於如下:
package javax.servlet.http;
import java.io.IOException;
import java.util.*;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
//HttpServletRequest繼承自ServletRequest介面,提供了關於http servlet請求資訊。
public interface HttpServletRequest extends ServletRequest {
//基本驗證識別符號
public static final String BASIC_AUTH = "BASIC";
//表單驗證識別符號
public static final String FORM_AUTH = "FORM";
//客戶端驗證識別符號
public static final String CLIENT_CERT_AUTH = "CLIENT_CERT";
//驗證識別符號
public static final String DIGEST_AUTH = "DIGEST";
//返回用於保護servlet的驗證模式名稱,值為BASIC_AUTH,FORM_AUTH, CLIENT_CERT_AUTH, DIGEST_AUTH中之一或特別指定的值,沒有則返回null
public String getAuthType();
//返回當前請求客戶端傳送的所有Cookie物件組成的陣列
public Cookie[] getCookies();
//返回header值為時間的自1970年1月1日(GMT)至今的毫秒值(header如:If-Modified-Since),沒有則返回-1
public long getDateHeader(String name);
//返回指定header的值,沒有則返回null
public String getHeader(String name);
//返回指定header的值集合(有些相同header有多個不同值,如Accept-Language),沒有則返回null
public Enumeration<String> getHeaders(String name);
//返回所有header的名稱集合,沒有則返回null
public Enumeration<String> getHeaderNames();
//以int方式獲取header值,沒有則返回-1
public int getIntHeader(String name);
//返回請求的方法
public String getMethod();
//返回關聯當前請求的額外地址資訊(起於servlet地址止於引數,並以/結尾),如:servlet匹配地址為/teacher/*,請求為/teacher/one.jsp,則額外地址為/one.jsp
public String getPathInfo();
//返回額外地址資訊(參考getPathInfo方法)的真實資源地址
public String getPathTranslated();
//返回web應用程式的路徑
public String getContextPath();
//返回在地址後的引數串
public String getQueryString();
//返回登入使用者名稱
public String getRemoteUser();
//檢查user是否在許可權role中
public boolean isUserInRole(String role);
//返回當前授權使用者的Principal物件
public java.security.Principal getUserPrincipal();
//返回請求指定的sessionId
public String getRequestedSessionId();
//返回URI地址(URL的一部分,不包含引數,如:/teacher/one.jsp)
public String getRequestURI();
//返回URL地址(不包含引數部分,如:http://localhost:8080/teacher/one.jsp)
public StringBuffer getRequestURL();
//返回Servlet請求地址,不包含額外地址資訊(如:servlet匹配地址為/teacher/*,請求為/teacher/one.jsp,則返回為/teacher)
public String getServletPath();
//返回HttpSession,引數create表示沒有時是否要建立HttpSession,true:要 false:不要
public HttpSession getSession(boolean create);
//返回HttpSession,若沒有則直接新建一個
public HttpSession getSession();
//修改Session,建立新一個的session id
public String changeSessionId();
//檢測當前session是否合法
public boolean isRequestedSessionIdValid();
//檢測請求的session id是否來自於cookie
public boolean isRequestedSessionIdFromCookie();
//檢測請求的session id是否來自於url
public boolean isRequestedSessionIdFromURL();
//基於容器的安全策略授權請求的使用者
public boolean authenticate(HttpServletResponse response)
throws IOException,ServletException;
//基於容器的登入機制驗證登入
public void login(String username, String password)
throws ServletException;
//退出登入
public void logout() throws ServletException;
//對於multipart/form-data型別,返回所有的Part集合
public Collection<Part> getParts() throws IOException, ServletException;
//返回指定名稱的Part
public Part getPart(String name) throws IOException, ServletException;
//返回HttpUpgradeHandler例項用於升級
public <T extends HttpUpgradeHandler> T upgrade(Class<T> handlerClass)
throws IOException, ServletException;
}
3.8 ServletResponse介面
ServletResponse為servlet用於響應客戶端的物件,介面定義如下:
package javax.servlet;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Locale;
//ServletResponse為servlet用於響應客戶端的物件
public interface ServletResponse {
//返回相應的MIME字元編碼(可透過setCharacterEncoding、setContentType、setLocale方法確定),若沒有指定,則返回ISO-8859-1,參考RFC 2047 (http://www.ietf.org/rfc/rfc2047.txt)
public String getCharacterEncoding();
//返回相應的MIME body的content-type(只能透過方法setContentType設定,且在response提交之前),沒有則為null
public String getContentType();
//返回ServletOutputStream,適合在response中寫二進位制資料
public ServletOutputStream getOutputStream() throws IOException;
//返回PrintWriter,能夠向客戶端傳送文字字元,預設編碼為ISO-8859-1
public PrintWriter getWriter() throws IOException;
//設定response響應的字元編碼,會覆蓋方法setContentType或setLocale的設定,設定需在getWriter或response提交之前,否則不生效
public void setCharacterEncoding(String charset);
//設定response響應內容body的長度,即是設定Content-Length的header值
public void setContentLength(int len);
//設定response響應內容body的長度,即是設定Content-Length的header值(@since Servlet 3.1)
public void setContentLengthLong(long len);
//設定response的content type,包含內容型別和字元編碼,如:text/html;charset=UTF-8
public void setContentType(String type);
//設定response body的buffer大小,在實際傳送內容前,更大的buffer可以寫更多的內容,不過小buffer能讓客戶端更快收到資料
public void setBufferSize(int size);
//獲取response body的buffer大小
public int getBufferSize();
//強制重新整理buffer,即是提交response
public void flushBuffer() throws IOException;
//清空buffer中的內容(不清空status code、headers)
public void resetBuffer();
//檢測response是否提交
public boolean isCommitted();
//清空buffer中的內容(同時清空status code、headers)
public void reset();
//設定response的方言
public void setLocale(Locale loc);
//獲取response的方言
public Locale getLocale();
}
3.9 HttpServletResponse
HttpServletResponse繼承ServletResponse介面,提供在傳送響應response時,提供http功能,如訪問http的headers和cookies,介面定義如下:
package javax.servlet.http;
import java.io.IOException;
import java.util.Collection;
import javax.servlet.ServletResponse;
//繼承ServletResponse介面,提供在傳送響應response時,提供http功能,如訪問http的headers和cookies
public interface HttpServletResponse extends ServletResponse {
//新增cookie
public void addCookie(Cookie cookie);
//檢測是否含有指定名稱的header
public boolean containsHeader(String name);
//編碼指定url(包含session id, 根據瀏覽器是否支援來決定session id是否放到url)
public String encodeURL(String url);
//編碼在sendRedirect方法中的指定url(根據瀏覽器是否支援來決定session id是否放到url)
public String encodeRedirectURL(String url);
//傳送錯誤,包含status和指定訊息
public void sendError(int sc, String msg) throws IOException;
//傳送錯誤,包含status
public void sendError(int sc) throws IOException;
//使用指定url傳送臨時重定向給客戶端,此時code為302。地址在傳送給客戶端前,servlet會將地址轉為絕對地址,
//地址沒有以/開頭,會解析為相對當前地址,
//地址以一個/開頭,會解析為相對servlet容器root地址,
//地址以兩個/(即//)開頭,會解析為網路地址
public void sendRedirect(String location) throws IOException;
//以date型別設定header,如果已經存在則覆蓋
public void setDateHeader(String name, long date);
//以date型別新增header,相同header可以存在多個值
public void addDateHeader(String name, long date);
//設定header,如果已經存在則覆蓋
public void setHeader(String name, String value);
//新增header,相同header可以存在多個值
public void addHeader(String name, String value);
//設定header,如果已經存在則覆蓋
public void setIntHeader(String name, int value);
//新增header,相同header可以存在多個值
public void addIntHeader(String name, int value);
//設定status(當沒有錯誤時,有錯誤時不生效)
public void setStatus(int sc);
//獲取response當前status
public int getStatus();
//獲取response中指定名稱的header(@since Servlet 3.0)
public String getHeader(String name);
//獲取response中指定名稱的header集合(@since Servlet 3.0)
public Collection<String> getHeaders(String name);
//獲取response中的header名稱集合
public Collection<String> getHeaderNames();
//後續還有響應status定義,在此略過,詳情請檢視原始碼
}
四、備註
更多基於原始碼的關於Servlet,在後續逐步介紹。