相關學習資料php
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/
目錄html
1. J2EE WEB應用文件目錄結構 2. web.xml基礎語法 3. JSP基礎語法 4. Servlet基礎語法
1. J2EE WEB應用文件目錄結構
java
Java Web應用由一組靜態HTML頁、Servlet、JSP和其餘相關的class組成,它們一塊兒構成一個大的工程項目。每種組件在Web應用中都有固定的存放目錄。Web應用的配置信息存放在web.xml文件中。在發佈某些組件(如Servlet)時,必須在web.xml文件中添加相應的配置信息
Java Web應用程序必須使用規範的目錄結構mysql
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基礎語法linux
位於每一個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中插入解釋說明能更好的說明問題web
/* <?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基礎語法spring
JSP的本質是Servlet,當用戶向指定Servlet發送請求時,Servlet利用輸出流動態生成HTML頁面,包括每個靜態的HTML標籤和全部在HTML頁面中出現的內容
JSP頁面由以下兩部分組成sql
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代碼,因此在<% %>中聲明的變量全都是局部變量(即在代碼塊中聲明的變量),
它們不能使用private、public、static等修飾 2) 類變量 <%! %> 用這種方式聲明的變量是在類的範圍域中聲明的,屬於類變量,它們可使用private、public、static等修飾
使用的使用必定要注意
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)進行後處理,和linux上的iptables相似,是一種典型的"處理鏈"機制。
Filter完整運行的流程是:
1) Filter對用於請求(HttpServletRequest)進行預處理 它使用戶可使用串行的方式在request到達servlet以前預處理,即改變一個Request 2) 接着將請求交給Servlet進行處理並生成響應 3) 最後Filter再對服務器響應(HttpServletResponse)進行後處理 它使用戶可使用串行的方式在request離開servlet時處理response,即修改一個response
Filter能夠實現的功能包括
1. 在servlet被調用以前截獲 2. 在servlet被調用以前檢查servlet request 3. 根據須要修改request頭和request數據 4. 根據須要修改response頭和response數據 5. 在servlet被調用以後截獲
使用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模式進行響應的預處理、後處理
Tomcat Filter的函數調用流程爲
1. setFilterConfig()方法 服務器每次只調用一次準備filter的處理 2. doFilter()方法 調用屢次,用於每次以處理不一樣的請求。FilterConfig接口有方法能夠找到filter名字及初始化參數信息。服務器能夠設置FilterConfig爲空來指明filter已經終結。 每個filter從doFilter()方法中獲得當前的request及response。在這個方法裏,能夠進行任何的針對request及 response的操做.(包括收集數據,包裝數據等) 3. chain.doFilter()方法 filter調用chain.doFilter()方法把控制權交給下一個filter。一個filter在doFilter()方法中結束。若是一個filter想中止request處理而得到對response的徹底的控制,那它能夠不調用下一個filter,即這是一個鏈式的操做
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. 在指定事件發生時執行相應的函數,咱們在實現相應的接口時就須要實現相應的函數
Copyright (c) 2014 LittleHann All rights reserved