JavaWeb之Servlet一
時間:2019.03.27
主機環境:MacBookPro
Servlet
1. Servlet簡介
-
Servlet是JavaWeb的三大組件之一,屬於動態資源
-
Servlet的功能
-
接受請求數據
-
處理請求:每個Servlet都是唯一的,能處理的請求都是不同的
-
完成響應
-
-
Servlet需要我們自己編寫
2. 實現Servlet的方式(三種)
-
實現javax.servlet.Servlet接口
-
繼承javax.servlet.GenericServlet類
-
繼承javax.servlet.http.HttpServlet類,它是GenericServlet的子類
3. Servlet接口
-
接口中的方法,生命周期方法是Tomcat自動調用的方法
publicclassMyServletimplementsServlet{ //是生命周期方法 //會在Servlet對象被創建後馬上執行,並只執行一次 publicvoidinit(ServletConfigservletConfig) throwsServletException; //可以用來獲取Servlet的配置信息 publicServletConfiggetServletConfig(); ? //是生命周期方法//會被調用多次 //每次處理請求都會被調用 publicvoidservice(ServletRequestservletRequest, ServletResponseservletResponse) throwsServletException, IOException; //可以獲取Servlet的信息 publicStringgetServletInfo(); //是生命周期方法 //會在Servlet被銷毀之前調用,並且只會被調用一次 //該方法不能銷毀Servlet publicvoiddestroy(); } ?
-
在web.xml文件中配置Servlet
<servlet> <!--xxx可以隨便寫--> <servlet-name>xxx</servlet-name> <servlet-class>servlet.MyServlet</servlet-class> </servlet> ? <servlet-mapping> <servlet-name>xxx</servlet-name> <!--必須以/開頭,後面隨便寫--> <url-pattern>/MyServlet</url-pattern> </servlet-mapping>
-
ServletConfig接口
-
一個ServletConfig對象對應一段web.xml中的Servlet配置信息
-
API:
-
String getServletName():獲取<servlet.name>的內容
-
ServletContext getServletContext():獲取Servlet上下文的對象
-
String getInitParament():通過名稱獲取指定初始化參數的值
-
Enumeration getInitParamentName():獲取所有初始化參數的名稱
-
-
<servlet> <servlet-name>One</servlet-name> <servlet-class>cn.itcast.servlet.OneServlet</servlet-class> <init-param> <param-name>paramName1</param-name> <param-value>paramValue1</param-value> </init-param> <init-param> <param-name>paramName2</param-name> <param-value>paramValue2</param-value> </init-param> </servlet>
4. GenericServlet類
-
GenericServlet是Servlet接口的實現類,我們可以通過繼承GenericServlet來編寫自己的Servlet。
下面是GenericServlet類的源代碼
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(); } }
-
init()方法
-
init()方法是用來在繼承GenericServlet類時,解決想要覆蓋init(ServletConfig config)方法忘記給config賦值的問題。此時,只需要覆蓋init()方法即可。
-
init()方法不是生命周期方法,但想要在構造Servlet時讓Tomcat調用該方法,需要在init(ServletConfig config)中調用init()方法
-
-
GenericServlet實現了所有ServletConfig的方法。
5. HttpServlet類
-
HttpServlet是GenericServlet的子類,它提供了對HTTP請求的特殊支持,所以通常我們都會通過繼承HttpServlet來完成自定義的Servlet。
-
HttpServlet覆蓋了service()方法
-
HttpServlet中有兩個service()方法,一個service(ServletRequest,ServletResponse),另一個為service(HttpServletRequest,HttpServletResponse),前者為覆蓋,後者不是覆蓋。
-
service(ServletRequest,ServletResponse)是生命周期方法,由Tomcat自動調用,在該方法中
-
首先對兩個參數強制轉換,將類型轉換為Http協議相關的類型,
-
再調用service(HttpServletRequest,HttpServletResponse)方法,
-
該方法會通過request得到當前請求的請求方式(GET或POST),
-
再根據請求方式調用相應的doGet()和doPost()方法。
-
-
所以,不用重寫service()方法,只需要重寫doGet()和doPost()方法。如果沒有覆蓋doGet()和doPost()方法,並且被調用了,會出現405。
-
6. Servlet細節
-
Servlet只有一個實例對象,就有可能會現時出一個Servlet同時處理多個請求
Servlet不是線程安全的。這說明Servlet的工作效率很高,但也存在線程安全問題!所以我們不應該在Servlet中隨便創建成員變量,因為可能會存在一個線程對這個成員變量進行寫操作,另一個線程對這個成員變量進行讀操作。
做到以下幾點:
-
不要在Servlet中創建成員,創建局部變量即可
-
可以創建無狀態成員,即只聲明
-
可以創建有狀態的成員,但狀態必須為只讀的
-
-
默認情況下,服務器會在某個Servlet第一次收到請求時創建它。也可以在web.xml中對Servlet進行配置,使服務器啟動時就創建Servlet。
<servlet> <servlet-name>hello1</servlet-name> <servlet-class>cn.itcast.servlet.Hello1Servlet</servlet-class> <load-on-startup>0</load-on-startup> </servlet> <servlet-mapping> <servlet-name>hello1</servlet-name> <url-pattern>/hello1</url-pattern> </servlet-mapping> ? <servlet> <servlet-name>hello2</servlet-name> <servlet-class>cn.itcast.servlet.Hello2Servlet</servlet-class> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>hello2</servlet-name> <url-pattern>/hello2</url-pattern> </servlet-mapping>
在<load-on-startup>中,給出一個非負整數。值小的先被創建,即hello1先創建,hello2後創建。
-
<url-pattern>
-
用來指定Servlet的訪問路徑,可以在<servlet-maping>中有多個
-
可以使用通配符*,通配符要麽為前綴,要麽為後綴,不能出現在URL中間位置,也不能只有通配符
路徑匹配:<url-pattern>/servlet/*</url-pattern>,可以匹配/servlet/a、/servlet/b等
擴展名匹配:<url-pattern>*.do</url-pattern>,可以匹配/abc/def/ghi.do、/a.do等
啥都匹配:<url-pattern>/*</url-pattern>,可以匹配所有url
-
-
web.xml文件的“繼承”
-
每一個JavaWeb應用都有一個web.xml,都“繼承”conf/web.xml
-
<?xmlversion="1.0" encoding="ISO-8859-1"?> ? <web-appxmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" version="3.0"> <servlet> <servlet-name>default</servlet-name><!--他的優先級最低,如果請求沒人處理,那麽它就會來處理,顯示404--> <servlet-class>org.apache.catalina.servlets.DefaultServlet</servlet-class> <init-param> <param-name>debug</param-name> <param-value>0</param-value> </init-param> <init-param> <param-name>listings</param-name> <param-value>false</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> ? <servlet> <servlet-name>jsp</servlet-name> <servlet-class>org.apache.jasper.servlet.JspServlet</servlet-class> <init-param> <param-name>fork</param-name> <param-value>false</param-value> </init-param> <init-param> <param-name>xpoweredBy</param-name> <param-value>false</param-value> </init-param> <load-on-startup>3</load-on-startup> </servlet> ? <servlet-mapping> <servlet-name>default</servlet-name> <url-pattern>/</url-pattern> <!--沒有url能匹配上,就會匹配這個--> </servlet-mapping> ? <servlet-mapping> <servlet-name>jsp</servlet-name> <url-pattern>*.jsp</url-pattern> <url-pattern>*.jspx</url-pattern> </servlet-mapping> ? <session-config> <!--session的過期時間為30分鐘--> <session-timeout>30</session-timeout> </session-config> ? <!-- 這裏省略了大概4000多行的MIME類型的定義,這裏只給出兩種MIME類型的定義 --> <mime-mapping> <extension>bmp</extension> <mime-type>image/bmp</mime-type> </mime-mapping> <mime-mapping> <extension>htm</extension> <mime-type>text/html</mime-type> </mime-mapping> ? <welcome-file-list> <welcome-file>index.html</welcome-file> <welcome-file>index.htm</welcome-file> <welcome-file>index.jsp</welcome-file> </welcome-file-list> </web-app>
7. ServletContext
-
概述
-
一個項目只有一個ServletContext對象,我們可以在很多個Servlet中來獲取這個唯一的對象,使用它可以給Servlet傳遞數據,完成共享數據。
-
ServletContext對象在Tomcat啟動時創建,在Tomcat關閉時銷毀
-
-
獲取ServletContext
在Servlet接口中,init(ServletConfig config)方法可以獲取ServletConfig對象,該對象有getServletContext()方法可以獲取ServletContext對象
public class MyServlet implements Servlet { public void init(ServletConfig config) { ServletContext context = config.getServletContext(); } … }
在GenericServlet類中,有成員變量ServletConfig,有getServletContext()方法可以獲取ServletContext對象
public class MyServlet extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) { ServletContext context = this.getServletContext(); } }
-
域對象的功能
-
域對象是用來在多個Servlet中傳遞數據,所以域對象必須要有存和取數據的功能。JavaWeb中包含四個域對象,分別是ServletContext、PageContext、HttpSession、ServletRequest
-
ServletContext對象用來操作數據的方法
-
void setAttribute(String name, Object value):用來存儲一個對象,相當於在ServletContext中有一個Map對象,所以在存儲時name值不能相同
-
Object getAttribute(String name):用來獲取數據,因為返回值為Object對象,需要強制轉換
-
void removeAttribute(String name):刪除一個對象
-
Enumeration getAttributeNames():獲取所有域屬性的名稱
-
-
-
獲取初始化參數
-
Servlet也可以獲取初始化參數,但它只能獲取局部的初始化參數,即只能獲取自己的初始化參數
-
使用ServletContext可以配置公共的初始化參數
-
<web-app...> ... <context-param> <param-name>paramName1</param-name> <param-value>paramValue1</param-value> </context-param> <context-param> <param-name>paramName2</param-name> <param-value>paramValue2</param-value> </context-param> </web-app>
ServletContext context = this.getServletContext(); String value1 = context.getInitParameter("paramName1"); String value2 = context.getInitParameter("paramName2"); System.out.println(value1 + ", " + value2);
-
獲取相關資源的方法
-
獲取真實路徑
-
獲取a.txt的真實路徑String realPath = this.getServletContext.getRealPath("/a.txt");
-
windows系統下這種方法獲取的路徑是代盤符的
-
-
獲取資源流
-
獲取a.txt的t資源流:InputStream in = this.getServletContext.getResourceAsStream("/a.txt");
-
-
-
獲取/WEB-INF下所有資源的路徑:Set set = this.getServletContext.getResourcePaths("/WEB-INF");
-
-
JavaWeb之Servlet一