JSP/Servlet基礎語法

相關學習資料

http://my.oschina.net/chape/blog/170247
http://docs.oracle.com/cd/E13222_01/wls/docs81/webapp/web_xml.html
http://blog.csdn.net/liaoxiaohua1981/article/details/6761053
http://computer.c.blog.163.com/blog/static/102524482012314537670/
http://www.blogjava.net/w2gavin/articles/358641.html
http://www.douban.com/note/310522851/
http://mianhuaman.iteye.com/blog/1105522
http://blog.csdn.net/li_jinjian2005/article/details/2915462
http://210.44.193.6/JSP/07.htm
http://www.ibm.com/developerworks/cn/java/j-lo-servlet30/

目錄

1. J2EE WEB應用文件目錄結構
2. web.xml基礎語法
3. JSP基礎語法
4. Servlet基礎語法

1. J2EE WEB應用文件目錄結構 

Java Web應用由一組靜態HTML頁、Servlet、JSP和其他相關的class組成,它們一起構成一個大的工程項目。每種組件在Web應用中都有固定的存放目錄。Web應用的配置信息存放在web.xml文件中。在發佈某些組件(如Servlet)時,必須在web.xml文件中添加相應的配置信息 
Java Web應用程序必須使用規範的目錄結構

1. 應用程序根目錄,可以取任意的名字,所有的HTML、JSP文件都放在這個目錄下
  1.1 WEB-INF目錄: 必須目錄 
    1.1.1 web.xml: Web應用部署描述文件,必須文件
    1.1.2 classes目錄: 
      1) 用於存放單個*.classes字節碼文件,Servlet類文件也存放在這個目錄下
    1.1.3 lib目錄: 
      1) 存放第三方類庫文件,即打包後的JAR文件
    1.1.4 TLD文件: 標籤庫描述文件 
  1.2 其他靜態文件:
    1.2.1 HTML
    1.2.2 CSS
    1.2.3 JavaScript
    1.2.4 圖片等
  1.3 *.jsp: 存放任意多個JSP頁面

2. web.xml基礎語法

位於每個WEB應用的的WEB-INF路徑下的web.xml文件被稱爲配置描述符,這個web.xml文件對於Java Web應用十分重要,總體來說,web.xml主要負責以下內容:

1. JSP環境參數初始化
2. 配置和管理Servlet
3. 配置和管理Listener
4. 配置和管理Filter
5. 配置和管理JNDI
6. Session配置
7. MIME TYPE配置
8. 錯誤處理
9. 配置標籤庫
10. 配置JSP屬性
11. 配置和管理JAAS授權認證
12. 配置和管理資源引用
13. WEB應用默認首頁(welcome文件)的設置

下面我儘量列出了一個完整的web.xml的結構,我使用了/**/註釋符來說明某個項目的說明,要明白的是,在真實的web.xml中不允許使用/**/註釋符的,只是我覺得直接在web.xml中插入解釋說明能更好的說明問題

