servlet 基礎原理 (映射方式、運行初始化參數)

簡介

servlet 本身是一個 JAVA 程序(或者其他環境的程序),  通過 web.xml 文件把 請求資源頁 反射成 JAVA對象到內存, 反射的對象需要實現 javax.servlet 裏的 HttpServlet 接口


映射方式

web.xml 是關鍵
一個 <servlet> 對應一個 <servlet-mapping>, 關聯唯一鍵值 <servlet-name>,  從而把 實現了 SERVLET接口的 JAVA類 映射到 URL的資源
這種映射在 JEE 5.0之後的版本變成默認的了, 不用配置, 可以沒有這個文件
  <servlet>
	  <servlet-name>Hello</servlet-name>
	  <servlet-class>cn.it.HelloServlet</servlet-class>
  </servlet>
  
  <servlet-mapping>
  		<servlet-name>Hello</servlet-name>
  		<url-pattern>/hello/1234</url-pattern>
  </servlet-mapping>

訪問主機名/hello/1234 就能映射到 cn.it.HelloServlet,  前提該類要實現好 implements Servlet 接口

Servlet 接口

servlet 是一個通用的接口, 只是看起來象或者就是爲 HTTP專門設計的, 帶http打頭的類 一般 繼承至 GenericServlet, 並且用對應的 http參數類繼承或者實現 servlet參數或者實現
比如  HttpServletRequest(tomcat中爲RequestFacade實現) Ex ==> ServletRequest 這類形式
也就是 servlet 提供了一個應用層協議的交互方式的統一接口, 把一些 參數配置, 加載方式, 請求應答 等統一了;

public void init(ServletConfig config) throws ServletException

