Servlet編寫步驟:
A:自定義類繼承HttpServlet並根據需要重寫相關方法
B:在web.xml文件中註冊Servlet
<servlet>
<servlet-name>HelloServletDemo01</servlet-name>
<servlet-class>com.hsj.servlet.HelloServletDemo01</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>HelloServletDemo01</servlet-name>
<url-pattern>/helloServletDemo01</url-pattern>
</servlet-mapping>
C:訪問Servlet
自定義Servlet有三種方式:
A:實現Servlet接口
B:繼承GenericServlet
C:繼承HttpServlet
自定義Servlet的編寫步驟:
A:自定義類實現Servlet接口並實現接口中所有的方法並打印輸出日誌方便觀察效果
B:在站點部署描述符文件(WEB-INF/web.xml)中註冊自定義的Servlet
<!-- 註冊自定義的Servlet -->
<servlet>
<!-- servlet-name的值可以任意取,但為了方便使用一般寫成自定義Servlet類的簡單類名 -->
<servlet-name>ServletLifeCycler</servlet-name>
<!-- servlet-class的值為自定義Servlet的完整包名+類名,即完全限定名 -->
<servlet-class>com.hsj.servlet.ServletLifeCycler</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>ServletLifeCycler</servlet-name>
<!-- url-pattern的值是我們訪問當前Servlet路徑的一部分,內容隨便寫,但為了開發方便,大家都約定:
當前Servlet的簡單類名並且把第一個字母小寫 -->
<url-pattern>/servletLifeCycler</url-pattern>
</servlet-mapping>
訪問Servlet的格式:http://localhost:8080/項目的站點名/url-pattern的值, Servlet的工作原理:
String url=http://localhost:8080/ServletDemo01/servletLifeCycler
int startIndex=url.lastIndexOf("/")
url.substring(startIndex)的執行結果為:/servletLifeCycler
在站點部署描述符文件中查找所有的servlet-mapping的url-pattern的值,如果和/servletLifeCycler相等,説明
找到了要訪問的Servlet的入口,然後查找和當前servlet-mapping是兄弟關係的servlet-name的值並且存儲起來,
繼續查找當前servlet-name的父元素servlet-mapping的兄弟節點servlet的子節點servlet-name的內容ServletLifeCycler
然後和之前servlet-mapping的子節點servlet-name的值進行比較看是否相等,如果不相等則繼續查詢其它的節點,如果相等
則找到了要訪問servlet的類的完整包名+類名即servlet的字節點servlet-name的兄弟節點servlet-class的值,然後
通過反射技術就可以實例化自定義的Servlet類了,
Class clz=Class.forName("com.hsj.servlet.ServletLifeCycler");
Object obj=clz.newInstance(); <===> ServletLifeCycler slc=new ServletLifeCycler(); Object obj=slc;
自動調用構造函數,之後自動調用init(ServletConfig config),然後調用service(req,res)完成客户端的處理請求,
之後再次訪問則只調用service(req,res);
面試題:請簡述Servlet生命週期函數及其執行流程?
init():當用户第一次訪問當前Servlet時自動調用,用來完成初始化工作,而且只調用一次。
service():用户每次當前當前Servlet都會自動調用當前方法,用來完成客户端發送過來的請求
destroy():當前Servlet銷燬時自動調用的方法,用來做資源釋放工作,而且只調用一次。
Servlet實例化的過程取決於web.xml文件中的<load-on-startup>0</load-on-startup>的值,如果大於等於0,則
表示tomcat服務器一啓動則馬上實例化,數字的順序代表了Servlet實例化的順序,數字越小越優先實例化
查看類的繼承結構圖的快捷鍵:ctrl+t
在Servlet中如何得到JSP的隱式對象?
方法的形式就是:request,response
out對象:PrintWriter out=response.getWriter();
session對象:HttpSession session=request.getSession();
application對象:ServletContext application=request.getServletContext();
config對象:config=this.getServletConfig();
自定義註冊Servlet
<!-- 註冊自定義的Servlet -->
<servlet>
<!-- servlet-name的值可以任意取,但為了方便使用一般寫成自定義Servlet類的簡單類名 -->
<servlet-name>ServletLifeCycler</servlet-name>
<!-- servlet-class的值為自定義Servlet的完整包名+類名,即完全限定名 -->
<servlet-class>com.hsj.servlet.ServletLifeCycler</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>ServletLifeCycler</servlet-name>
<!-- url-pattern的值是我們訪問當前Servlet路徑的一部分,內容隨便寫,但為了開發方便,大家都約定:
當前Servlet的簡單類名並且把第一個字母小寫 -->
<url-pattern>/servletLifeCycler</url-pattern>
</servlet-mapping>
面試題:flush()和close()方法的區別:
相同點:都會刷新緩衝區並馬上將數據寫出到底層設備中
不同點:
A:flush()方法只能刷新緩衝區 close()方法會首先刷新緩衝區然後在關閉流對象。
B:flush()之後可以繼續寫出內容,close()之後就不能再寫出內容了,否則報錯
如果同時編寫了init()和init(ServletConfig config)則訪問當前Servlet時只會調用init(ServletConfig config)方法,
如果想同時調用init()方法,則可以在init(ServletConfig config)中加上代碼:super.init(config);
如果沒有提供init(ServletConfig config),只提供了init()方法會咋樣?會自動調用init()方法
關於Servlet註解
如果在註解中只有一個value屬性在使用,此時的value=可以省略
@WebServlet("/qq")//如果沒有顯示指定Servlet的名字,默認默認情況下當前Servlet的名字為當前Servlet類的完整包名+類名,即完全限定名
@WebServlet(value="/qq")
@WebServlet(name="ServletDemo01",value="/qq")
@WebServlet(name="ServletDemo01",value={"/qq","/feiqiu","/ly"})
@WebServlet(name="ServletDemo01",urlPatterns={"/qq","/feiqiu","/ly"})
GenericServlet類中的一些方法
String getInitParameter(String name) :返回具有指定名稱的初始化參數。通過調用config. getInitParameter(name)實現
ServletConfig getServletConfig() :返回傳遞到init()方法的ServletConfig對象
ServletContext getServletContext() : 返回config對象中引用的ServletContext
abstract void service(Request request,Response response) throws ServletException,IOException :由Servlet引擎調用為請求對象描述的請求提供服務。這是GenericServlet中唯一的抽象方法。因此它也是唯一必須被子類所覆蓋的方法