/*
<?xml version="1.0" encoding="GBK"?>是一個基本的XML文件的框架,不管是什麼配置文件,只要是基於XML的,它的基本結構都是這樣
*/
<?xml version="1.0" encoding="GBK"?>
/*
web.xml文件的根元素是<web-app.../>元素,整個web.xml只有這個根元素,每個web.xml必須以這個<web-app>根元素作爲開頭,在Servlet 3.0規範中,該元素新增了
metadata-complete屬性,當該屬性值爲true時,該web應用"不會"加載Annotation配置的WEB組件(如Servlet、Filter、Listener等),反之則加載
*/
<web-app xmlns="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">
  /*
  1. icon信息: 用來指定web站點中小圖標和大圖標的路徑
    1) small-icon: 大小爲16 X 16 pixel,但是圖象文件必須爲GIF或JPEG格式,擴展名必須爲:.gif或
.jpg.
    2) large-icon: 大小爲32 X 32 pixel,但是圖象文件必須爲GIF或JPEG的格式,擴展名必須爲; gif
或jpg. 
  */
  <small-icon>/路徑/smallicon.gif</small-icon>
  <large-icon>/路徑/largeicon-jpg</large-icon>

  /*
  2. 描述信息
  display-name: 定義站點的名稱
  description: 對站點的描述
  */
  <display-name>站點名稱</display-name>
  <description>站點描述</discription>

  /*
  3. distributable
  distributable元素爲空標籤,它的存在與否可以指定站臺是否可分佈式處理.如果web.xml中出現這個元素,則代表站臺在開發時已經被設計爲能在多個JSP Container之間分散執行
  */ 
  <distributable/> 

  /*
  4. JSP環境參數: context-param
  context-param元素用來設定web站臺的環境參數(context),它包含兩個子元素:
    1) param-name: 參數名稱
    2) param-value: 值 
  此所設定的參數,在JSP網頁中可以使用下列方法來取得:
  ${initParam.param_name}
  若在Servlet可以使用下列方法來獲得:
  String param_name=getServletContext().getInitParamter("param_name");
  */ 
  <context-param>
     <param-name>param_name</param-name>
     <param-value>param_value</param-value>
  </context-param>

  /*
  5. filter過濾器、filter-mapping
  用於指定WEB容器的過濾器,在請求和響應對象在Servlet處理之前和之後,可以通過此過濾器對這兩個對象進行處理  
  filter-class 中指定的過濾器類須繼承 javax.servlet.Filter具有須有以下三種方法
  init(FilterConfig filterConfig):初始化;一般情況下時讀取配置文件中的init-param參數值 如 filterConfig.getInitParameter("encoding")
  doFilter(...):用於對request,response進行處理,並能過chain.doFilter(...) 交過下一個控制器
  destroy():資源銷燬
  filter-mapping則指示需要進行過濾器處理的URL訪問模式,可以理解爲當我們的URL匹配到指定的模式後,則對這個請求執行指定的"過濾處理流程"(可以把它理解爲一種路由機制)
  */
  <filter>
    <small-icon>/路徑/smallicon.gif</small-icon>
    <large-icon>/路徑/largeicon-jpg</large-icon>
    <filter-name>encodingfilter</filter-name>
    <display-name>站點名稱</display-name>
    <description>站點描述</discription>
    <filter-class>com.my.app.EncodingFilter</filter-class>
    <init-param>
      <param-name>encoding</param-name>
      <param-value>UTF-8</param-value>
    </init-param>
  </filter>
  <filter-mapping>
    <filter-name>encodingfilter</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>
  
  /*
  6. servlet、servlet-mapping
  和filter過濾器類似,servlet也是用來配置映射處理機制的
  和filter-mapping的作用類似,servlet-mapping用來定義servlet所對應URL.
  */
  <servlet>
    <small-icon>/路徑/smallicon.gif</small-icon>
    <large-icon>/路徑/largeicon-jpg</large-icon>
    <servlet-name>MyServletName</servlet-name>
    <display-name>站點名稱</display-name>
    <description>站點描述</discription>
    /*
    servlet-class、jsp-file有且只能出現一個
    */
    <servlet-class>com.Little.MyServlet</servlet-class>
    <jsp-file>/path/index.jsp</jsp-file> 
    <init-param>
      <param-name>name1</param-name>
      <param-value>value1</param-value>
    </init-param> 
    /*
    指定當Web應用啓動時,裝載Servlet的次序
    1) 當值爲正數或零時: 容器在應用啓動時就加載這個servlet,Servlet容器先加載數值小的servlet,再依次加載其他數值大的servlet
    2) 當值爲負或未定義: 容器在該servlet被選擇時才加載,即Servlet容器將在Web客戶首次訪問這個servlet時加載它
    */
    <load-on-startup></load-on-startup>
    /*
    設定運行時角色,可以使當前Servlet以一個特定的角色運行,有利於安全權限控制
    */
    <run-as>	
      <description>Security role for anonymous access</description>	
      <role-name>tomcat</role-name>	
    </run-as> 
    /*
    security-role-ref子元素提供出現在服務器專用口令文件中的安全角色名的一個別名。例如,假如編寫了一個調用 request.isUserInRole("boss")的servlet,
但後來該servlet被用在了一個其口令文件調用角色manager而不 是boss的服務器中。下面的程序段使該servlet能夠使用這兩個名稱中的任何一個
    */
    <security-role-ref>
      <role-name>boss</role-name> <!-- New alias -->
      <role-link>manager</role-link> <!-- Real name -->
    </security-role-ref>  
  </servlet>
  
  <servlet-mapping>
    <servlet-name>LoginChecker</servlet-name>
    <url-pattern>/LoginChecker</url-pattern>
    <servlet-name>MyServletName</<servlet-name>
  </servlet-mapping>

  /*
  7. security-role(虛擬安全用戶)
  給出安全角色的一個列表,這些角色將出現在servlet元素內的security-role-ref元素的role-name元素中。分別聲明角色可使高級IDE處理安全信息更爲容易。
  */
  <security-role>
    <description>安全賬戶描述</discription>
    <role-name>admin</role-name>
  </security-role>

  /*
  8. listener
  監聽器也叫Listener,是Servlet的監聽器,它可以監聽客戶端的請求、服務端的操作等。通過監聽器,可以自動激發一些操作,Servlet本身在一些特定的關鍵處理流程節點上增加Hook
回調機制,使得我們可以在這些節點位置配置監聽器
  常見的監聽器如下:
  Listener接口 
  1) ServletContextListener: ServletContextEvent
  2) ServletContextAttributeListener: ServletContextAttributeEvent
  3) HttpSessionListener: HttpSessionEvent
  4) HttpSessionActivationListener: HttpSessionAttributeListener
  5) HttpSessionBindingEvent: HttpSessionBindingListener
  6) ServletRequestListener: ServletRequestEvent
  7) ServletRequestAttributeListener: ServletRequestAttributeEvent 
  */
  <listener>
    <listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>
  </listener>

  /*
  9. session配置
  session-config包含一個子元素session-timeout.定義web站臺中的session參數,定義這個web站臺所有session的有效期限.單位爲分鐘
  */
  <session-config>
    <session-timeout>20</session-timeout>
  </session-config>

  /*
  10. mime-mapping
  mime-mapping包含兩個子元素extension和mime-type.定義某一個擴展名和某一MIME Type做對映,和apache中的文件擴展處理器原理類似,對指定的擴展名指定相應的處理程序
  */
  <mime-mapping>
    <extension>doc</extension>
    <mime-type>application/vnd.ms-word</mime-type>
  </mime-mapping> 
  <mime-mapping>
    <extension>xls</extension>
    <mime-type>application/vnd.ms-excel</mime-type>
  </mime-mapping>

  /*
  11. welcome-file-list
  welcome-file-list包含一個子元素welcome-file.用來定義首頁列單,即當客戶端的請求沒有指定具體的頁面時,服務區器默認指定的首頁腳本
  */
  <welcome-file-list>
    <welcome-file>index.jsp</welcome-file>
    <welcome-file>index.htm</welcome-file>
  </welcome-file-list>

  /*
  12. error-page
  錯誤處理機制,error-page元素包含三個子元素error-code,exception-type和location.將錯誤代碼(Error Code)或異常(Exception)的種類對應到web站點資源路徑。
簡單來說就是返回特定HTTP狀態代碼或者特定類型的異常被拋出時,制定響應將要顯示的頁面。
  */
  <error-page>
    <error-code>404</error-code>
    <exception-type>java.lang.Exception</exception-type>
    <location>/error404.jsp</location>
  </error-page>
  <error-page>
    <exception-type>java.lang.Exception</exception-type>
    <exception-type>java.lang.NullException</exception-type>
    <location>/except.jsp</location>
  </error-page>

  /*
  13. jsp-config
  JSP相關配置 
  */
  <jsp-config>
    <taglib>
      /*
      taglib-uri定義TLD文件的URI,JSP網頁的taglib指令可以經由這個URI存取到TLD文件
      */
      <taglib-uri>Taglib</taglib-uri>
      /*
      taglib-location定義TLD文件對應Web站臺的存放位置
      */
      <taglib-location>/WEB-INF/tlds/MyTaglib.tld</taglib-location>
    </taglib>
    <jsp-property-group>
      <description>
        Special property group for JSP Configuration JSP example.
      </description>
      <display-name>JSPConfiguration</display-name>
      /*
      設定值所影響的範圍,如:/CH2 或者/*.jsp
      */
      <uri-pattern>/*</uri-pattern> 
      /*
      若爲true,表示不支持EL語法
      */
      <el-ignored>true</el-ignored>
      /*
      設定JSP網頁的編碼
      */
      <page-encoding>GB2312</page-encoding>
      /*
      若爲true表示不支持<%scription%>語法.
      */
      <scripting-inivalid>true</scripting-inivalid> 
      /*
      設置JSP網頁的結尾,擴展名爲.jspf
      */
      <include-coda>.jspf</include-coda>
      /*
      設置JSP網頁的擡頭,擴展名爲.jspf
      */
      <include-prelude>.jspf</include-prelude>
    </jsp-property-group>
  </jsp-config>

  /*
  14. resource-ref、resource-env-ref
  resource-ref聲明資源工廠使用的外部資源
  resource-env-ref聲明與資源相關的管理對象
  */
  <resource-ref>
    <description>JNDI JDBC DataSource of JSPBook</description> <!-- 資源說明 -->
    <res-ref-name>jdbc/sample_db</res-ref-name> <!-- 資源名稱 -->
    <res-type>javax.sql.DataSoruce</res-type> <!-- 資源種類 -->
    <res-auth>Container</res-auth> <!-- 資源由Application或Container來許可 -->
    <res-sharing-scope>Shareable|Unshareable</res-sharing-scope> <!-- 資源是否可以共享.默認值爲 Shareable -->
  </resource-ref>

  <resource-env-ref>	
    <resource-env-ref-name>jms/StockQueue</resource-env-ref-name>	
  </resource-env-ref>	

  /*
  15. EJB配置 
  ejb-ref用於聲明一個EJB的主目錄的引用
  用於聲明一個EJB的本地主目錄的應用。
  */
  <ejb-ref>	
    <description>Example EJB reference</decription>	
    <ejb-ref-name>ejb/Account</ejb-ref-name>	
    <ejb-ref-type>Entity</ejb-ref-type>	
    <home>com.mycompany.mypackage.AccountHome</home>	
    <remote>com.mycompany.mypackage.Account</remote>	
  </ejb-ref>	

  <ejb-local-ref>	
    <description>Example Loacal EJB reference</decription>	
    <ejb-ref-name>ejb/ProcessOrder</ejb-ref-name>	
    <ejb-ref-type>Session</ejb-ref-type>	
    <local-home>com.mycompany.mypackage.ProcessOrderHome</local-home>	
    <local>com.mycompany.mypackage.ProcessOrder</local>	
  </ejb-local-ref>	

  /*
  16. WEB應用環境參數配置
  */
  <env-entry>  
    <description>環境參數說明</description>
    <env-entry-name>minExemptions</env-entry-name>	
    <env-entry-value>1</env-entry-value>	
    <env-entry-type>java.lang.Integer</env-entry-type>	
  </env-entry> 
  
  /*
  17. 安全配置、資源限制訪問配置
  在Web應用程序的web.xml中創建security-constraint、login-config和security-role元素
  */
  /*
  配置對指定資源、指定角色的訪問權限
  */
  <security-constraint>
    <web-resource-collection>
      <web-resource-name>HelloServlet</web-resource-name>
      <url-pattern>/HelloServlet</url-pattern>
      <http-method>GET</http-method>
      <http-method>POST</http-method>
    </web-resource-collection>
    <auth-constraint>
      <description>This applies only to the "tomcat" security role</description>
      <role-name>admin</role-name>
    </auth-constraint>
    <user-data-constraint>
      <transport-guarantee>NONE</transport-guarantee>
    </user-data-constraint>
  </security-constraint>
    
  /*
  auth-method的方法有:
    1) BASIC
    BASIC是一種常見的Web認證方式,瀏覽器給用戶提示一個對話框,要求輸入用戶名和密碼,隨後Tomcat將給出的用戶名和密碼與tomcat-users.xml中的用戶名和密碼進行比較,
然後使用前面的security-constraint配置來確定用戶是否可訪問受保護的servlet
    2) FORM
    3) CLIENT-CERT
    4) DIGEST
  */
  <login-config>
    <realm-name>在HTTP驗證返回包中的顯示名稱</<realm-name>
    <auth-method>BASIC</auth-method>
    <form-login-config>如果auth-method採用FORM,則這裏填寫form-login-config名稱</form-login-config> 

  </login-config>
  /*
  關於security-role,在前面的servlet已經說明過,這裏要強調一下:
  web.xml中的HTTP認證方法實際上有兩個步驟:
    1) 檢查提供的用戶名和密碼是否正確。
    2) 判斷用戶是否映射到特定的安全角色。例如,用戶可能提供了正確的用戶名和密碼,但沒有映射到特定的安全角色,也將被禁止訪問特定的Web資源。
  */
  <security-role>
    <role-name>admin</role-name>
  </security-role>  
</web-app>

以上就是web.xml的完整結構,需要注意的是,web.xml中有一些環境參數的加載配置,它們之間存在優先級的關係,我們在編寫配置的時候需要注意這一點

web.xml 的加載順序是:context-param -> listener -> filter -> servlet ,而相同類型節點之間的程序調用的順序是根據對應的mapping的順序進行調用的

3. JSP基礎語法

JSP的本質是Servlet,當用戶向指定Servlet發送請求時,Servlet利用輸出流動態生成HTML頁面,包括每一個靜態的HTML標籤和所有在HTML頁面中出現的內容 
JSP頁面由如下兩部分組成

1. 靜態部分: 標準的HTML標籤、靜態的頁面內容,也就是普通的HTML代碼
2. 動態部分: 受java程序控制的內容,這些內容由Java程序來動態生成

/*
1. JSP的編譯指令 
*/
<%@ page contentType="text/html; charset=GBK" language="java" errorPage="" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
  <title>learn j2ee</title> 
  /*
  2. JSP註釋 
  */ 
</head> 
/*
3. JSP聲明 
*/
<body> 
/*
4. JSP表達式
*/
/*
5. JSP腳本
*/ 
/*
6. JSP的動作指令
*/ 
/*
7. JSP腳本中的內置對象
*/
</body>
</html>

0x1: JSP的編譯指令

JSP的編譯指令是通過JSP引擎的消息,它不直接生成輸出。編譯指令都有默認值,我們並不需要爲每個指令設置值。它的格式如下
<%@ 編譯指令名 屬性名="屬性值"...%>(不同屬性名之間用空格分開)
  1) page: Page指令爲容器提供當前頁面的使用說明。一個JSP頁面可以包含多個page指令
    1.1) buffer: 指定緩衝區的大小。緩衝區是JSP內部對象"out",它用於緩存JSP頁面對客戶端瀏覽器的輸出,默認值爲8KB,可以設置爲none,也可以設置爲其他的值,單位爲Kb
    1.2) autoFlush: 當緩衝區即將滿而溢出時,是否需要強制輸出緩衝區的內容:
      1.2.1) 如果設置爲true則正常輸出
      1.2.2) 如果設置爲false,則會在buffer溢出時產生一個異常
    1.3) contentType: 用於設定生成網頁的文件格式(MIME類型)、和編碼字符集(頁面字符集類型)(text/html;charSet=ISO-8859-1)
      1.3.1) 默認的MIME類型是text/html
      1.3.2) 默認的字符集類型爲ISO-8859-1
    1.4) errorPage: 指定錯誤處理頁面,如果本頁面產生了異常或錯誤,而該JSP頁面沒有對應的錯誤處理代碼(沒有用try、catch機制捕捉異常),則會自動調用該屬性所指定的JSP
