教育行業(yè)A股IPO第一股(股票代碼 003032)

全國(guó)咨詢/投訴熱線:400-618-4000

Java培訓(xùn)之GenericServlet類

更新時(shí)間:2016年07月25日17時(shí)52分 來源:傳智播客Java培訓(xùn)學(xué)院 瀏覽次數(shù):

1.GenericServlet原理分析

GenericServlet類是一個(gè)抽象類,并且是Servlet接口的實(shí)現(xiàn)類,HttpServlet類的父類,下面我們通過一張圖來更直觀的了解GenericServlet的類結(jié)構(gòu),如圖1-1所示:

                                                           圖1-1 GenericServlet類結(jié)構(gòu)                                          
通過圖1-1發(fā)現(xiàn),GenericServlet類不僅實(shí)現(xiàn)了Servlet接口,還實(shí)現(xiàn)了ServletConfig接口。因此,在GenericServlet類中一定包含Servlet接口和ServletConfig接口的所有方法.。接下來,我們創(chuàng)建一個(gè)類來模擬GenericServlet的功能,詳情請(qǐng)參考GenericServlet案例詳解,點(diǎn)擊此處 下載源代碼。
(1)創(chuàng)建應(yīng)用Example11,新建一個(gè)類MyServlet,該類實(shí)現(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對(duì)象賦值給本類的成員變量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對(duì)象
     * */
    public ServletContext getServletContext(){
       return this.config.getServletContext();
    }
    public String getServletName(){
       return this.config.getServletName();
    }
}
由例1-1可知,當(dāng)前的MyServlet類中不僅包含了Servlet接口的五個(gè)方法,還包含了以下方法:
  • public ServletConfig getServletContext()
  • public String getInitParameter(String name)
  • public String getServletName()
由于GenericServlet類實(shí)現(xiàn)了ServletConfig接口,那么必然重寫了ServletConfig的方法,因此在MyServlet 類中也要定義了ServletConfig的相關(guān)方法,這些方法的實(shí)現(xiàn)都是通過成員變量config調(diào)用自身的方法來實(shí)現(xiàn)的。
另外MyServlet類中還有一個(gè)無參的init()方法,該方法不是生命周期方法,它會(huì)被生命周期方法init(ServletConfig)方法調(diào)用。 這樣做的目的是為了方便繼承MyServlet類的子類,完成自己所需要的初始化工作,而不用再定義一個(gè)ServletConfig類型的成員變量。
(2)再創(chuàng)建一個(gè)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)方法,該方法會(huì)覆蓋父類的init(ServletConfig)方法。那么第一次訪問該Servlet時(shí),服務(wù)器會(huì)調(diào)用子類的init()生命周期方法進(jìn)行初始化,父類的init()生命周期方法沒有被調(diào)用,那么父類的config成員就為null,當(dāng) SonServlet 類中的service方法調(diào)用父類的getInitParameter()方法時(shí)就會(huì)出現(xiàn)空指針異常。所以,SonServlet 類中不能覆寫有參的init()方法,而應(yīng)該覆寫無參的init()方法。這也是為什么在MyServlet類中定義一個(gè)無參的init()方法,然后再在有參的init方法中調(diào)用無參的init方法的原因。
以上案例就是為了方便開發(fā)人員開發(fā)Servlet,以后就不用去實(shí)現(xiàn)Servlet接口?,F(xiàn)在我們來看一下GenericServlet的源碼,源碼的jar包點(diǎn)擊此處 進(jìn)行下載。具體代碼如例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 類比實(shí)現(xiàn)Servlet接口更加方便Servlet開發(fā)。

本文版權(quán)歸傳智播客Java培訓(xùn)學(xué)院所有,歡迎轉(zhuǎn)載,轉(zhuǎn)載請(qǐng)注明作者出處。謝謝!
作者:傳智播客Java培訓(xùn)學(xué)院
首發(fā):http://xamj520.com/javaee
0 分享到:
和我們?cè)诰€交談!