config 裏面讀好了 web.xml 裏面的 init param
XML
  <servlet>
	  <servlet-name>Hello</servlet-name>
	  <servlet-class>cn.it.HelloServlet</servlet-class>
	  
	  <init-param>
	  	<param-name>WEB_NAME</param-name>
	  	<param-value>HELLO IT</param-value>	
	  </init-param>
	  
	  <init-param>
	  	<param-name>WEB_NAME2</param-name>
	  	<param-value>HELLO IT2</param-value>	
	  </init-param> 
	  
	  <init-param>
	  	<param-name>WEB_NAME3</param-name>
	  	<param-value>HELLO IT3</param-value>	
	  </init-param> 
  </servlet>
	public void init(ServletConfig config) throws ServletException {
		System.out.println("Init");
		
		System.out.println(config.getInitParameter("WEB_NAME")); // 輸出: HELLO IT

		Enumeration<String> names = config.getInitParameterNames();
		
		while( names.hasMoreElements() )
		{
			String name = names.nextElement();
			System.out.println(name + ":" + config.getInitParameter(name)); // 遍歷輸出
																			// init
																			// PARAM
		}
首次使用某個 servlet 時, 可能init中出現較長時間的初始化動作, 用戶體驗不好, 通過添加配置 <servlet > 中的 <load-on-startup>節點, 讓服務器開啓時即完成 類的init操作, 改元素的值越小, 加載的順序越靠前


public void service(ServletRequest req, ServletResponse res)
throws ServletException, IOException {

標準請求應答方式類型的協議通訊方式封裝
具體實現爲 org.apache.catalina.connector.RequestFacade ==> HttpServletRequest ==> ServletRequest


servlet 層次範圍



轉載下別人的筆記

喜羊羊同學 : http://blog.csdn.net/wandan_/article/details/17401883

一、Servlet生命週期

       servlet的生命週期:init(ServletConfig)、service(ServletRequest,ServletResponse)、destroy()

[java] view plaincopy在CODE上查看代碼片派生到我的代碼片
  1. public class HelloWorldInit implements Servlet {  
  2.     public HelloWorldInit(){  
  3.         System.out.println("hello 默認構造");  
  4.     }  
  5.     public void init(ServletConfig config) throws ServletException {  
  6.         System.out.println("init");  
  7.     }  
  8.     public void service(ServletRequest request, ServletResponse response)  
  9.             throws ServletException, IOException {  
  10.         System.out.println("service");  
  11.     }  
  12.     public void destroy() {  
  13.         System.out.println("destroy");  
  14.     }  
  15.     public ServletConfig getServletConfig() {  
  16.         return null;  
  17.     }  
  18.     public String getServletInfo() {  
  19.         return null;  
  20.     }  
  21. }  

輸出結果:

            

爲什麼會創建構造方法?

Tomcat服務器加載web.xml中的<servlet-class>com.test.HelloWorldInit</servlet>時,會根據這個類路徑通過反射創建該類的實例。在服務器中操作大概過程如下:

[java] view plaincopy在CODE上查看代碼片派生到我的代碼片
  1. Class clazz = Class.forName("com.test.HelloWorldInit");  
  2. Object obj = clazz.newInstance();//調用了構造方法  

然後通過反射獲取該對象裏的init和service方法並調用,調用時會傳入相應的實參(ServletConfig、ServletRequest和ServletResponse)

二、init(ServletConfig config)和service(ServletRequest request, ServletResponse response)倆方法的參數解析 

[java] view plaincopy在CODE上查看代碼片派生到我的代碼片
  1. public void init(ServletConfig config) throws ServletException {  
  2.     System.out.println("config:"+config);  
  3. }  
  4. public void service(ServletRequest request, ServletResponse response)  
  5.         throws ServletException, IOException {  
  6.     System.out.println("request:"+request+"\n"+"response:"+response);  
  7. }  

輸入結果:

           

上圖輸出的結果分別是ServletConfig、ServletRequest、ServletResponse的實現類,下圖爲源碼中的實現

         

  (1)javax.servlet.ServletConfig(接口),該接口下有四個抽象方法

         

[java] view plaincopy在CODE上查看代碼片派生到我的代碼片
  1. public void init(ServletConfig config) throws ServletException {  
  2.         //1、<servlet-name>返回這個裏面的名稱</servlet-name>  
  3.         System.out.println(config.getServletName());  
  4.         //2、返回指定初始化參數名稱的值,如果參數不存在就返回Null(在web.xml中要配置初始化參數)  
  5.         System.out.println(config.getInitParameter("gf"));  
  6.           
  7.         //3、返回當前servlet的所有的初始化參數的名稱,返回的是一個Enumeration(枚舉)  
  8.         Enumeration<String> names = config.getInitParameterNames();  
  9.         while(names.hasMoreElements()){  
  10.             String name = names.nextElement();  
  11.             System.out.println(name + ":" + config.getInitParameter(name));  
  12.         }  
  13.         //4、ServletConfig保存了當前web項目的 ServletContext的引用  
  14.         ServletContext sc = config.getServletContext();  
  15.         System.out.println(sc);  
  16.         //實現類:org.apache.catalina.core.ApplicationContextFacade  
  17.     }  
[html] view plaincopy在CODE上查看代碼片派生到我的代碼片
  1. <servlet>  
  2.     <servlet-name>helloWorldInit</servlet-name>  
  3.     <servlet-class>cn.test.HelloWorldInit</servlet-class>  
  4.     <!-- 配置初始化參數列表 -->  
  5.     <init-param>  
  6.         <!-- 初始化參數的名稱 -->  
  7.         <param-name>gf</param-name>  
  8.         <!-- 初始化參數的值 -->  
  9.         <param-value>規範</param-value>  
  10.     </init-param>  
  11. </servlet>  

(2)javax.servlet.ServletRequest和javax.servlet.ServletResponse(service方法的兩個參數)]

[html] view plaincopy在CODE上查看代碼片派生到我的代碼片
  1.             /**第一個參數*/  
  2. //接口:javax.servlet.ServletRequest  
  3. //實現類:org.apache.catalina.connector.RequestFacade  
  4. /*  
  5.  * 關係:  
  6.  *   * public class RequestFacade implements HttpServletRequest {  
  7.  *   * public interface HttpServletRequest extends ServletRequest {  
  8.  *   
  9.  *   總結: RequestFacade --> HttpServletRequest  --> ServletRequest  
  10.  *   ************  
  11.  *   ServletRequest req = new RequestFacade();  
  12.  *   HttpServletRequest http = new RequestFacade();  
  13.  *   HttpServletRequest http2 = (HttpServletRequest)req;  
  14.  */  
[html] view plaincopy在CODE上查看代碼片派生到我的代碼片
  1. /**第二個參數*/  
  2.         //接口:javax.servlet.ServletResponse  
  3.         //實現類:org.apache.catalina.connector.ResponseFacade  
  4.           
  5.         /* 關係:  
  6.          *   * public class ResponseFacade implements HttpServletResponse {  
  7.          *   * public interface HttpServletResponse extends ServletResponse {  
  8.          *     
  9.          *   * 總結:ResponseFacade  --> HttpServletResponse  --> ServletResponse  
  10.          */  
  11.         HttpServletResponse response = (HttpServletResponse)resp;  

三、Servlet實現初始化工作

[java] view plaincopy在CODE上查看代碼片派生到我的代碼片
  1. public class FirstServlet extends HttpServlet {  
  2.     //進行初始化,直接覆蓋GenericServlet的init()方法  
  3.     @Override  
  4.     public void init() throws ServletException {  
  5.         //初始化工作  
  6.     }  
  7.     public void doGet(HttpServletRequest request, HttpServletResponse response)  
  8.             throws ServletException, IOException {  
  9.         this.doPost(request, response);  
  10.     }  
  11.     public void doPost(HttpServletRequest request, HttpServletResponse response)  
  12.             throws ServletException, IOException {  
  13.     }  
  14. }  
[html] view plaincopy在CODE上查看代碼片派生到我的代碼片
  1.  <servlet>  
  2.     <servlet-name>FirstServletxx</servlet-name>  
  3.     <servlet-class>cn.itcast.servlet.FirstServlet</servlet-class>  
  4.     <!-- 配置當前servlet在服務器啓動時加載順序  
  5.         取值:0-6 ,值越小,優先加載  
  6.      -->  
  7.     <load-on-startup>2</load-on-startup>  
  8. </servlet>  
  9. <servlet-mapping>  
  10.     <servlet-name>FirstServletxx</servlet-name>  
  11.     <url-pattern>/firstServlet</url-pattern>  
  12. </servlet-mapping>  

四、servlet的虛擬路徑
      1) 只能使用 / 或 * 開頭
      2) / 和 *. 不能同時存在
      3) / 或 /* 表示任意
      4) 只有*.才表示通配符

五、項目路徑

     (1)getAbsolutePath( )  

              案例1:

[java] view plaincopy在CODE上查看代碼片派生到我的代碼片
  1. public static void main(String[] args) {  
  2.     File file = new File("");  
  3.     System.out.println(file.getAbsolutePath());//absolute絕對的意思  
  4. }  

       輸出結果:
                     

       用命令窗口執行:

                    JAVA項目的class文件是存放在項目根目錄的bin目錄下

                    

       案例2:

[java] view plaincopy在CODE上查看代碼片派生到我的代碼片
  1. public static void main(String[] args) {  
  2.     File file = new File("/") ; //   '/'是相對路徑,相對於當前盤符 可以獲得當前盤符  
  3.     System.out.println(file.getAbsolutePath());  
  4. }  

        輸出結果都爲:F:\(命令運行和eclipse運行)
        總結:getAbsolutePath()使用java命令時輸出的路徑是當前Java命令停留的目錄,使用eclipse運行時輸出的路徑是當前項目根目錄的絕對路徑

       注意:生成jar包后里面的沒有src和bin目錄的,生成jar包的過成是把bin目錄下的文件全都拷貝過來,所以將配置文件放在src下其實就是在根目錄下

    

     (2)類加載器獲取路徑

[java] view plaincopy在CODE上查看代碼片派生到我的代碼片
  1. public static void main(String[] args) {  
  2.     //類加載器  
  3.     //通過類 -> 獲得字節碼 -> 獲得類加載器 -> 獲得資源路徑  
  4.     //路徑指向class文件存放的目錄  
  5.     URL url = Hello.class.getClassLoader().getResource("");  
  6. /       InputStream is = Hello.class.getClassLoader().getResourceAsStream(""); //跟getResource一樣  
  7.     System.out.println(url);  
  8. }  

輸出結果:file:/F:/myeclipse/Workspaces/TestProject/WebRoot/WEB-INF/classes/
注意:類加載器不能使用"/"

    (3)ServletContext獲取路徑

              ServletContext是對當前項目上下文的描述(對當前web項目所有內容的描述),tomcat爲每一個web項目單獨創建一個區域,用來管理整個項目。此區域稱爲ServletContext。

              context root是指當前項目的根目錄:

                    * tomcat --> webapps/webName

                    * myeclipse --> webName/WebRoot 指向的是WebRoot目錄

[java] view plaincopy在CODE上查看代碼片派生到我的代碼片
  1. public void doGet(HttpServletRequest req, HttpServletResponse resp)  
  2.             throws ServletException, IOException {  
  3.         ServletContext sc2 = this.getServletConfig().getServletContext();  
  4.         ServletContext sc = this.getServletContext();  
  5.         //1 、  
  6.         String path = sc.getRealPath("/1.html");//獲得實際路徑,要求/開頭  
  7.         System.out.println(path);//     F:\apache-tomcat-7.0.29\webapps\day06\1.html  
  8.         //2、獲得資源文件  
  9.         URL url = sc.getResource("/1.html");   
  10.         System.out.println(url.getPath());//   /localhost/day06/1.html  
  11.         //3、  
  12.         InputStream is = sc.getResourceAsStream("/1.html");  
  13.         System.out.println(is);       
  14.     }  

輸出結果:F:\apache-tomcat-7.0.29\webapps\day06\1.html

要求必須以'/'開頭
(4)web的相對路徑

    1、abc:與當前頁面同級的目錄或servlet的名稱
     * <a href="c/c.html">c.html</a><br>
    2、/abc:相對於web站點,%tomcat%/webapps/
     * <a href="/day06_web/b/c/c.html">c.html</a><br>
    3、./abc:當前目錄,與第一種情況相同
     * <a href="./c/c.html">c.html</a><br>
    4、../abc:上一次目錄
     * <a href="../b/c/c.html">c.html</a><br>

 六、Servlet過濾器Filter

        所有的Servlet過濾器類都必須實現javax.servlet.Filter接口。這個接口含有3個過濾器類必須實現的方法:

            init( FilterConfig config);//Servlet容器創建Servlet過濾器實例後將調用這個方法。在這個方法中可以讀取web.xml件中Servlet過濾器的初始化參數

           doFilter( ServletRequest req, ServletResponse resp ,FilterChain chain);//FilterChain參數用於訪問後續過濾器

           destroy( );

         在web.xml中必須先配置過濾器再配置Servlet

[java] view plaincopy在CODE上查看代碼片派生到我的代碼片
  1. import java.io.IOException;  
  2. import java.io.PrintWriter;  
  3.   
  4. import javax.servlet.Filter;  
  5. import javax.servlet.FilterChain;  
  6. import javax.servlet.FilterConfig;  
  7. import javax.servlet.ServletException;  
  8. import javax.servlet.ServletRequest;  
  9. import javax.servlet.ServletResponse;  
  10. import javax.servlet.http.HttpServletRequest;  
  11.   
  12. public class MyFilter implements Filter {  
  13.     private FilterConfig config = null;  
  14.   
  15.     private String blackList = null;  
  16.   
  17.     public void init(FilterConfig config) throws ServletException {  
  18.         this.config = config;  
  19.         blackList = config.getInitParameter("blacklist");  
  20.     }  
  21.   
  22.     public void destroy() {  
  23.         config = null;  
  24.     }  
  25.   
  26.     public void doFilter(ServletRequest request, ServletResponse response,  
  27.             FilterChain chain) throws IOException, ServletException {  
  28.   
  29.         String username = ((HttpServletRequest) request)  
  30.                 .getParameter("username");  
  31.         if (username != null)  
  32.             username = new String(username.getBytes("ISO-8859-1"), "GB2312");  
  33.         if (username != null && username.indexOf(blackList) != -1) {  
  34.             response.setContentType("text/html;charset=GB2312");  
  35.             PrintWriter out = response.getWriter();  
  36.             out.println("<html><head></head><body>");  
  37.             out.println("<h1>對不起," + username + ",你沒有權限留言 </h1>");  
  38.             out.println("</body></html>");  
  39.             out.flush();  
  40.             return;  
  41.         }  
  42.   
  43.         long before = System.currentTimeMillis();  
  44.         config.getServletContext().log(  
  45.                 "NoteFilter:before call chain.doFilter()");  
  46.   
  47.         chain.doFilter(request, response);  
  48.   
  49.         config.getServletContext()  
  50.                 .log("NoteFilter:after call chain.doFilter()");  
  51.         long after = System.currentTimeMillis();  
  52.         String name = "";  
  53.         if (request instanceof HttpServletRequest) {  
  54.             name = ((HttpServletRequest) request).getRequestURI();  
  55.         }  
  56.         config.getServletContext().log(  
  57.                 "NoteFilter:" + name + ": " + (after - before) + "ms");  
  58.     }  
  59. }   
[html] view plaincopy在CODE上查看代碼片派生到我的代碼片
  1. <filter>  
  2.     <filter-name>myFilter</filter-name>  
  3.     <filter-class>com.test.filter.MyFilter</filter-class>  
  4.     <init-param>  
  5.         <param-name>blacklist</param-name>  
  6.         <param-value>hello</param-value>  
  7.     </init-param>  
  8. </filter>  
  9.   
  10. <filter-mapping>  
  11.     <filter-name>myFilter</filter-name>  
  12.     <url-pattern>/NoteServlet</url-pattern>  
  13. </filter-mapping>  


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章