頁面。值得注意的是,爲頁面指定錯誤發生時的錯誤提示頁面是一種安全的做法,能夠在一定程度上組織error-based-sql-injection的攻擊
    1.5) isErrorPage: 指定當前頁面是否可以作爲另一個JSP頁面的錯誤處理頁面
    1.6) extends: JSP程序編譯時所產生的Java類,需要繼承的父類,或者需要實現的接口的全限定類名(即包含包名在內的完整路徑)
    1.7) import: 用來導入包。默認自動導入的包(參數之間用逗號分隔)(java.lang.*,javax.servlet.*)
      1.7.1) java.lang.*
      1.7.2) javax.servlet.*
      1.7.3) javax.servlet.jsp.*
      1.7.4) javax.servlet.http.*
    1.8) info: 定義JSP頁面的描述信息
    1.9) isThreadSafe: 指定對JSP頁面的訪問是否爲線程安全
    1.10) language: 定義JSP頁面所用的腳本語言,默認是Java
    1.11) session: 指定JSP頁面是否使用session
    1.12) isELIgnored: 指定是否執行EL表達式
    1.13) isScriptingEnabled: 確定腳本元素能否被使用
  2) include: 用於指定包含另一個頁面
  <%@include file="file.jsp"%>
  可以將外部文件嵌入到當前JSP文件中,同時解析這個頁面中的JSP語句(如果有的話),也就是說,它既可以包含靜態的文本,也可以包含動態的JSP頁面。包含頁面在編譯時將完全包含了被包
含頁面的代碼,融合成一個頁面。作用和PHP中的inlcude、require類似。
  需要注意的是,要指出的是,靜態包含還會將被包含頁面的編譯指令也包含進來,如果兩個頁面的編譯指令衝突,那麼頁面就會出錯(即被包含的頁面中不能重複定義
page、include、taglib)
  3) taglib: 用於定義和訪問自定義標籤
  自定義標籤庫是一種非常優秀的表現層組件技術。通過使用自定義標籤庫,可以在簡單的標籤中封裝複雜的功能,在JSP2中使用自定義標籤需要以下步驟
    1) 開發自定義標籤處理類
    在JSP頁面使用一個標籤時,底層實際上由標籤處理類提供支持,從而可以通過簡單的標籤來封裝複雜的功能,從而使團隊更好地協作開發。自定義標籤類應該繼承一個父類: 
javax.servlet.jsp.tagext.SimpleTagSupport,除此之外,JSP自定義標籤類還有如下要求(通過接口來強制性保證):
      1) 如果標籤包含屬性,每個屬性都有對應的getter、setter方法
      2) 重寫doTag()方法,這個方法負責生成頁面內容
    example1: 無屬性、無標籤體的最簡單的標籤處理類
    package lee;
    import javax.servlet.jsp.tagext.*;
    import javax.servlet.jsp.*;
    import java.io.*;

    public class HelloWorldTag extends SimpleTagSupport
    {
      //重寫doTag方法,該方法在標籤結束生成頁面內容
      public void doTag()throws JspException, IOException
      {
        //獲取頁面輸出流,並輸出字符串
        getJspContext().getOut().write("Hello World " + new java.util.Date());
      }
    }
    這個標籤處理類繼承了SimpleTagSupport父類,並重寫了doTag()方法,doTag()負責輸出頁面內容(即標籤代表的內容)

    example2: 帶屬性的標籤處理類
    package lee;
    import javax.servlet.jsp.tagext.*;
    import javax.servlet.jsp.*;
    import java.io.*;
    import java.sql.*;

    public class QueryTag extends SimpleTagSupport
    {
      //標籤的屬性
      private String driver;
      private String url;
      private String user;
      private String pass;
      private String sql;

      //driver屬性的setter和getter方法
      public void setDriver(String driver)
      {
        this.driver = driver;
      }
      public String getDriver()
      {
        return this.driver;
      }
      
      //url屬性的setter和getter方法
      public void setUrl(String url)
      {
        this.url = url;
      }
      public String getUrl()
      {
        return this.url;
      }
      
      //user屬性的setter和getter方法
      public void setUser(String user)
      {
        this.user = user;
      }
      public String getUser()
      {
        return this.user;
      }
      
      //pass屬性的setter和getter方法
      public void setPass(String pass)
      {
        this.pass = pass;
      }
      public String getPass()
      {
        return this.pass;
      }	
      
      //sql屬性的setter和getter方法
      public void setSql(String sql)
      {
        this.sql = sql;
      }
      public String getSql()
      {
        return this.sql;
      }	
      
      //conn屬性的setter和getter方法
      public void setConn(Connection conn)
      {
        this.conn = conn;
      }
      public Connection getConn()
      {
        return this.conn;
      }
      
      //stmt屬性的setter和getter方法
      public void setStmt(Statement stmt)
      {
        this.stmt = stmt;
      }
      public Statement getStmt()
      {
        return this.stmt;
      }	
      
      //rs屬性的setter和getter方法
      public void setRs(ResultSet rs)
      {
        this.rs = rs;
      }
      public ResultSet getRs()
      {
        return this.rs;
      }
      
      //rsmd屬性的setter和getter方法
      public void setRsmd(ResultSetMetaData rsmd)
      {
        this.rsmd = rsmd;
      }
      public ResultSetMetaData getRsmd()
      {
        return this.rsmd;
      }
      //執行數據庫訪問的對象 
      private Connection conn = null;
      private Statement stmt = null;
      private ResultSet rs = null;
      private ResultSetMetaData rsmd = null;
      public void doTag()throws JspException,
        IOException
      {
        try
        {
          //註冊驅動
          Class.forName(driver);
          //獲取數據庫連接
          conn = DriverManager.getConnection(url,user,pass);
          //創建Statement對象
          stmt = conn.createStatement();
          //執行查詢
          rs = stmt.executeQuery(sql);
          rsmd = rs.getMetaData();
          //獲取列數目
          int columnCount = rsmd.getColumnCount();
          //獲取頁面輸出流
          Writer out = getJspContext().getOut();
          //在頁面輸出表格
          out.write("<table border='1' bgColor='#9999cc' width='400'>");
          //遍歷結果集
          while (rs.next())
          {
            out.write("<tr>");
            //逐列輸出查詢到的數據
            for (int i = 1 ; i <= columnCount ; i++ )
            {
              out.write("<td>");
              out.write(rs.getString(i));
              out.write("</td>");
            }
            out.write("</tr>");
          }
        }
        catch(ClassNotFoundException cnfe)
        {
          cnfe.printStackTrace();
          throw new JspException("自定義標籤錯誤" + cnfe.getMessage());
        }
        catch (SQLException ex)
        {
          ex.printStackTrace();
          throw new JspException("自定義標籤錯誤" + ex.getMessage());
        }
        finally
        {
          //關閉結果集
          try
          {
            if (rs != null)
              rs.close();
            if (stmt != null)
              stmt.close();
            if (conn != null)
              conn.close();
          }
          catch (SQLException sqle)
          {
            sqle.printStackTrace();
          }
        }
      }
    }

    example3: 帶標籤體的標籤處理類
    帶標籤體的標籤可以在標籤內嵌入其他內容(包括靜態HTML、動態JSP內容),通常用於完成一些邏輯運算
    package lee;
    import javax.servlet.jsp.tagext.*;
    import javax.servlet.jsp.*;
    import java.io.*;
    import java.sql.*;
    import java.util.*;

    public class IteratorTag extends SimpleTagSupport
    {
      //標籤屬性,用於指定需要被迭代的集合
      private String collection;
      //標籤屬性,指定迭代集合元素,爲集合元素指定的名稱
      private String item;
      
      //collection屬性的setter和getter方法
      public void setCollection(String collection)
      {
        this.collection = collection;
      }
      public String getCollection()
      {
        return this.collection;
      }
      //item屬性的setter和getter方法
      public void setItem(String item)
      {
        this.item = item;
      }
      public String getItem()
      {
        return this.item;
      }
      //標籤的處理方法,簡單標籤處理類只需要重寫doTag方法
      public void doTag() throws JspException, IOException
      {
        //從page scope中獲取屬性名爲collection的集合
        Collection itemList = (Collection)getJspContext().getAttribute(collection);
        //遍歷集合
        for (Object s : itemList)
        {
          //將集合的元素設置到page 範圍
          getJspContext().setAttribute(item, s);
          //輸出標籤體
          getJspBody().invoke(null);
        }
      }
    }
  
    example4: 以"頁面片段"作爲屬性的標籤處理類
    package lee;
    import javax.servlet.jsp.tagext.*;
    import javax.servlet.jsp.*;
    import java.io.*; 

    public class FragmentTag extends SimpleTagSupport 
    {
      private JspFragment fragment;
      
      //fragment屬性的setter和getter方法
      public void setFragment(JspFragment fragment)
      {
        this.fragment = fragment;
      }
      public JspFragment getFragment()
      {
        return this.fragment;
      }
      @Override
      public void doTag() throws JspException, IOException
      {
        JspWriter out = getJspContext().getOut();
        out.println("<div style='padding:10px;border:1px solid black'>");
        out.println("<h3>下面是動態傳入的JSP片段</h3>");
        //調用、輸出“頁面片段”
        fragment.invoke( null );
        out.println("</div");
      }
    }
    上面的程序定義了JspFragment類型的fragment屬性,該屬性代表了使用該標籤時的"頁面片段"

    example5: 動態屬性的標籤處理類
    在某些特殊情況下,我們需要傳入自定義標籤的屬性個數是不確定的、屬性名也是不確定的,這就需要使用到動態屬性的標籤
    package lee;
    import javax.servlet.jsp.tagext.*;
    import javax.servlet.jsp.*;
    import java.io.*;
    import java.util.*;

    public class DynaAttributesTag extends SimpleTagSupport implements DynamicAttributes
    {
      //保存每個屬性名的集合
      private ArrayList<String> keys = new ArrayList<String>();
      //保存每個屬性值的集合
      private ArrayList<Object> values = new ArrayList<Object>();

      @Override
      public void doTag() throws JspException, IOException
      {
        JspWriter out = getJspContext().getOut();
        //此處只是簡單地輸出每個屬性
        out.println("<ol>");
        for( int i = 0; i < keys.size(); i++ )
        {
          String key = keys.get( i );
          Object value = values.get( i );
          out.println( "<li>" + key + " = " + value + "</li>" );
        }
        out.println("</ol>");
      }
      
      /*
      實現DynamicAttributes接口必須實現setDynamicAttribute,該方法用於爲該標籤處理類動態添加屬性名、屬性值
      */
      @Override
      public void setDynamicAttribute( String uri, String localName, Object value) throws JspException
      {
        //添加屬性名
        keys.add( localName );
        //添加屬性值
        values.add( value );
      }
    }


    2) 建立一個*.tld文件,每個*.tld文件對應一個標籤庫,每個標籤庫可包含多個標籤
    TLD(Tag Library Definition 標籤庫定義)的根元素是taglib,它可以包含多個tag子元素,每個tag元素都定義一個標籤
    taglib結構如下
      1) tlib-version: 指定該標籤庫實現的內部版本號
      2) short-name: 該標籤庫的默認短名
      3) uri: 指定該標籤庫的唯一標識URI,JSP頁面中使用標籤庫就是根據該URI屬性來定位標籤庫的
      4) tag: 每個tag元素定義一個標籤
        4.1) name: 該標籤的名字
        4.2) tag-class: 該標籤的處理類
        4.3) body-content: 指定標籤體內容
          4.3.1) tagdependent: 標籤處理類自己負責處理標籤體
          4.3.2) empty: 該標籤只能作爲空標籤使用
          4.3.3) scriptless: 該標籤可以是靜態HTML元素、表達式語言,但不允許JSP腳本
          4.3.4) JSP: 該標籤可以使用JSP腳本
          4.3.5) dynamic-attributes: 該標籤是否支持動態屬性
    JSP2規範的自定義標籤還允許直接將一段"頁面代碼"作爲屬性,這種方式給自定義標籤提供了更大的靈活性,它和普通標籤的區別並不大,對於以"頁面代碼"作爲屬性的自定義標籤來
