1. 程式人生 > >Servlet知識詳解(一)ServletContext物件 和 ServletConfig物件學習筆記

Servlet知識詳解(一)ServletContext物件 和 ServletConfig物件學習筆記

學習小結 (一)Servlet的對映URL中使用*萬用字元的方法:兩種固定格式           b:另一種格式是以正斜槓(/)開頭並以/*結尾           備註:/####/*形式的優先順序要高於*.副檔名的優先順序 (二)Servlet例項物件的預裝載配置<load-on-startup>           <servlet>             <servlet-name>invoker</servlet-name>             <servlet-class>org.apache.catalina.servlets.invokerServlet</servlet-class>             <load-on-startup>2</load-on-startup>           </servlet> (三)ServletConfig物件-獲取Servlet的初始化引數          配置:           <servlet>             <servlet-name>ServletDemo4</servlet-name>             <servlet-class>cn.itcast.web.servlet.ServletDemo4</servlet-class>              <init-param>                 <param-name>charset</param-name>                 <param-value>UTF-8</param-value>              </init-param>              <servlet>            呼叫:            ServletConfig config = this.getServletConfig();            //獲取配置的初始化引數的方式1:獲取單個引數值           string value=config.getInitParameter("charset");           //獲取配置的初始化引數的方式2:獲取多個引數值           Enumeration e = config.getInitParameterNames();           while(e.hasMoreElements()){              String name=(String)e.nextElement();              String value=config.getInitParameter(name);              System.out.println(name+"="+value);           } (四)ServletContext  獲取WEB應用的初始化引數 配置: <web-app>    <context-param>      <param-name>username</param-name>      <param-value>root</param-value>    </context-param> </web-app> 呼叫:String uri = this.getServletContext().getInitParameter("url"); (五)獲取檔案的MIME型別的值 ---------------------------------------------------------------------?? String mimeType = this.getServletContext().getMimeType(filename); (六)利用ServletContext物件讀取src下面的配置檔案【注意:資源在src下面】 ServletContext context = this.getServletContext(); String realpath=context.getRealPath("/WEB-INF/classes/db.properties"); S
tring filename=realpath.substring(realpath.lastIndexOf("\\")+1); System.out.println("當前讀到的檔案時:"+filename); FileInputStream in = new FileInputStream(realpath); Properties prop = new Properties(); prop.load(in); String uri = prop.getProperty("url"); Strring username=prop.getProperty("username"); String password = prop.getProperty("password"); (七)在web工程的普通java程式中如何讀取資原始檔【資源在src下面】 ClassLoader loader = StudentDao.class.getClassLoader(); URL url = loader.getResource("cn/itcast/dao/db.properties");//此時仍然把資源裝載進記憶體中了。 String filepath=uri.getPath();//獲取其絕對路徑 FileInputSream in = new FileInputStream(filepath); Properties prop = new Properties();//map prop.load(in); String dbUri= prop.getProperty("url"); String username=prop.getProperty("username"); String password = prop.getProperty("password"); (
八) 獲取web.xml檔案中配置的web應用的顯示名稱 web.xml中配置:<display-name>day05</dispaly-name> 呼叫:String name=this.getServletContext().getServletContextName(); response.getWriter().write("<a href='/"+name+"/1.html'>點點</a>"); //開發階段的工程名稱可能與釋出階段的工程名稱不相同,這樣做就免於更改路徑中的工程名稱 ——————————————————————————————————————————————————————————— (一) Servlet 簡介             Servlet是sun公司提供的一門用於開發動態web資源的技術。Sun公司在其API中提供了一個servlet介面,使用者若想 開發一個動態的web資源(即開發一個java程式向瀏覽器輸出資料),需要完成以下2個步驟: a.編寫一個java類,實現servlet介面。 b.把開發好的java類部署到web伺服器中。 提示:按照一種約定俗成的稱呼習慣,通常我們也把實現了servlet介面的java程式,稱之為Servlet (二) Servlet的執行過程(生命週期) Servlet程式由Web伺服器呼叫,Web伺服器收到客戶端的Servlet訪問請求後: (1)Web伺服器首先檢查時候已經裝載並建立了Servlet的例項物件。如果是,則直接執行第(4)步,否則,執行第(2)步。 (2)裝載並建立該Servlet的一個勢力物件。 (3)呼叫Servlet例項物件的init()方法。 (4)建立一個用於封裝HTTP請求訊息的HttpServletRequest物件和一個代表HTTP響應訊息的HttpServletResponse物件,然後 呼叫Servlet的service()方法並將請求和響應物件作為引數傳遞進去。 (5)web應用程式被停止或重新啟動之前,Servlet引擎將解除安裝Servlet,並在解除安裝之前呼叫Servlet的destroy()方法。 Servlet物件的解除安裝:從第一次請求訪問Servlet開始,Servlet物件被建立後,記憶體中將只存在這一個Servlet物件對後續所有的請求訪問提供服務,該Servlet物件都將一直存在下去,知道Web應用被移除或者伺服器停止才被解除安裝,並且解除安裝前還將呼叫destroy()方法。 (四) Servlet介面的實現類 SUN公司為Servlet介面定義了兩個預設實現類,分別是GenericServlet、 HttpServlet。 HttpServlet指能夠處理HTTP請求的servlet,他在原有Servlet介面上添加了一些有關HTTP協議的處理方法,它比Servlet介面的功能更為強大。因此開發人員在編寫Servlet時,通常應繼承這個類,而避免直接去實現Servlet介面。 (五)Servlet的一些細節 1:Servlet程式的URL對映的基本語法 由於客戶端是通過URL地址訪問web伺服器中的資源,所以Servlet程式若想被外界訪問,必須把servlet程式對映到一個URL地址上,這個工作再web.xml檔案中使用<servlet>元素和<servlet-mapping>元素完成。 a <servlet>元素用於註冊Servlet,他包含有兩個主要的子元素:<servlet-name>和<servlet-class>,分別用於設定Servlet的註冊名稱和servlet的完整類名 b  一個<servlet-mapping>元素用於對映一個已註冊的Servlet的一個對外路徑,它包含兩個子元素: <servlet-name>和<url-pattern>,分別用於指定Servlet的註冊名稱和Servlet的對外訪問路徑。 c 同一個Servlet可以對映到多個URL上,即多個<servlet-mapping>元素的<servlet-name>子元素的設定值可以是同一個Servlet的註冊名 Demo樣例: <web-app>      <servlet>           <servlet-name>AnyName</servlet-name>           <servlet-class>HelloServlet</servlet-class>      </servlet>      <servlet-mapping>           <servlet-name>AnyName</servlet-name>           <url-pattern>/demo/hello.html</url-pattern>      </servlet-mapping>      <servlet-mapping>           <servlet-name>AnyName</servlet-name>           <url-pattern>/login/login.html</url-pattern>      </servlet-mapping>      </web-app> 2:Servlet的對映URL中使用*萬用字元的方法 在Servlet對映到的URL中也可以使用*萬用字元,但是隻能有兩種固定的格式: a 一種格式是 *.副檔名                        *.do b 另一種格式是以反斜槓/開頭並以/*結尾                       /action/* 對於如下的一些對映關係: Servlet1對映到/abc/* Servlet2對映到/* Servlet3對映到 /abc Servlet4 對映到*.do 問題: @ 1 當請求URL為/abc/a.html,/abc/*和/*都匹配,那個Servlet響應        答:Servlet引擎將呼叫Servlet1 @ 2 當請求Url為/abc, /abc/*和、abc都匹配,那個servlet響應        答:Servlet引擎將呼叫Servlet3
@ 3  當請求URL為/abc/a.do,/abc/*和*.do都匹配,那個servlet響應         答:servlet引擎將呼叫Servlet1 @ 4  當請求URL為/a.do,/*和*.do都匹配,哪個servlet響應         答:servlet引擎將呼叫Servlet2 @ 5  當請求URL為/xxx/yyy/a.do,/*和*.do都匹配,哪個servlet響應         Servlet引擎將呼叫Servlet2【即:/*的優先順序高於 *.do】 3 Servlet例項物件的生命週期細節     Sevlet是一個供其他java程式(Servlet引擎如Tomcat伺服器程式)呼叫的Java類,它不能獨立執行,它的執行完全由Servlet引擎來控制盒排程。     針對客戶端的多次Servlet請求,通常情況下,伺服器只會建立一個Servlet例項物件,也就是說Servlet例項物件一旦建立,它就會駐留在記憶體中,為後續的其他請求服務,直至web容器退出,servlet例項物件才會銷燬。     在Servlet的整個生命週期內,Servlet的init方法只被呼叫一次。而對一個servlet的每次訪問請求都導致Servlet引擎呼叫一次一次servlet的service方法。對於每次訪問請求,Service引擎都會建立一個新的HttpServletRequest請求物件和一個新的HttpServletResponse響應物件,然後將這兩個物件作為引數傳遞給它呼叫的Servlet的service()方法,service方法再根據請求方式分別呼叫doXXX方法。
4:Servlet例項物件的預裝載配置<load-on-startup> 如果在<servlet>元素中配置了一個<load-on-startup>元素,那麼WEB應用程式在啟動時,就會裝載並建立Servlet的例項物件,以及呼叫Servlet例項物件的init()方法。 舉例: <servlet>      <servlet-name>invoker</servlet-name>      <servlet-class>org.apache.catalina.servlets.InvokerServlet</servlet-class>      <load-on-startup>2</load-on-startup> </servlet> 用途舉例:為web應用寫一個initServlet,這個servlet配置為啟動時裝載,為整個web應用建立必要的資料庫表和資料。 5:web應用程式的預設Servlet 在<tomcat的安裝目錄>/conf/web.xml檔案中,註冊了一個名稱為org.apache.catalina.servlets.DefaultServlet的Servlet,並將這個Servlet設定為了預設Servlet 凡是在web.xml中找不到匹配的<servlet-mapping>元素的URL,他們的訪問請求都將交給預設Servlet處理,也就是說,預設Servlet用於處理所有其他Servlet都不處理的訪問請求。 例如:當訪問Tomcat伺服器伺服器中的某個靜態html檔案和圖片時,實際上是在訪問這個預設SErvlet.。 【備註:為避免遮蔽迷人的預設Servlet強大全面的功能,精良不要自定義預設servlet】 6:Servlet的執行緒安全問題 多執行緒安全的由來 當多個客戶端併發訪問同一個Servlet時,web伺服器會為每一個客戶端的訪問請求建立一個執行緒,並在這個執行緒上呼叫Servlet的service方法,因此service方法內如果訪問了同一個資源的話,就有可能引發執行緒安全問題。
SingleThreadMode介面 解決多執行緒安全問題 如果某個Servlet實現了SingleThreadMode介面,那麼Servlet引擎將以單執行緒模式來呼叫其service方法。 SingleThreadMode介面中沒有定義任何方法,只要在Servlet類的定義中增加實現SingleThreadMode介面的宣告即可。對於實現了SingleThreadMode介面的Servlet,Servlet引擎仍然支援對該Servlet的多執行緒併發訪問,其採用的方式是產生多個Servlet例項物件,併發的每個執行緒分別呼叫一個獨立的Servlet例項物件。 實現SingleThreadMode介面並不能真正解決Servlet的執行緒安全問題,因為Servlet引擎會建立多個Servlet例項物件,而真正意義上解決多執行緒安全問題是指一個SerVlet例項物件被多個執行緒同時呼叫的問題。事實上,在Servlet API 2.4中,已經將SingleThreadMode標記為Deprecated(過時的). 【備註1:多執行緒併發操作共享資料,就會發生執行緒安全問題。Synchronized程式碼塊可以很好的解決執行緒安全問題,但是會造成伺服器響應效能變得極差,很難提供大量的併發訪問服務,所以要慎用。共享資料包括如:成員變數,或是靜態成員變數等。】 【備註2:慎用靜態成員的增長問題,會同類位元組碼一同長期駐留在系統中,並將靜態變數中的資料長期駐留在記憶體中,最終會造成記憶體溢位。可在新增、使用之後,再找機會釋放掉。】 6:ServletConfig物件--獲取Servlet的初始化引數 在Servlet的配置檔案中,可以使用一個或多個<init-param>標籤為servlet配置一些初始化引數 當servlet配置了初始化引數後,web容器在建立servlet例項化物件時,會自動將這些初始化引數封裝到ServletConfig物件中,並在呼叫servlet的init方法時,將ServletConfig物件傳遞給servlet。進而,程式設計師通過ServletConfig物件就可以得到當前servlet的初始化引數資訊。 該物件的作用:a:獲得字符集編碼;b:獲得資料庫連線資訊;c:獲得配置檔案。 Demo範例: web.xml檔案的配置: <web-app>     <servlet>      <servlet-name>ServletDemo4</Servlet-name>      <init-param><!--servletConfig-->      <param-name>charset</param-name>      <param-value>UTF-8</param-value>      </init-param> <init-param> <param-name>xxx</param-name> <param-value>yyy</param-value> </init-param> </servlet></web-app> java原始檔中的編碼 //通過servletConfig獲取servlet配置的初始化引數 public class ServletDemo4 extends HttpServlet{ public void doGet(HttpServletRequest request,HttpServletResponse response) throws ServletException,IOException{ ServletConfig config = this.getServletConfig(); //該類為我們書寫了通過init()方法獲取ServletConfig物件的程式碼,我們只需要呼叫this.getSErvletConfig();即可 //獲取初始化引數的方式1:獲取單個引數值 //String
 value = config.getInitParameter("charset"); //獲取配置的初始化引數的方式2:獲取多個引數值 Enumeration e = config.getInitParameterNames(); while(e.hasMoreElements()){ String name =(String)e.nextElement(); String value=config.getInitParameter(name); System.out.println(name+"="+value); } } public vodi doPost(HttpServletRequest request ,HttpServletResponse reponse) throws ServletException,IOException{ doGEt(request,response); } } 7:ServletContext物件介紹 Web容器在啟動時,它會為每個web應用程式都建立一個對應的ServletContext物件,它代表當前web應用。 ServletConfig物件中維護了ServletContext物件的引用,開發人員在編寫servlet時,可以通過ServletConfig。getServletContext方法獲得ServletContext物件。 由於一個web應用中的所有Servlet共享同一個ServletContext物件,因此Servlet物件之間可以通過ServletContext物件來實現通訊。ServletContext物件也被稱之為context域物件。 8  ServletContext物件的應用 (1)多個Servlet通過ServletContext物件實現資料共享 Demo樣例: 第一部分: 1  在servlet中獲取servletContext 2  如何servletContext帶資料給其他web資源 public  class ServletDemo5 extends HttpServlet { public void doGet(HttpServletRequeste request,HttpServletResponse response) throws ServletException ,IOException{       ServletContext context = this.getServletConfig().getServletContext();        ServletContext context1 = this.getServletContext();        //servlet5帶資料給servlet6(用context物件實現資料共享)         context.setAttribute("data","aaaaaaaaaaaaaaaaa"); } public void doPost (HttpServletRequest request,HttpServletResponse response) throws ServletException,IOEception{ doGet(request,response); } }
第二部分 //配合servlet5,通過servletContext獲取5帶過來的資料 public class ServletDemo6 extends HttpServlet{        public void doGet(HttpServletRequest request,HttpServletResponse response) throws ServletException,IOException{       ServletContext context = this.getServletContext();      System.out.println(context.getAttribute("data")); } public void doPost(HttpServletRequest request,HttpServletResponse response) throws ServletException,IOException{ doGet(request,response); } } (2)獲取WEB應用的初始化引數 Demo樣例: 第一部分: <web-app> <context-param> <param-name>url</param-name> <param-value>jdbc:mysql://localhost:3306/test</param-value> </context-param> <context-param> <param-name>username</param-name> <param-value>root</param-value> </context-param> <context-param> <param-name>password</param-name> <param-value>root</param-value> </context-param>L </web-app> 第二部分: 通過servletContext獲取web應用配置的初始化引數 public class ServletDemo7 extends HttpServlet{   public void doGet(HttpServletRequest,HttpServletResponse response) throws ServletException ,IOException{  //Stringvalue=this.ServletContext().getInitParameter("xxx"); String url = this.getServletContext().getInitParameter("url"); String username=this.getServletContext().getInitParameter("username'); String password = this.getServletContext().getInitParameter("password"); System.out.println(url); System.out.println(username); } public void doPost(HttpServletRequest request,HttpServletResponse response) throws ServletException,IOException{ doGet(request,response); } } 獲取檔案MIME型別的值 Demo樣例 通過servletContext獲取檔案的mime型別 public class ServletDemo8 extends HttpServlet{ public void doGet(HttpServletRequest request ,HttpServletResponse response) throws ServletException,IOException{ String filename="1.jpg"; ServletContext context = this.getServletContext(); System.out.println(context.getMimeType(filename)); response.setHeader("content-type","image/jpeg"); } public void doPost(HttpServletResponse repuest,HttpServletResponse response) throws ServletException ,IOException{ doGet(request,response); } } (4) 實現Servlet請求的轉發 Demo樣例: //servletDemo9收到請求後,轉發給servletDemo1處理(mvc設計模式) public class ServletDemo9 extends HttpServlet{ public void doGet(HttpServletRequest request ,HttpServletResponse response) throws ServletException ,IOException{ String data ="aaaaaa"; this.getServletContext().setAttribute("data",data); RequestDispatcher rd = this.getServletContext().getRequestDispatcher("/view.jsp"); rd.forward(request,response); //RequesteDispatcher rd= this.getServletContext().getRequestDispatcher("/servlet/ServletDemo10"); // rd.forward(request,response); } public void doPost(HttpServletRequest request,HttpServletResponse response) throws ServletException,IOException{ doGet(request,response); } } 【備註:轉發servlet的路徑,是該servlet的對映路徑,而非其類名稱。所以若是更改了類名稱,則需要更改該servlet的web。xml檔案中註冊及對映程式碼】 9:利用ServletContext物件讀取資原始檔       通過ServletContext物件 實現讀取資原始檔的三種方式: demo樣例 //用servetContext讀取web工程不同位置的資原始檔 .properties檔案(屬性檔案) public class ServletDemo11 extends HttpServelt{ public void doGet(HttpServletRequest request,HttpServletResponse response) throws ServletException,IOException{ //test5(); }      //讀取配置檔案的第一種方式【注意:資源在WebRoot下面】 private void test1() throws IOException{ ServletContext context =this.getServletContext(); InputStream in = context.getResourceAsStream("db/properties"); Properties prop = new Properties();//map prop.load(in); String url=prop.getPropery("url"); System.out.println(url); } //讀取配置檔案的第二種方式【注意:資源在webroot下面】 private void test2()throws IOException{ ServletContext context = this.getServletContext(); String realpath=context.getRealPath("/db.properties"); //獲取到操作檔名 realpath=xxx.properties String filename = realpath.substring(realpath.lastIndexOf("\\")+1); System.out.println("當前讀到的檔案是:"+filename); FileInputSream in = new FileInputStream(realpath); Properties prop = new Properties(); prop.load(in); String url=pro.getProperty("ur"); } //讀取配置檔案的第三種方式【注意:資源在webRoot下面】 private  void test3() throws IOException{ ServletContext context = this.getServletContext(); URL url = context.getResource("/resource/db.properties"); inputStream in = url.openStream(); Properties prop = new Properties(); prop.load(in); String url = prop.getProperty("url"); } //【注意:資源在src下面】 //讀取src下面的配置檔案(傳統方式不可取)。注:相對路徑是相對於java虛擬機器的相對位置,而在傳統方法中我們設定//classpath來設定與java虛擬機器讀取程式的路徑。而在javaweb中則不可行,但一切都可受到serviceContext的管理。 private void test4()throws IOException{ FileInputStream in = new FileInputStream("classes/db.properties")://此種方式不可行 } //讀取src下面的配置檔案【注意:資源在src下面】 private void test5() throws IOException{      InputStream in = this.getServletContext().getResourceAsStream("/WEB-INF/classes/db.properties");      Properties prop = new Properties();//map       prop.load(in);      String url = prop.getProperty("url"); } public void doPost(HttpServletRequest request,HttpServletResponse response) throws ServletException,IOException{ doGet(request,response); } } 10  在web工程的普通java程式中如何讀取資原始檔 Demo樣例 public class StudenDao {//servlet public String get()throws IOException{//類裝載器讀 test1(); test2(); return null; } public void test2() throws IOException { ClassLoader loader StudentDao.class.getClassLoader(); Url url = loader.getResource("cn/itcat/dao.db.properties");//此時仍然把資源轉載進記憶體了。、 String filepath =url.getPath();//獲取其絕對路徑 FileInputStream in = new FileInputStream(filepath); Properties prop = new Properties();//map prop.load(in); String url = prop.getproperty("url"); }

 //以下程式碼在讀檔案時,讀到不到更新後的資原始檔

          public void test1() throws IOException{

                ClassLoader loader = StudentDao.class.getClassLoader();

                InputStream in = loader.getResourceAsStream("cn/itcast/dao/db.properties");

                Properties prop = new Properties();  //map

                prop.load(in);

                String url = prop.getProperty("url");

                String username = prop.getProperty("username");

                String password = prop.getProperty("password");

                System.out.println(url);

                System.out.println(username);

                System.out.println(password);         

          }     

      //通過類裝載器讀檔案時,需要注意的問題

      //備註:當資原始檔很大時,採用類裝載器裝載時,可能會造成記憶體溢位。

    }

【重點知識:Web工程中,使用“類裝載器”讀取相對路徑的資源。相對路徑是相對於類路徑classes資料夾/src路徑下。】

src類路徑下:  servlet時:使用ServletContext物件獲取器絕對路徑,

             非servlet時:使用類裝載器使用其相對路徑(相對於src)

WebRoot下: servlet時:使用ServletContext物件獲取器絕對路徑進行讀取。

            非servlet時:無法讀取。

11、獲取web.xml檔案中配置的web應用的顯示名稱  

    Demo樣例: 

    //獲取web.xml檔案中配置的web應用的顯示名稱  

    ​web.xml中配置:<display-name>day05</display-name>

    public class ServletDemo13 extends HttpServlet {     

          public void doGet(HttpServletRequest request, HttpServletResponse response)

              throws ServletException, IOException {     

                String name = this.getServletContext().getServletContextName();     

                response.getWriter().write("<a href='/"+name+"/1.html'>點點</a>");

          }    //開發階段的工程名稱可能與釋出階段的工程名稱不相同,這樣做就免於更改路徑中的工程名稱。

          public void doPost(HttpServletRequest request, HttpServletResponse response)

              throws ServletException, IOException {

                doGet(request, response);

          }     

    }

}