手動添加Servlet構造函數出現的問題及猜想
我們需要用到servlet的時候,都是右鍵,新建一個servlet,但是有人註意到一個細節沒有,當我們手動給我們的servlet添加一個構造函數時候,會出現什麽狀況呢?
1.嘗試添加無參構造函數
直接上代碼
public class Test extends HttpServlet { Test(String a){ System.out.println("這是構造函數"); } @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throwsServletException, IOException { } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { } }
好了,一個我們都熟悉的基本的servlet,它的名字叫做Test。
為了方便起見,我們重寫接口Servlet中的init()函數,並配置這個Servlet預加載,更直觀的幫助我們理解。
public class Test extends HttpServlet {Test(){ System.out.println("這是構造函數"); }
@Override public void init() throws ServletException { System.out.println("這是Init函數"); } @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { } @Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { } }
好了,關於預加載,簡單說,就是服務器運行的的時候,就會實例化這個servlet並且走完init()函數,這樣,我們只需開啟服務器,不需要進行請求,就可以看出這個servlet‘是否被正確實例化。
好了,測試開始,啟動服務器。
實驗結果:手動寫的Test()構造函數沒有被執行,init()函數也沒被執行。瀏覽器訪問此Servlet時,404錯誤。
實驗結論:當我們手動一個無參Servlet構造函數時,服務器就不會創建我們請求的servlet實例,當然也不會走servlet的生命周期
2.嘗試有參構造函數
public class Test extends HttpServlet { Test(String a){ System.out.println("這是構造函數"); } @Override public void init() throws ServletException { System.out.println("這是Init函數"); } @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { } }
結果同無參構造函數一樣:服務器不會創建servlet實例。
3.web.xml給出錯誤提示
錯誤說,我們的servlet沒有默認的構造函數。
我們現在證明了,手動寫一個有參和無參構造函數後,服務器都不會創建這個實例,根據xml錯誤,我們保留默認無參構造函數,並重載一個有參構造函數
public class Test extends HttpServlet { Test(){} Test(String a){ System.out.println("這是構造函數"); } @Override public void init() throws ServletException { System.out.println("這是Init函數"); } @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { } }
實驗結果:構造函數仍無法輸出任何內容,init()方法也不輸出,說明servlet仍未被創建實例。
4.結果猜想:我們都知道,當我們請求servlet時候,服務器會根據servlet的servlet-class,反射創建servlet對象,並且會將一切參數傳入到實例中(例如request,response,servletConfig等),
大致流程就是Class.from("我們的servlet-class").getDeclaredConstructor(上述說的參數類型...).newInstance(上述說的參數的值...)
因為,只有這樣構造實例,才能把一些必要的數據(request,response,servletConfig),封裝到實例裏面。
況且,這個有參構造函數,第一句又調用了無參構造函數,也就是 this();
這樣,通過有參構造函數將參數傳遞過來並保存,然後在無參構造函數中,進行初始化servlet,因此,當我們重寫了無參構造,服務器就無法完成這些流程,因此,服務器直接做一個判斷,如果你手動寫了構造函數,直接讓這個servlet無法初始化。
手動添加Servlet構造函數出現的問題及猜想