說,需要注意的是:
      1) 標籤處理類中定義類型爲JspFragment的屬性,該屬性代表了"頁面片段"
      2) 使用標籤庫時,通過<jsp:attribute../>動作指令爲標籤庫屬性指定值
    除此之外,還可以動態屬性的標籤
    <?xml version="1.0" encoding="GBK"?>
    <taglib xmlns="http://java.sun.com/xml/ns/j2ee"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee web-jsptaglibrary_2_0.xsd"
      version="2.0">
      <tlib-version>1.0</tlib-version>
      <short-name>mytaglib</short-name>
      <!-- 定義該標籤庫的URI -->
      <uri>http://littlehann.cnblogs.com/mytaglib</uri>

      <!-- 定義第一個標籤 -->
      <tag>
        <!-- 定義標籤名 -->
        <name>helloWorld</name>
        <!-- 定義標籤處理類 -->
        <tag-class>lee.HelloWorldTag</tag-class>
        <!-- 定義標籤體爲空 -->
        <body-content>empty</body-content>
      </tag>

      /*
      定義第二個標籤,對於有屬性的標籤,需要爲<tag../>元素增加<attribute../>子元素,每個attribute子元素定義一個標籤元素。<attribute../>子元素通常還需要指定
如下子元素
        1) name: 屬性名,子元素的值是字符串內容
        2) required: 該屬性是否爲必須屬性,true or false
        3) fragment: 該屬性是否支持JSP腳本、表達式等動態內容,true or false
      */
      <tag>
        <!-- 定義標籤名 -->
        <name>query</name>
        <!-- 定義標籤處理類 -->
        <tag-class>lee.QueryTag</tag-class>
        <!-- 定義標籤體爲空 -->
        <body-content>empty</body-content>
        <!-- 配置標籤屬性:driver -->
        <attribute>
          <name>driver</name> 
          <required>true</required>
          <fragment>true</fragment>
        </attribute>
        <!-- 配置標籤屬性:url -->
        <attribute>
          <name>url</name> 
          <required>true</required>
          <fragment>true</fragment>
        </attribute>
        <!-- 配置標籤屬性:user -->
        <attribute>
          <name>user</name> 
          <required>true</required>
          <fragment>true</fragment>
        </attribute>
        <!-- 配置標籤屬性:pass -->
        <attribute>
          <name>pass</name> 
          <required>true</required>
          <fragment>true</fragment>
        </attribute>
        <!-- 配置標籤屬性:sql -->
        <attribute>
          <name>sql</name> 
          <required>true</required>
          <fragment>true</fragment>
        </attribute>
      </tag>

      <!-- 定義第三個帶標籤體的標籤 -->
      <tag>
        <!-- 定義標籤名 -->
        <name>iterator</name>
        <!-- 定義標籤處理類 -->
        <tag-class>lee.IteratorTag</tag-class>
        <!-- 定義標籤體不允許出現JSP腳本 -->
        <body-content>scriptless</body-content>
        <!-- 配置標籤屬性:collection -->
        <attribute>
          <name>collection</name> 
          <required>true</required>
          <fragment>true</fragment>
        </attribute>
        <!-- 配置標籤屬性:item -->
        <attribute>
          <name>item</name> 
          <required>true</required>
          <fragment>true</fragment>
        </attribute>
      </tag>
      <tag>
        <!-- 定義以"頁面片段"作爲屬性的標籤名 -->
        <name>fragment</name>
        <!-- 定義標籤處理類 -->
        <tag-class>lee.FragmentTag</tag-class>
        <!-- 指定該標籤不支持標籤體 -->
        <body-content>empty</body-content>
        <!-- 定義標籤屬性:fragment -->
        <attribute>
          <name>fragment</name>
          <required>true</required>
          <fragment>true</fragment>
        </attribute>
      </tag>
      <!-- 定義接受動態屬性的標籤 -->
      <tag>
        <name>dynaAttr</name>
        <tag-class>lee.DynaAttributesTag</tag-class>
        <body-content>empty</body-content>
        <!-- 指定支持動態屬性 -->
        <dynamic-attributes>true</dynamic-attributes>
      </tag>
    </taglib> 
    定義了上面的標籤庫定義文件之後,將標籤庫文件放在WEB應用的WEB-INF路徑下,WEB容器會自動加載該文件,則該文件定義的標籤庫也將生效

    3) 在JSP文件中使用自定義標籤
    在JSP頁面中使用標籤庫步驟
      1) 導入標籤庫: 使用taglib編譯指令導入標籤庫,由URI唯一標識指定標籤庫,並將標籤庫和指定前綴關聯起來(即所有使用該前綴的標籤將由此標籤庫處理)
      <%@ taglib uri="tagliburi" prefix="tagPrefix" %>
      2) 使用標籤: 在JSP頁面中使用自定義標籤
      <tagPrefix:tagName tagAttribute="tagValue" ..>
        <tagBody/>
      </tagPrefix:tagName>
    example1: helloWorld標籤使用
    <%@ taglib uri="http://littlehann.cnblogs.com/mytaglib" prefix="mytag"%>
    <mytag:helloWorld></mytag:helloWorld>

    example2: QueryTag標籤使用
    <%@ taglib uri="http://littlehann.cnblogs.com/mytaglib" prefix="mytag"%>
    <mytag:query
    driver="com.mysql.jdbc.Driver"
    url="jdbc:mysql://localhost:3306/javaee"
    user="root"
    pass="32147"
    sql="select * from news_inf"/>
    可以看出自定義標籤庫的作用,以簡單的標籤,隱藏複雜的邏輯

    example3: IteratorTag標籤使用
    <%@ taglib uri="http://littlehann.cnblogs.com/mytaglib" prefix="mytag"%>
    <%
    //創建一個List對象
    List<String> a = new ArrayList<String>();
    a.add("瘋狂Java");
    a.add("www.crazyit.org");
    a.add("java");
    //將List對象放入page範圍內
    pageContext.setAttribute("a" , a);
    %>
    <table border="1" bgcolor="#aaaadd" width="300">
      <!-- 使用迭代器標籤,對a集合進行迭代 -->
      <mytag:iterator collection="a" item="item">
      <tr>
        <td>${pageScope.item}</td>
      <tr>
      </mytag:iterator>
    </table>
    可以看到,使用iterator標籤遍歷集合元素比使用JSP腳本遍歷集合元素要優雅,這也是自定義標籤的優勢

    example4: fragment標籤使用
    <%@ taglib uri="http://littlehann.cnblogs.com/mytaglib" prefix="mytag"%>
    <mytag:fragment>
    <!-- 使用jsp:attribute標籤傳入fragment參數 -->
    <jsp:attribute name="fragment">
      <!-- 下面是動態的JSP頁面片段 -->
      <mytag:helloWorld/>
    </jsp:attribute>
    </mytag:fragment> 
    <mytag:fragment>
      <jsp:attribute name="fragment">
        <!-- 下面是動態的JSP頁面片段 -->
        ${pageContext.request.remoteAddr}
      </jsp:attribute>
    </mytag:fragment>

    example5: dynaAttr標籤使用
    <%@ taglib uri="http://littlehann.cnblogs.com/mytaglib" prefix="mytag"%>
    <mytag:dynaAttr name="crazyit" url="crazyit.org"/>  
    <mytag:dynaAttr 書名="瘋狂Java講義" 價格="99.0" 出版時間="2008年" 描述="Java圖書"/>
    可以看到,不管傳入多少屬性,這個標籤都可以處理 

  JSTL是Sun提供的一套標籤庫,DisplayTag是Apache組織下的一套開源標籤庫,主要用於生成頁面並顯示效果

