javax.servlet 包含定義servlet與servlet容器之間契約的類和接口
javax.servlet.http 包含定義http servlet與servlet容器之間契約的類和接口
javax.servlet.annotation 包含對servlet、filter和listener進行标注的注解。它還為标注元件指定中繼資料。
javax.servlet.descriptor 包含為web應用程式的配置資訊提供程式設計式通路的類型。
servlet技術的核心是servlet接口,這是所有servlet類都必須直接或者間接實作的一個接口。使用者的請求會引發servlet容器調用一個servlet的service方法,并給這個方法傳入一個servletrequest執行個體和一個servletresponse執行個體。
servlet接口定義了以下5個方法。
void init(servletconfig config) throws servletexception
void destroy()
java.lang.string getservletinfo()
servletconfig getservletconfig()
init、service和destroy方法屬于servlet聲明周期方法。servlet容器将根據以下原則調用這三個方法。
1. init。第一次請求servlet時,servlet容器就會調用這個方法。在後續的請求中,将不再調用該方法。可以利用這個方法來編寫一些應用程式初始化相關的代碼。在調用這個方法時,servlet容器會傳遞一個servletconfig。一般來說,會将servletconfig賦給一個類級變量,以便servlet類中的其他方法也可以使用這個對象。
2. service。每次請求servlet時,servlet容器都會調用這個方法。必須在這裡編寫要servlet完成的相應代碼,第一次請求servlet時,servlet容器會調用init方法和service方法,對于後續請求,則隻調用service方法。
3. destroy。要銷毀servlet時,servlet容器就會調用這個方法。它通常發生在解除安裝應用程式,或者關閉servlet容器的時候。一般來說,可以在這個方法中編寫一些資源清理相關的代碼。
servlet中的另外兩個方法是非聲明周期方法:getservletinfo和getservletconfig。
1. getservletinfo。該方法傳回servlet的描述,可以傳回可能有用的任意字元串,甚至是null。
2. getservletconfig。該方法傳回由servlet容器傳給init方法的servletconfig。但是,為了讓getservletconfig傳回非null值,你肯定已經為傳給init方法的servletconfig賦給了一個類級變量。
*必須注意個一點是線程安全性。一個應用程式中的所有使用者将共用一個servlet執行個體,是以不建議使用類級變量,除非他們是隻讀的,或者是java.util.concurrent.atomic包中的成員。
1.3、編寫基礎的servlet應用程式
package servlet;
import java.io.ioexception;
import java.io.printwriter;
import javax.servlet.servlet;
import javax.servlet.servletconfig;
import javax.servlet.servletexception;
import javax.servlet.servletrequest;
import javax.servlet.servletresponse;
import javax.servlet.annotation.webservlet;
@webservlet(name="myservlet",urlpatterns={"/my"})
public class myservlet implements servlet{
private transient servletconfig servletconfig ;
@override
public void destroy() {
// todo auto-generated method stub
}
public servletconfig getservletconfig() {
return servletconfig;
public string getservletinfo() {
return "my servlet";
public void init(servletconfig servletconfig) throws servletexception {
this.servletconfig = servletconfig ;
public void service(servletrequest req, servletresponse res)
throws servletexception, ioexception {
string servletname = servletconfig.getservletname() ;
res.setcontenttype("text/html");
printwriter writer = res.getwriter() ;
writer.print("<html><head></head><body>hello from " + servletname + "</body></html>") ;
}
對于每一個http請求,servlet容器都會建立一個serveltrequest執行個體,并将它傳給servlet的service方法。servletrequest封裝有關請求的資訊。
下面是servletrequest接口中的方法。
public int getcontentlength()
傳回請求主體中的位元組數。如果不知道位元組的長度,該方法将傳回-1。
public java.lang.string getcontenttype()
傳回請求主體mime類型,如果不知道類型,則傳回null。
public java.lang.string getparameter(java.lang.string name)
傳回指定請求參數的值
public java.lang.string getprotocol()
傳回這個http請求的協定名稱和版本号
getparameter是servletrequest中最常用的方法。該方法通常用來傳回一個html表單域的值。
getparameter也可以用來擷取查詢字元串的值。例如:如果利用下面這個uri調用一個servlet:
<a target="_blank" href="http://domain/context/servletname?id=123">http://domain/context/servletname?id=123</a>
将可以在servlet中利用下面這個語句來擷取id的值
string id = request.getparameter(“id”) ;
注意,如果該參數不存在,那麼getparameter将傳回null。
servletresponse中定義的其中一個方法是getwriter方法,它傳回可以将文本傳給用戶端的java.io.printwriter。在預設情況下,printwriter對象采用iso-8859-1編碼。
為了從一個servlet内部擷取某個初始參數的值,應該在由servlet容器傳給servlet的init方法的servletconfig中調用getinitparameter方法。getinitparameter方法的簽名如下:
java.lang.getinitparameter(java.lang.string name) ;
此外,getinitparameternames方法則是傳回所有初始化參數名稱的一個enumeration:
java.util.enumeration<java.lang.string> getinitparameternames()
除了這2個方法外,servletconfig還提供了另一個很有用的方法:getservletcontext。可以利用這個方法從servlet内部擷取servletcontext。
import javax.servlet.annotation.webinitparam;
@webservlet(name="servletconfigdemoservlet",
urlpatterns={"/servletconfigdemo"},
initparams={
@webinitparam(name="admin",value="benjamin"),
@webinitparam(name="email",value="[email protected]")
}
)
public class servletconfigdemoservlet implements servlet{
return "servletconfig demo";
servletconfig servletconfig = getservletconfig() ;
string admin = servletconfig.getinitparameter("admin") ;
string email = servletconfig.getinitparameter("email") ;
writer.print("<html><head></head><body>admin:"+admin+"<br/>email:"+email+"</body></html>") ;
servletcontext辨別servlet應用程式。每個web應用程式隻有一個context。在分布式環境中,一個應用程式同時部署到多個容器中,并且每台java虛拟機都有一個servletconfig對象。
在servletconfig中調用getservletcontext方法可以獲得servletcontext。
genericservlet通過在init方法中将servletconfig對象賦給一個類級變量servlet-config,實作對servletconfig的儲存。下面是geneericservlet的源代碼:
package javax.servlet;
import java.io.serializable;
import java.util.enumeration;
import java.util.resourcebundle;
public abstract class genericservlet
implements servlet, servletconfig, serializable
{
private static final string lstring_file = "javax.servlet.localstrings";
private static resourcebundle lstrings = resourcebundle.getbundle("javax.servlet.localstrings");
private transient servletconfig config;
public void destroy()
{
}
public string getinitparameter(string name)
servletconfig sc = getservletconfig();
if (sc == null) {
throw new illegalstateexception(lstrings.getstring("err.servlet_config_not_initialized"));
return sc.getinitparameter(name);
public enumeration<string> getinitparameternames()
return sc.getinitparameternames();
public servletconfig getservletconfig()
return this.config;
public servletcontext getservletcontext()
return sc.getservletcontext();
public string getservletinfo()
return "";
public void init(servletconfig config)
throws servletexception
this.config = config;
init();
public void init()
public void log(string msg)
getservletcontext().log(getservletname() + ": " + msg);
public void log(string message, throwable t)
getservletcontext().log(getservletname() + ": " + message, t);
public abstract void service(servletrequest paramservletrequest, servletresponse paramservletresponse)
throws servletexception, ioexception;
public string getservletname()
return sc.getservletname();
大家考慮一下為什麼genericservlet中有兩個init方法?
genericservlet通過在init方法中将servletconfig對象賦給一個類級變量servletconfig,實作對servletconfig的儲存。
但是如果在類中覆寫了這個方法,則調用servlet中的init方法,并且必須調用super.init(servletconfig)來儲存servletconfig。為了避免這麼做,genericservlet又另外提供了一個init方法,它不帶參數。當把servletconfig賦給servletconfig之後,這個方法就會被第一個init方法調用,進而不影響servletconfig的建立。
1.9.1 httpservlet
httpservlet類覆寫javax.servlet.genericservlet類,在使用httpservlet時,還要使用httpservletrequest和httpservletresponse對象,它們分别辨別servlet請求和servlet響應。httpservletrequest接口內建javax.servlet.servletrequest,httpservletresponse繼承javax.servlet.servletresponse。
這個新的service方法與javax.servlet.servlet中的差別在于,前者接受的是httpservletrequest和httpservletresponse,而不是servletrequest和servletresponse。
原始的service方法将請求和響應對象進行向下轉換,分别從servlet容器轉換成httpservletrequest和httpservletresponse,并調用新的service方法。
httpservlet中新的service方法會檢視通常用來發送琴秋(通過調用request.getmethod)的http方法,并調用以下某個方法(doget、dopost、dohead、doput、dotrace、dooptions和dodelete)。
總之,httpservlet中有兩項特性是genericservlet所沒有的:
1、不覆寫service方法,而是覆寫doget、dopost,或者兩者都覆寫調。
2、将用httpservletrequest和httpservletresponse代替servletrequest和servletresponse
1.9.2 httpservletrequest
httpservletrequest表示http環境中的servlet請求。它內建javax.servlet.servletrequest接口,并增加了幾個方法,例如:
java.lang.string getcontextpath()
傳回表示請求context的請求uri部分。
cookie[] getcookies()
傳回一個cookie對象數組
java.lang.string getheader(java.lang.string name)
傳回指定http标頭的值
java.lang.string getmethod()
傳回發出這條請求的http方法的名稱
java.lang.string getquerystring()
傳回請求url中的查詢字元串
httpsession getsession()
傳回與這個請求有關的session對象。如果沒有找到,則建立新的session對象。
httpsession getsession(boolean create)
傳回與這個請求有關的session對象。如果沒有找到,并且create參數為true,那麼将建立新的session對象。如果為false,傳回空
1.9.3 httpservletresponse
httpservletresponse表示http環境下的servlet響應。下面是其中定義的部分方法:
void addcookie(cookie cookie)
給這個響應對象添加cookie
void addheader(java.lang.string name,java.lang.string value)
給這個響應對象添加标頭
void sendredirect(java.lang.string location)
發送響應代号,将浏覽器重定向到指定的位置
package app01c;
import javax.servlet.http.httpservlet;
import javax.servlet.http.httpservletrequest;
import javax.servlet.http.httpservletresponse;
@suppresswarnings("serial")
public class simpleservlet extends httpservlet{
protected void doget(httpservletrequest req, httpservletresponse resp)
resp.setcontenttype("text/html") ;
printwriter writer = resp.getwriter() ;
writer.print("<html><head></head><body>simple servlet</body></html>") ;
public class welcomeservlet extends httpservlet{
writer.print("<html><head></head><body>welcome</body></html>") ;
<?xml version="1.0" encoding="utf-8"?>
<web-app version="2.5"
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/xmlschema-instance"
xsi:schemalocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
<servlet>
<servlet-name>ss</servlet-name>
<servlet-class>app01c.simpleservlet</servlet-class>
<load-on-startup>10</load-on-startup>
</servlet>
<servlet-mapping>
<url-pattern>/simple</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>ww</servlet-name>
<servlet-class>app01c.welcomeservlet</servlet-class>
<load-on-startup>20</load-on-startup>
<url-pattern>/welcome</url-pattern>
</web-app>
這樣我們就可以利用下面這些路徑去通路它們了:
http://localhost:8080/app01c/simple
http://localhost:8080/app01c/welcome
servlet技術是javaee技術的組成部分。servlet容器中運作的所有servlet,以及容器與servlet之間的契約,都采用了javax.servlet.servlet接口的形式。javax.servlet包也提供了實作servlet接口的genericservlet抽象類。這是一個便利類,可以通過擴充它來建立servlet。但是,大多數現代的servlet都在http環境中處理請求。是以,将javax.servlet.http.httpservlet類子類化會更有意義。httpservlet類本身也是genericservlet的一個子類。