1.GenericServlet原理分析
GenericServlet類是一個抽象類,并且是Servlet接口的實現(xiàn)類,HttpServlet類的父類,下面我們通過一張圖來更直觀的了解GenericServlet的類結(jié)構(gòu),如圖1-1所示:
圖1-1 GenericServlet類結(jié)構(gòu)
通過圖1-1發(fā)現(xiàn),GenericServlet類不僅實現(xiàn)了Servlet接口,還實現(xiàn)了ServletConfig接口。因此,在GenericServlet類中一定包含Servlet接口和ServletConfig接口的所有方法.。接下來,我們創(chuàng)建一個類來模擬GenericServlet的功能,詳情請參考
GenericServlet案例詳解,下載源代碼。
(1)創(chuàng)建應(yīng)用Example11,新建一個類MyServlet,該類實現(xiàn)了Servlet接口,具體代碼如例1-1所示:
例1-1 MyServlet.java
public class MyServlet implements Servlet {
/*
* 成員變量config
* */
private ServletConfig config;
public void init(){}
@Override
public void destroy() {
System.out.println("destroy run......");
}
/*
* 返回config,該方法一定在init方法之后執(zhí)行
* */
@Override
public ServletConfig getServletConfig() {
return config;
}
@Override
public String getServletInfo() {
return "MyServlet....";
}
/*
* init()方法是這些方法中,最先被調(diào)用的,在本類構(gòu)造方法執(zhí)行后執(zhí)行.
* */
@Override
public void init(ServletConfig servletConfig) throws ServletException {
/*
* 將服務(wù)器創(chuàng)建的servletConfig對象賦值給本類的成員變量config,方便在其他方法中使用
* */
this.config=servletConfig;
init();
}
@Override
public void service(ServletRequest arg0, ServletResponse arg1)
throws ServletException, IOException {
System.out.println("service run ......");
}
/*
* 獲得Servlet的初始化參數(shù)
* */
public String getInitParameter(String name){
return this.config.getInitParameter(name);
}
/*
* 獲得ServletContext對象
* */
public ServletContext getServletContext(){
return this.config.getServletContext();
}
public String getServletName(){
return this.config.getServletName();
}
}
由例1-1可知,當前的MyServlet類中不僅包含了Servlet接口的五個方法,還包含了以下方法:
- public ServletConfig getServletContext()
- public String getInitParameter(String name)
- public String getServletName()
由于GenericServlet類實現(xiàn)了ServletConfig接口,那么必然重寫了ServletConfig的方法,因此在MyServlet 類中也要定義了ServletConfig的相關(guān)方法,這些方法的實現(xiàn)都是通過成員變量config調(diào)用自身的方法來實現(xiàn)的。
另外MyServlet類中還有一個無參的init()方法,該方法不是生命周期方法,它會被生命周期方法init(ServletConfig)方法調(diào)用。 這樣做的目的是為了方便繼承MyServlet類的子類,完成自己所需要的初始化工作,而不用再定義一個ServletConfig類型的成員變量。
(2)再創(chuàng)建一個Servlet類,讓該類繼承MyServlet 類,具體代碼如例1-2所示:
例1-2 SonServlet.java
public class SonServlet extends MyServlet{
@Override
public void init(ServletConfig config) {
// TODO Auto-generated method stub
System.out.println("i am sonservlet.......");
}
@Override
public void service(ServletRequest arg0, ServletResponse arg1)
throws ServletException, IOException {
String value=getInitParameter("name");
}
}
由例1-2可知,在SonServlet中定義了本類的init(ServletConfig)方法,該方法會覆蓋父類的init(ServletConfig)方法。那么第一次訪問該Servlet時,服務(wù)器會調(diào)用子類的init()生命周期方法進行初始化,父類的init()生命周期方法沒有被調(diào)用,那么父類的config成員就為null,當 SonServlet 類中的service方法調(diào)用父類的getInitParameter()方法時就會出現(xiàn)空指針異常。所以,SonServlet 類中不能覆寫有參的init()方法,而應(yīng)該覆寫無參的init()方法。這也是為什么在MyServlet類中定義一個無參的init()方法,然后再在有參的init方法中調(diào)用無參的init方法的原因。
以上案例就是為了方便開發(fā)人員開發(fā)Servlet,以后就不用去實現(xiàn)Servlet接口?,F(xiàn)在我們來看一下GenericServlet的源碼,源碼的jar包。具體代碼如例1-3所示:
例1-3 GenericServlet.java
public abstract class GenericServlet implements Servlet, ServletConfig,
java.io.Serializable {
private static final long serialVersionUID = 1L;
private transient ServletConfig config;
public GenericServlet() {}
@Override
public void destroy() {}
@Override
public String getInitParameter(String name) {
return getServletConfig().getInitParameter(name);
}
@Override
public Enumeration<String> getInitParameterNames() {
return getServletConfig().getInitParameterNames();
}
@Override
public ServletConfig getServletConfig() {
return config;
}
@Override
public ServletContext getServletContext() {
return getServletConfig().getServletContext();
}
@Override
public String getServletInfo() {
return "";
}
@Override
public void init (ServletConfig config) throws ServletException {
this.config = config;
this.init();
}
public void init() throws ServletException {}
public void log(String msg) {
getServletContext().log(getServletName() + ": " + msg);
}
public void log(String message, Throwable t) {
getServletContext().log(getServletName() + ": " + message, t);
}
@Override
public abstract void service(ServletRequest req, ServletResponse res)
throws ServletException, IOException;
@Override
public String getServletName() {
return config.getServletName();
}
}
由例1-3可知,GenericServlet類的原理和我們剛才寫的MyServlet 類的原理是一樣的。繼承GenericServlet 類比實現(xiàn)Servlet接口更加方便Servlet開發(fā)。
本文版權(quán)歸傳智播客Java培訓學院所有,歡迎轉(zhuǎn)載,轉(zhuǎn)載請注明作者出處。謝謝!
作者:傳智播客Java培訓學院
首發(fā):http://xamj520.com/javaee