2. JSP註釋

<%-- 註釋內容 --%>
JSP註釋用於標註在程序開發過程中的開發提示,"不會"輸出到客戶端,即客戶端連註釋符號都看不到

3. JSP聲明

JSP聲明用於聲明變量和方法,值得注意的是,JSP聲明將會轉換成對應的Servlet(.java文件)的成員變量或成員方法(牢記這點,後因爲我們還會看到在<%..%>中聲明的是局部成員),
因此JSP聲明依然符合java語法。
<%! 聲明部分 %>

關於JSP的變量聲明
梳理一下,在JSP中聲明變量總共有2中情況:
1) 局部變量
<% 在JSP(本質是java代碼)中聲明變量 %>,又因爲JSP代碼是會被Tomcat翻譯成Servlet的面向對象的java代碼,所以在<% %>中聲明的變量全都是局部變量(即在代碼塊中聲明的變量),
它們不能使用privatepublicstatic等修飾
2) 類變量
<%! %>
用這種方式聲明的變量是在類的範圍域中聲明的,屬於類變量,它們可以使用privatepublicstatic等修飾
使用的使用一定要注意

example:
<%!
//聲明一個整形變量
public int count;
//聲明一個方法
public String info()
{
    return "hello";
}
%>

4. JSP表達式

JSP提供了一種輸出表達式值的簡單方法
<%=表達式%> 

example:
<%!
public int count; 
%>
<%=count++%>

5. JSP腳本

所有可執行性java代碼都可以通過JSP腳本嵌入HTML頁面

example:
<%
out.println(new java.util.Date());
%>

6. JSP的動作指令

動作指令與編譯指令不同:
  1) 編譯指令是通知Servlet引擎的處理消息,是在將JSP編譯成Servlet時起作用
  2) 動作指令只是運行時的動作,通常可替換成JSP腳本,它只是JSP腳本的標準化寫法
JSP的動作指令主要有如下7個:

1) jsp:forward: 
執行頁面轉向,將請求的處理轉發到下一個頁面,可以轉發到:
  1) 靜態HTML頁面
  2) 動態的JSP頁面
  3) 容器中的Servlet
語法1:
<jsp:forward page="{relativeURL|<%=expression%>}"/>
語法2:
<jsp:forward page="{relativeURL|<%=expression%>}">
  {<jsp:param.../>}
</jsp:forward>
第二種語法用於在轉發時增加額外的請求參數。增加的請求參數的值可以通過HttpServletRequest類的getParameter()方法獲取
request.getParameter("");
從本質上來說,jsp:forward這個動作指令只是一個內部轉發,即<jsp:forward../>並沒有重新向新頁面發送了請求,它只是完全採用了新頁面來對用戶生成響應(內部轉發),請求依然是一次
請求,所以請求參數、請求屬性都不會丟失

2) jsp:include:
動態引入一個JSP頁面,它不會導入被include頁面的編譯指令,僅僅將被導入頁面的body內容插入本頁面中
<jsp:include page="{relativeURL|<%=expression%>}" flush="true"/>
或者
<jsp:include page="{relativeURL|<%=expression%>}" flush="true">
  <jsp:param name="parameterName" value="parameerValue"/>
</jsp:include>
這裏要注意和編譯指令的inlcude進行區分
1) 靜態引入(編譯指令)
<%@include file="file.jsp"%>
可以將外部文件嵌入到當前JSP文件中,同時解析這個頁面中的JSP語句(如果有的話),也就是說,它既可以包含靜態的文本,也可以包含動態的JSP頁面。包含頁面在編譯時將完全包含了被包含
頁面的代碼。需要指出的是,靜態包含還會將被包含頁面的編譯指令也包含進來,如果兩個頁面的編譯指令衝突,那麼頁面就會出錯
2) 動態引入(動作指令)
<jsp:include>
歸納起來,動態導入和靜態導入的區別有
1. 靜態導入是將被導入頁面的代碼完全融入,兩個頁面融合成一個整體Servlet
2. 動態導入則在Servlet中使用include方法來引入被導入頁面的內容
3. 靜態導入時被導入頁面的編譯指令會起作用。
4. 動態導入時被導入頁面的編譯指令則失去作用,只是插入被導入頁面的body內容
5. 動態導入可以增加額外的參數
實際上,forward動作指令和include動作指令(動態引入)十分相似,它們都採用方法來引入目標頁面
forward指令使用_jspx_page_context.forward()方法來引入目標頁面
include指令使用org.apache.jasper.runtime.JspRuntimeLibrary.include()方法來引入目標頁面
區別在於,執行forward時,被forward的頁面將完全代替原有的頁面,而執行include時,被include的頁面只是插入原有頁面
即forward拿目標頁面代替原有頁面,而include則拿目標頁面插入原有頁面

3) JavaBean相關
  3.1) jsp:useBean: 在JSP頁面中初始化一個JavaBean的實例
  <jsp:useBean id="name" class="Classname" scope="page|request|session|application"/>
    3.1.1) id: JavaBean的實例名 
    3.1.2) class: 確定JavaBean的實現類
    3.1.3) scope: 指定JavaBean實例的作用範圍
      3.1.3.1) page: 該JavaBean實例僅在該頁面有效
      3.1.3.2) request: 在本次請求有效
      3.1.3.3) session: 在本次session內有效
      3.1.3.4) application: 在本應用中一直有效 
    3.1.4) 
  3.2) jsp:setProperty: 設置JavaBean實例的屬性值
  <jsp:setProperty name="BeanName" property="propertyName" value="value" />
    3.2.1) name: JavaBean的實例名
    3.2.2) property: 確定需要設置的屬性名
    3.2.3) value: 確定需要設置的屬性值
  3.3) jsp:getProperty: 輸出JavaBean實例的屬性值
  <jsp:getProperty name="BeanName" property="propertyName" />
    3.3.1) name: 確定需要輸出的JavaBean實例名
    3.3.2) property: 確定需要輸出的屬性名
這三個指令都是與JavaBean相關的指令,如果多個JSP頁面中需要重複使用某段代碼,我們可以把這段代碼定義成java類的方法,然後讓多個JSP頁面調用該方法即可,這樣可以達到較好的代碼
複用
在.jsp頁面中我們可以這樣編碼
<!-- 創建lee.Person的實例,該實例的實例名爲p1 -->
<jsp:useBean id="p1" class="lee.Person" scope="page"/>
<!-- 設置p1的name屬性值 -->
<jsp:setProperty name="p1" property="name" value="wawa"/>
<!-- 設置p1的age屬性值 -->
<jsp:setProperty name="p1" property="age" value="23"/>
<!-- 輸出p1的name屬性值 -->
<jsp:getProperty name="p1" property="name"/><br/>
<!-- 輸出p1的age屬性值 -->
<jsp:getProperty name="p1" property="age"/>
從代碼中可以看到,我們使用了useBean、setProperty、getProperty來操作JavaBean的方法,同時我們需要明白的是,對於property="name",在JavaBean中提供了setName()、
getName()方法來操作,property="age"也是同理
代碼中對應的JavaBean的Person類源代碼如下
package lee;
public class Person
{
  private String name;
  private int age;
  
  //無參數的構造器
  public Person()
  {
  }
  //初始化全部屬性的構造器
  public Person(String name , int age)
  {
    this.name = name;
    this.age = age;
  }
  
  //name屬性的setter和getter方法
  public void setName(String name)
  {
    this.name = name;
  }
  public String getName()
  {
    return this.name;
  }
  
  //age屬性的setter和getter方法
  public void setAge(int age)
  {
    this.age = age;
  }
  public int getAge()
  {
    return this.age;
  }
} 

4) plugin指令
plugin指令主要用於下載服務器端的JavaBean、或Applet到客戶端執行。由於程序在客戶端執行,因此客戶端必須安裝虛擬機

5) param指令
param指令用於設置參數值,這個指令本身不能單獨使用,因爲單獨的param沒有實際意義。param指令可以與以下三個指令結合使用
  5.1) jsp:include
  當與include指令結合使用時,param指令用於將參數值傳入被導入的頁面
  5.2) jsp:forward
  當與forward指令結合使用時,param指令用於將參數值傳入被轉向的頁面
  5.3) jsp:plugin
  當與plugin指令結合使用時,用於將參數傳入頁面中的JavaBean實例或Applet實例
