Servlet 2.x 規範
Servlet 2.x 規範
sun 公司制訂的一種用來擴充套件 web 伺服器功能的元件規範。
Servlet 介面
:init(ServletConfig config)、service(ServletRequest req, ServletResponse res)、destroy()GenericServlet 抽象類
:實現了 Servlet 介面中的 init, destroy 方法HttpServlet 抽象類
:繼承了 GenericServlet 抽象類,實現了 service()ServletConfig 介面
:String getInitParameter(String paraName)ServletRequest 介面
:HttpServletRequest 的父介面ServletResponse 介面
:HttpServletResponse 的父介面
一、Servlet
1.1 Servlet 的生命週期
Servlet 的生命週期指 Servlet 容器如何去建立 Servlet 物件、如何給 Servlet 物件分配資源、如何呼叫 Servlet 物件的方法來處理請求、以及如何銷燬 Servlet 物件的整個過程。
Servlet 生命週期的四個階段:
(1) 例項化:容器呼叫 Servlet 的構造器,建立 Servlet 物件。
情況1:容器收到請求後才建立 Servlet 物件。預設,容器只會為 Servlet 建立唯一一個例項。
情況2: 容器啟動時交某些 Servlet 物件建立好(需要配置 load-on-startup)。load-on-startup 引數值必須是 >=0 的整數,越小優先順序(即先例項化)越高。
(2) 初始化:容器在建立好 Servlet 物件後,立即呼叫 init() 方法。
init() 只執行一次
GenericServlet 已經實現了 init(),該方法會將容器建立好的 ServletConfig 物件作為引數傳給 init()。
ServletConfig 物件提供一個 getInitParameter() 來訪問 Servlet 的初始化引數。
如果 GenericServlet 的 init() 提供的初始化操作不滿足需要,可以重寫 init() 無參方法,不重寫 init(ServletConfig config)
(3) 就緒
Servlet 物件可以呼叫了,容器收到請求後,會呼叫 Servlet 物件的 service() ,該方法會依據請求型別(get/post)分別呼叫 doGet(), doPost()
(4) 銷燬:Servlet 容器在銷燬 Servlet 物件之前,會呼叫 destroy() 方法。
1.2 Servlet 如何處理請求資源路徑
Servlet 容器會先假設訪問的是一個 Servlet ,會依據應用名(appname)找到應用所在的資料夾,然後找到 web.xml 檔案。
匹配
- 精確匹配(完全匹配)
- 萬用字元匹配:使用 * 匹配任意長度的字串。eg:
- 字尾匹配:使用 . 開頭,後面可以接任意字元。eg: .do
如果都不匹配,則容器認為訪問的是一個靜態資原始檔(html/css/js),如果找到則返回,否則返回404。
1.3 Servlet 是如何執行的?
- 瀏覽器依據 ip, port 建立與 Servlet 容器之間的連線。
- 瀏覽器將請求資料打包(即按照 http 協議的要求,將相關資料封閉成一個數據包,即請求資料包)併發送給 Servlet 容器。
- Servlet 容器解析請求資料包,並將解析後的資料放到 request 物件上。同時建立一個 response 物件。
- Servlet 容器依據請求資源路徑找到 Servlet 的配置,然後建立 Servlet 物件。
- Servlet 呼叫 service 方法,並且會將事先建立好的 request 物件和 response 物件作為 service 方法的引數傳遞給 Servlet 物件。
- Servlet 通過 request 物件獲得請求引數,進行相應的處理,然後將處理結果寫到 response 物件上。
- Servlet 讀取 response 物件上的資料,然後將處理結果打包(響應資料包)併發送給瀏覽器。
- 瀏覽器解析響應資料包,將返回的資料展現給使用者。
1.4 例項
public class HelloWorldServlet extends HttpServlet {
public void service(HttpServletRequest req, HttpServletResponse res) throws IOException, ServletException {
//1、讀請求引數值
String qtyStr = req.getParameter("qty");
int qty = Integer.parseInt(qtyStr);
//2、處理請求
String rs = "";
for (int i = 0; i < qty; i++) {
rs += "<h1>Hello World</h1>";
}
//3、設定一個訊息頭content-type,告訴瀏覽器返回的資料型別是一個html文件及編碼格式
//告訴伺服器使用out輸出時使用指定的編碼格式進行編碼
res.setContentType("text/html;charset=utf-8");
//4、獲得一個輸出流
PrintWriter out = res.getWriter();
//5、呼叫流的方法進行輸出,其實質是將處理結果寫到了res物件上
out.println(rs);
out.close();
}
}
配置 WEB-INF/web.xml 配製檔案
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
version="3.1">
<servlet>
<servlet-name>helloWord</servlet-name>
<!--類名要完整(包名,類名都要全)-->
<servlet-class>com.herolei.HelloWorldServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>helloWord</servlet-name>
<url-pattern>/hello</url-pattern>
</servlet-mapping>
</web-app>
啟動程式,訪問 http://localhost:8080/hello?qty=30
補充:web 打包後的目錄如下
appname(應用名)
└──WEB-INF
├──classes .class檔案
├──lib .jar檔案,lib資料夾可選
└──web.xml 部署描述檔案
二、Listener
Servlet 規範當中定義的一種特殊的元件,用來監聽容器產生的事件並進行處理。
容器會產生兩大類事件:
- 生命週期相關的事件:容器在建立或者銷燬 request, servletContext(Servlet 上下文)時產生的事件。對應的介面有 ServletRequestListener、ServletContextListener。
- 繫結相關的事件:容器呼叫了 request, servletContext 的 setAttribute, removeAttribute 時產生的事件。。對應的介面有 ServletContextAttributeListener、ServletRequestAttributeListener。
public interface ServletContextListener extends EventListener {
// 容器初始化
void contextInitialized(ServletContextEvent ctx);
// 容器銷燬
void contextDestroyed(ServletContextEvent ctx);
}
public interface ServletContextAttributeListener extends EventListener {
void attributeAdded(ServletContextAttributeEvent event);
void attributeRemoved(ServletContextAttributeEvent event);
void attributeReplaced(ServletContextAttributeEvent event);
}
三、Filter
public interface Filter {
// 初始化 Filter
void init(FilterConfig filterConfig) throws ServletException;
// 呼叫,如果要繼續呼叫下一個 Filter,需要呼叫 chain.doFilter(request, response)
void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException;
// 銷燬
public void destroy();
}
public interface FilterChain {
void doFilter(ServletRequest request, ServletResponse response) throws IOException, ServletException;
}
參考:
每天用心記錄一點點。內容也許不重要,但習慣很重要!