<jsp:param name="paramName" value="paramValue"/>
*/

7. JSP腳本中的內置對象

JSP腳本中包含內置對象,這些內置對象都是Servleet API接口的實例,JSP規範對它們進行了默認初始化(由JSP頁面對應的Servlet的_jspService()方法來創建這些實例)。即它們已經是對
象了,可以直接在JSP腳本中使用了
內置對象依次如下:
  1) application:
  javax.servlet.ServletContext的實例,該實例代表JSP所屬的WEB應用本身,因此可以使用application來操作WEB相關的數據,application對象通常有如下兩個作用:
    1.1) 在整個WEB應用的多個JSP、Servlet之間共享數據
    application通過setAttribute(String attrName, Object value)方法將一個值設置成application的attrName屬性,該屬性的值對整個WEB應用有效,因此該WEB應用的每
個JSP頁面或Servlet都可以訪問該屬性,訪問屬性的方法爲getAttribute(String attrName)
      1) put-application.jsp
      <% application.setAttribute("counter",String.valueOf(++i)); %>
      2) get-application.jsp
      <%=application.getAttribute("counter")%> 
      3) GetApplication.java
      ServletContext sc = getServletConfig().getServletContext();
      out.println(sc.getAttribute("counter"));
    因爲application代表的是整個WEB應用,因此可以在JSP、Servlet之間共享數據,由於在Servlet中並沒有application內置對象,所以需要獲取該web應用的ServletContext
實例,每個web應用只有一個ServletContext實例,而在JSP中可以直接通過application內置對象訪問該實例
    1.2) 訪問WEB應用的配置參數
    除了共享數據,application還可用於從web.xml中獲得WEB應用的配置參數
    //從配置參數中獲取驅動
    String driver = application.getInitParameter("driver");
    從以上的代碼可以看到,可以使用application的getInitParameter(String paramName)來獲取WEB應用的配置參數,這些參數應該在web.xml文件中使用context-param元素
配置,每個<context-param../>元素配置一個參數
    <context-param>
      <param-name>driver</param-name>
      <param-value>com.mysql.jdbc.Driver</param-value>
    </context-param>

  2) config對象
  javax.servlet.ServletConfig類的實例,config對象代表當前JSP配置信息
  <%=config.getServletName()%>
  因爲所有的JSP頁面都有相同的名字: jsp,所以這段JSP代碼永遠輸出jsp
  實際上,我們也可以在web.xml文件中配置JSP,這樣就可以爲JSP頁面指定配置信息,併爲JSP頁面指定一個虛擬路徑
    1) configTest2.jsp
    <!-- 輸出該JSP名爲name的配置參數 -->
    name配置參數的值:<%=config.getInitParameter("name")%><br/>
    <!-- 輸出該JSP名爲age的配置參數 -->
    age配置參數的值:<%=config.getInitParameter("age")%>
    2) web.xml
    <servlet>
    <!-- 指定Servlet名字 -->
    <servlet-name>config</servlet-name>
    <!-- 指定將哪個JSP頁面配置成Servlet -->
    <jsp-file>/configTest2.jsp</jsp-file>
    <!-- 配置名爲name的參數,值爲yeeku -->
    <init-param>
      <param-name>name</param-name>
      <param-value>yeeku</param-value>
    </init-param>
    <!-- 配置名爲age的參數,值爲30 -->
    <init-param>
      <param-name>age</param-name>
      <param-value>30</param-value>
    </init-param>
    </servlet>
    <servlet-mapping>
      <!-- 指定將config Servlet配置到/config URL-->
      <servlet-name>config</servlet-name>
      <url-pattern>/config</url-pattern>
    </servlet-mapping>

  3) exception對象
  exception對象是Throwable的實例,代表JSP腳本中產生的錯誤和異常,是JSP異常機制的一部分。在JSP腳本中無須處理異常,即使該異常是checked異常,JSP腳本包含的異常都可以交
給錯誤處理頁面處理,exception對象也僅在異常處理頁面中才有效。
  打開普通的JSP頁面所生成的Servlet類,可以看到如下代碼段
  public void _jspService(final javax.servlet.http.HttpServletRequest request, final javax.servlet.http.HttpServletResponse response)
    throws java.io.IOException, javax.servlet.ServletException 
  {
    ..
    try 
    {
      response.setContentType("text/html; charset=GBK");
      ..
      out.write(' ');
    } 
    catch (java.lang.Throwable t) 
    {
      .. 
      if (_jspx_page_context != null) 
        _jspx_page_context.handlePageException(t);
      else 
        throw new ServletException(t);
    } 
    finally 
    {
      _jspxFactory.releasePageContext(_jspx_page_context);
    }
  }
  從以上代碼可以看出,JSP腳本和靜態HTML部分都已經轉換成_jspService()方法裏的執行型代碼,這就是JSP腳本無須處理異常的原因,因爲這些腳本都已經被包含在try塊中了。一旦try
塊中捕捉到JSP腳本的異常,並且_jspx_page_context不爲null,就會由該對象來處理異常。_jspx_page_context對異常的處理也非常簡單: 如果該頁面的page指令指定了errorPage屬性
,則將請求forward到errorPage屬性指定的頁面,否則使用系統頁面來輸出異常信息 

  4) out對象
  out對象代表一個頁面輸出流,通常用於在頁面刪輸出變量值、及常量。所有使用out的地方,都可以使用輸出表達式來代替,而且輸出表達式更加簡潔。從底層原理來看,<%=..%>的本質就
是out.write(..);

  5) pageContext對象
  pageContext對象代表頁面上下文,該對象主要用於訪問JSP之間的共享數據。使用pageContext可以訪問page、request、session、application範圍的變量。
  pageContext是javax.servlet.jsp.PageContext類的實例,它提供了
  getAttribute(String name, int scope)來取得指定範圍內的name屬性,其中scope可以是如下值:
    1) PageContext.PAGE_SCOPE(對應於page範圍,默認值)
    2) PageContext.REQUEST_SCOPE(對應於requsst範圍)
    3) PageContext.SESSION_SCOPE(對應於session範圍)
    4) PageContext.APPLICATION_SCOPE(對應於application範圍)
  與getAttribute相對的,PageContext內置對象自然也有一個setAttribute()方法,用於將指定變量放入page、request、session、application範圍內
  <%
  //使用pageContext設置屬性,該屬性默認在page範圍內
  pageContext.setAttribute("page","hello");	 
  //下面獲取各屬性所在的範圍:
  out.println("page變量所在範圍:" + pageContext.getAttributesScope("page") + "<br/>");
  %>

  除此之外,pageContext還可用於獲取其他內置對象,pageContext對象還包含如下方法
    1) ServletRequest getRequest(): 獲取request對象
    2) ServletResponse getResponse(): 獲取response對象
    3) ServletConfig getServletConfig(): 獲取config對象
    4) ServletContext getServletContext(): 獲取application對象
    5) HttpSession getSession(): 獲取session對象
  因此,pageContext對象是一個很重要的對象,一旦在JSP、Servlet編程中獲取了pageContext對象,就可以通過它提供的相應方法來獲取其他內置對象

  6) request對象
  request對象是JSP中重要的對象,每個request對象封裝着一次用戶請求,並且所有的請求參數都被封裝在request對象中,因此request對象是獲取"請求參數"的重要途徑。除此之外,
request可代表本次請求的範圍,所以還可用於操作request範圍的屬性
  和request對象相關的功能有:
    1) 獲取請求頭/請求參數
    request是HttpServletRequest接口的實例,它提供瞭如下幾個方法來獲得"請求參數"(GET、POST、COOKIE)
      1.1) String getParameter(String paramName): 獲取paramName參數的值
      1.2) Map getParameterMap(): 獲取所有請求參數名和參數值所組成的Map對象
      1.3) Enumeration getParameterNames(): 獲取所有請求參數名和參數值所組成的Enumeration對象
      1.4) String[] getParameterValues(String name): 獲取參數name的值,如果有同名的多個,則返回數組
    HttpServletRequest提供瞭如下方法來訪問HTTP請求頭
      1.1) String getHeader(String name): 獲取指定HTTP頭的參數值
      1.2) java.util.Enumeration<String> getHeaderNames(): 獲取所有請求頭的名稱
      1.3) java.util.Enumeration<String> getHeaders(String name): 獲取指定請求頭的所有值
      1.4) int getIntHeader(String name): 獲取指定請求頭的值,並轉化爲整數值返回
    
    2) 操作request範圍的屬性
    HttpServletRequest還包含如下兩個方法,用於設置和獲取request範圍的屬性
      2.1) setAttribute(String attName, Object attValue): 將attValue設置成request範圍的屬性(用於JSP頁面間共享變量)
      2.2) Object getAttribute(String attName): 獲取request範圍的屬性
    
    3) 執行forward、或include
    request還有一個功能是執行forward和include,也就是代替JSP所提供的forward和include動作指令。
    HttpServletRequest類提供了一個:
    RequesDispatcher getRequestDispatcher(String path):
      1) path爲希望forward或include的目標路徑
    返回了一個RequesDispatcher對象,它提供如下兩個方法:
      1) forward(ServletRequest request, ServletResponse response): 執行forward
      getRequestDispatcher("/a.jsp").forward(request, response);
      2) include(ServletRequest request, ServletResponse response): 執行include
      getRequestDispatcher("/a.jsp").include(request, response);
    
  7) response對象
  response代表服務器對客戶端的響應。大部分時候,使用out(頁面輸出流)生成響應更簡單。但out是JspWriter的實例,JspWriter是Writer的子類,而Writer是字符流,無法輸出非字
符數據。如果需要在JSP中生成一副位圖、PDF文檔,則必須使用response作爲響應輸出
    7.1) response響應生成非字符響應
    response是HttpServletResponse接口的實例,該接口提供了一個getOutputStream()方法,該方法返回響應輸出"字節流"
    <%-- 通過contentType屬性指定響應數據是圖片 --%>
    <%@ page contentType="image/jpeg" language="java"%>
    <%@ page import="java.awt.image.*,javax.imageio.*,java.io.*,java.awt.*"%>
    <%
    //創建BufferedImage對象
    BufferedImage image = new BufferedImage(340, 160, BufferedImage.TYPE_INT_RGB);
    //以Image對象獲取Graphics對象
    Graphics g = image.getGraphics();
    //使用Graphics畫圖,所畫的圖像將會出現在image對象中
    g.fillRect(0,0,400,400);
    //設置顏色:紅
    g.setColor(new Color(255,0,0));
    //畫出一段弧
    g.fillArc(20, 20, 100,100, 30, 120);
    //設置顏色:綠
    g.setColor(new Color(0 , 255, 0));
    //畫出一段弧
    g.fillArc(20, 20, 100,100, 150, 120);
    //設置顏色:藍
    g.setColor(new Color(0 , 0, 255));
    //畫出一段弧
    g.fillArc(20, 20, 100,100, 270, 120);
    //設置顏色:黑
    g.setColor(new Color(0,0,0));
    g.setFont(new Font("Arial Black", Font.PLAIN, 16));
    //畫出三個字符串
    g.drawString("red:climb" , 200 , 60);
    g.drawString("green:swim" , 200 , 100);
    g.drawString("blue:jump" , 200 , 140);
    g.dispose();
    //將圖像輸出到頁面的響應
    ImageIO.write(image , "jpg" , response.getOutputStream());
    %>
    從代碼中可以看到幾個關鍵點:
      1) 設置了服務器響應數據是image/jpeg,這表明服務器響應是一張JPG圖片
      2) 最後的響應輸出流是一個圖片的字節流
    也可以在其他HTML頁面中使用img標籤來顯示這張圖片
    <img src="img.jsp">

    7.2) 重定向
    重定向是response的另外一個用處,要注意的是,和forward這種內部轉接"不同"的是,response的重定向會丟失所有的原始請求參數和request範圍的屬性,因爲重定向將生成第二
次請求,自然與前一次請求不在同一個request範圍內。
    HttpServletResponse提供了一個sendRedirect(String path)方法,該方法用於"重定向"到path資源,即"重新"向path資源發送請求

    7.3) 增加Cookie
    增加Cookie也是使用response內置對象完成的,增加Cookie的步驟如下
      1) 創建Cookie實例,構造函數Cookie(String name, String value)
      2) 設置Cookie的生命週期,即該Cookie在多長時間內有效
      3) 向客戶端寫Cookie,void addCookie(Cookie cookie): 增加Cookie
    <%
    //獲取請求參數
    String name = request.getParameter("name");
    //以獲取到的請求參數爲值,創建一個Cookie對象
    Cookie c = new Cookie("username" , name);
    //設置Cookie對象的生存期限
    c.setMaxAge(24 * 3600);
    //向客戶端增加Cookie對象
    response.addCookie(c);
    %>

    獲取客戶端發送的Cookie的方法
    <%
    //獲取本站在客戶端上保留的所有Cookie
    Cookie[] cookies = request.getCookies();
    //遍歷客戶端上的每個Cookie
    for (Cookie c : cookies)
    {
      //如果Cookie的名爲username,表明該Cookie是我們需要訪問的Cookie
      if(c.getName().equals("username"))
      {
        out.println(c.getValue());
      }
    }
    %>
    要注意的是:
      1) 使用Cookie對象必須設置生存週期,否則Cookie將會隨瀏覽器關閉而自動消失(session cookie)
      2) 如果要存入中文Cookie,則需要使用java.net.URLEncoder進行編碼,在獲取時用java.net.URLDncoder進行解碼

  8) session對象 
  session對象代表一次用戶會話,session範圍內的屬性可以在多個頁面的跳轉之間共享。session對象是HttpSession的實例,它有如下兩個常用的方法:
    8.1) setAttribute(String attName, Object attValue): 設置session範圍內attName屬性的值爲attValue
    8.2) getAttribute(String attName): 返回session範圍內attName屬性的值
  使用session對象要注意的是:
  考慮session本身的目的,通常只應該把與用戶會話狀態相關的信息放入session範圍內。不要僅僅爲兩個頁面之間交換信息,就將信息放入session範圍內。如果僅僅是爲了頁面間交換信
息,可以將信息放入request範圍內,然後forward請求即可。
  除此之外,session機制通常用於保存客戶端的狀態信息,這些狀態信息需要保存到web服務器的硬盤上,所以要求session裏的屬性值必須是可序列化的,否則將引起"不可序列化異常",
即session的屬性值可以是任何可序列化的java對象

  4. Servlet基礎語法

我們知道,JSP的本質就是Servlet,開發者把編寫好的JSP頁面部署在WEB容器中之後,WEB容器會將JSP編譯成對應的Servlet。

Servlet和JSP的區別在於:

1) Servlet中沒有內置對象,原來在JSP中的內置對象都必須由程序顯示創建。JSP是Servlet的一種簡化,使用JSP只需要完成程序員需要輸出到客戶端的內容,至於JSP腳本如何嵌入一個類中,
由JSP容器完成
2) 對於靜態HTML標籤,Servlet都必須使用頁面輸出流逐行輸出。而Servlet則是一個完整的java類,這個類的service()方法用於生成對客戶端的響應

0x1: Servlet的配置

配置需要的準備條件如下:

1. 編輯好的Servlet源代碼文件並不能響應用戶請求,還必須將其編譯成class文件。將編譯好的.class文件放在WEB-INF/classes路徑下,如果Servlet有包,則還應該將class文件放在對
應的包路徑下
2. 爲了讓Servlet能響應用戶請求,還必須將Servlet配置在web應用中,配置Servlet有兩種方式
  1) 在Servlet類中使用@WebServlet Annotation進行配置
  使用@WebServlet時可制定如下常用屬性
    1.1) asyncSupported: 聲明Servlet是否支持異步操作模式,等價於<async-supported>標籤
    1.2) displayName: 該Servlet的顯示名,通常配合工具使用,等價於<display-name>標籤
    1.3) initParams: 指定一組Servlet初始化參數,等價於<init-param>標籤
    1.4) loadOnStartup: 指定Servlet的加載順序,等價於<load-on-startup>標籤
    1.5) name: 指定Servlet的name屬性,等價於<servlet-name>,如果沒有顯式指定,則該Servlet的取值即爲類的全限定名
    1.6) urlPatterns: 指定一組Servlet的URL匹配模式(虛擬路徑)。等價於<url-pattern>標籤
    1.7) value: 該屬性等價於urlPatterns屬性。兩個屬性不能同時使用
  example:
  @WebServlet(name="firstServlet", urlPatterns={"/firstServlet"})
  需要注意的是,如果打算採用Annotation來配置Servlet,需要注意如下兩點:
    1) 不要在web.xml文件的根元素<web-app../>中指定metadata-complete="true",因爲當該屬性值爲true時,該web應用不會加載Annotation配置的WEB組件(如Servlet、
Filter、Listener等)
    2) 不要在web.xml文件中配置該Servlet
  2) 通過在web.xml文件中進行配置
    2.1) 配置Servlet的名字: 對應web.xml文件中的<servlet/>元素
    2.2) 配置Servlet的URL: 對應web.xml文件中的<servlet-mapping/>元素。這一步是可選的。但如果沒有爲Servlet配置URL(虛擬路徑),則該Servlet不能響應用戶請求
  example:
  <servlet>
    <!-- 指定Servlet的名字,相當於指定@WebServlet的name屬性 -->
    <servlet-name>firstServlet</servlet-name>
    <!-- 指定Servlet的實現類 -->
    <servlet-class>lee.FirstServlet</servlet-class>
  </servlet>
  <!-- 配置Servlet的URL -->
  <servlet-mapping>
    <!-- 指定Servlet的名字 -->
    <servlet-name>firstServlet</servlet-name>
    <!-- 指定Servlet映射的URL地址,相當於指定@WebServlet的urlPatterns屬性-->
    <url-pattern>/aa</url-pattern>
  </servlet-mapping>
需要明白的,Annotation和web.xml配置,只要其中一種即可完成Servlet的配置

0x2: JSP/Servlet的生命週期

JSP的本質就是Servlet,當Servlet在容器中運行時,其實例的創建及銷燬等都不是由程序員決定的,而是由WEB容器進行控制的。 
創建Servlet實例有兩個時機 

1. 客戶端第一次請求某個Servlet時,系統創建該Servlet的實例: 大部分的Servlet都是這種情況
2. WEB應用啓動時立即創建Servlet實例,即load-on-startup Servlet

每個Servlet的運行都遵循如下生命週期 

1. 創建Servlet實例
2. WEB容器調用Servlet的init方法,對Servlet進行初始化
3. Servlet初始化之後,將一直存在於容器中,用於響應客戶端請求:
    1) 如果客戶端發送GET請求,容器調用Servlet的doGet方法處理並響應請求
    2) 如果客戶端發送POST請求,容器調用Servlet的doPost方法處理並響應請求
    3) 或者統一用service()方法處理來響應用戶請求
4. WEB容器決定銷燬Servlet時,先調用Servlet的destroy方法,通常在關閉web應用之前銷燬Servlet

0x3: Filter介紹

Filter從本質上來說和Servlet很相似,它主要用於對用於請求(HttpServletRequest)進行預處理、以及對用戶響應(HttpServletResponse)進行後處理,是一種典型的"處理鏈"機制。 
Filter完整運行的流程是: 

1) Filter對用於請求(HttpServletRequest)進行預處理
2) 接着將請求交給Servlet進行處理並生成響應
3) 最後Filter再對服務器響應(HttpServletResponse)進行後處理

使用Filter編程的完成流程是:

1. 創建Filter類
創建Filter必須實現javax.servlet.Filter接口,在該接口中定義瞭如下3個方法
  1) void init(FilterConfig config): Filter的初始化
  2) void destroy(): 用於Filter銷燬前,完成資源的回收等工作
  3) void doFilter(ServletRequest request, ServletResponse response, FilterChain chain): 實現過濾功能,該方法負責對每個請求、及響應增加額外的處理
example:
package lee;
import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.*;
import java.io.*;

@WebFilter(filterName="log", urlPatterns={"/*"})
public class LogFilter implements Filter 
{
  //FilterConfig可用於訪問Filter的配置信息
  private FilterConfig config;
  //實現初始化方法
  public void init(FilterConfig config)
  {
    this.config = config; 
  }
  //實現銷燬方法
  public void destroy()
  {
    this.config = null; 
  }
  //執行過濾的核心方法
  public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException,ServletException
  {
    //---------下面代碼用於對用戶請求執行預處理---------
    //獲取ServletContext對象,用於記錄日誌
    ServletContext context = this.config.getServletContext(); 
    long before = System.currentTimeMillis();
    System.out.println("開始過濾...");
    //將請求轉換成HttpServletRequest請求
    HttpServletRequest hrequest = (HttpServletRequest)request;
    //輸出提示信息
    System.out.println("Filter已經截獲到用戶的請求的地址: " + hrequest.getServletPath());
    //Filter只是鏈式處理,請求依然放行到目的地址
    chain.doFilter(request, response);
    //---------下面代碼用於對服務器響應執行後處理---------
    long after = System.currentTimeMillis();
    //輸出提示信息
    System.out.println("過濾結束");
    //輸出提示信息
    System.out.println("請求被定位到" + hrequest.getRequestURI() + "   所花的時間爲: " + (after - before)); 
  } 
}
從代碼中可以看到,doFilter()方法中"請求預處理""響應後處理"的分界線是chain.doFilter()

2. 配置Filter
配置Filter和配置Servlet非常類似,需要配置如下兩部分:
  1) 配置Filter名
  2) 配置Filter攔截URL模式: Servlet通常只配置一個URL,而Filter可以同時攔截多個請求的URL。因此在配置Filter的URL模式時通常會使用"模式字符串"(正則字符串),使得
Filter可以攔截多個請求
    2.1) 在Filter類中通過Annotation進行配置
      2.1.1) asyncSupported: 聲明Filter是否支持異步操作模式 
      2.1.2) dispatcherTypes: 指定該Filter僅對哪種dispatcher模式的請求進行過濾
        2.1.2.1) ASYNC
        2.1.2.2) ERROR
        2.1.2.3) FORWARD
        2.1.2.4) INLCUDE
        2.1.2.5) REQUEST
      5種組合可以以OR的形式進行組合,dispatcherTypes的默認值是"同時"過濾5種模式的請求
      2.1.3) displayName: 該Filter的顯示名 
      2.1.4) filterName: 指定該Filter的名稱
      2.1.5) initParams: 指定一組Filter配置參數 
      2.1.6) servletName: 指定多個Servlet的名稱,用於指定該Filter僅對這幾個Servlet執行過濾
      2.1.7) urlPatterns: 指定一組Filter的URL匹配模式(虛擬路徑) 
      2.1.8) value: 該屬性等價於urlPatterns屬性。兩個屬性不能同時使用
    2.2) 在web.xml文件中通過配置文件進行配置
    <filter>
      <!-- Filter的名字,相當於指定@WebFilter的filterName屬性 -->
      <filter-name>log</filter-name>
      <!-- Filter的實現類 -->
      <filter-class>lee.LogFilter</filter-class> 
    </filter>
    <!-- 定義Filter攔截的URL地址 -->
    <filter-mapping>
      <!-- Filter的名字 -->
      <filter-name>log</filter-name>
      <!-- Filter負責攔截的URL,相當於指定@WebFilter的urlPatterns屬性 -->
      <url-pattern>/*</url-pattern>
    </filter-mapping>

3. 使用Filter
Filter對應的.class文件被加載後,Filter就會根據設定的URL模式進行響應的預處理、後處理

Filter和Servlet的異同

從本質上來說,Filter和Servlet很相似,Filter裏的doFilter()方法裏的代碼就是從多個Servlet的service()方法裏抽取的通用代碼,通過使用Filter可以實現更好的代碼複用
(類似PHP中的auto_prepend_file、auto_append_file)
假設系統有包含多個Servlet,這些Servlet都需要進行一些通用處理,比如
1) 權限控制: 在預處理中判斷用戶是否登錄,從而決定是否重定向到初始登錄頁面
2) 記錄日誌: 將用戶的訪問記錄記錄到日誌中
3) URL Rewrite實現網站僞靜態
所謂僞靜態,是將*.jsp、*.php、這種動態URL僞裝成靜態HTML頁面,目的是提供搜索引擎的收錄率,我們可以通過Filter攔截所有發向*.html請求,然後按某種規則將請求forward到實際的
*.jsp頁面
  3.1) 下載Url Rewrite: http://www.tuckey.org/urlrewrite/
  3.2) 將urlrewrite-3.2.0.jar放到WEB-INF\lib目錄下
  3.3) 配置WEB-INF\web.xml
  <filter>
    <filter-name>UrlRewriteFilter</filter-name>
    <filter-class>org.tuckey.web.filters.urlrewrite.UrlRewriteFilter</filter-class>
  </filter>
  <!-- 配置Url Rewrite的Filter攔截所有請求 -->
  <filter-mapping>
    <filter-name>UrlRewriteFilter</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>
  3.4) 配置WEB-INF\urlrewrite.xml
  <urlrewrite>
    <rule>
      <!-- 所有配置如下正則表達式的請求 -->
      <from>/userinf-(\w*).html</from>
      <!-- 將被forward到如下JSP頁面,其中$1代表上面第一個正則表達式所匹配的字符串 -->
      <to type="forward">/userinf.jsp?username=$1</to>
    </rule>
  </urlrewrite>
  3.5) 訪問僞靜HTML頁面: http://localhost:8080/urlrewrite/userinf-LittleHann.html

0x4: Listener介紹

當WEB應用在WEB容器中運行時,WEB應用內部會不斷地發生各種事件: 

1) web應用被啓動
2) web應用被停止
3) 用戶session開始
4) 用戶session結束
5) 用戶請求到達

通常來說,這些web事件對開發者是透明的 
實際上,Servlet API提供了大量監聽器和監聽WEB應用內部事件,從而允許當WEB內部事件發生時自動回調"事件監聽器內的方法"

使用Listener的步驟如下:

1. 實現Listener類
監聽不同的WEB事件的監聽器也不相同。WEB事件監聽器接口如下
  1) ServletContextListener: 用於監聽WEB應用的啓動和關閉
    1.1) contextInitialized(ServletContextEvent sce)
    1.2) contextDestroyed(ServletContextEvent sce)
  2) ServletContextAttributeListener: 用於監聽ServletContext範圍(application)內屬性的改變
    2.1) attributeAdded(ServletContextAttributeEvent event) 
    2.2) attributeRemoved(ServletContextAttributeEvent event)
    2.3) attributeReplaced(ServletContextAttributeEvent event)
  3) ServletRequestListener: 用於監聽用戶請求
    3.1) requestInitialized(ServletRequestEvent sre) 
    3.2) requestDestroyed(ServletRequestEvent sre) 
  由於實現了ServletRequestListener接口的監聽器可以非常方便地監聽到每次請求的創建、銷燬,因此web應用可通過該接口的監聽器來監聽訪問該應用的每個請求,從而實現系統日誌
  4) ServletRequestAttributeListener: 用於監聽ServletRequest範圍(request)內屬性的改變
    4.1) attributeAdded(ServletRequestAttributeEvent event) 
    4.2) attributeRemoved(ServletRequestAttributeEvent event)
    4.3) attributeReplaced(ServletRequestAttributeEvent event) 
  5) HttpSessionListener: 用於監聽用戶session的開始和結束
    5.1) sessionCreated(HttpSessionEvent se) 
    5.2) sessionDestroyed(HttpSessionEvent se)
  實現HttpSessionListener接口的監聽器可以監聽每個用於會話的開始和斷開,因此應用可以通過該監聽器監聽系統的在線用戶
  6) HttpSessionAttributeListener: 用於監聽HttpSession範圍(session)內屬性的改變
    6.1) attributeAdded(HttpSessionBindingEvent se) 
    6.2) attributeRemoved(HttpSessionBindingEvent se) 
    6.3) attributeReplaced(HttpSessionBindingEvent se) 
2. 配置Listener
配置Listener只要向web應用註冊Listener實現類即可,無須配置參數,相對較簡單
  1) 使用@WebListener修飾Listener實現類
  2) 在web.xml文檔中使用<listener../>元素進行配置
  <listener>
    <!-- 指定Listener的實現類 -->
    <listener-class>lee.GetConnListener</listener-class>
  </listener>
3. 在指定事件發生時執行相應的函數,我們在實現相應的接口時就需要實現相應的函數
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章