javaweb應用程序概述

一、HTTP(超文本傳輸協議),它是一種主流的B/S架構中應用的通訊協議。具備如下特色:

1.一、無狀態:服務不會記錄客戶端每次提交的請求,服務器一旦響應客戶端以後,就會結束本次的通訊過程,客戶端下一次的請求是一個新的鏈接,和上一次通訊沒有任何關係html

1.二、簡單靈活:HTTP是基於請求和響應的模型java

支持客戶端與服務端:web

1.三、支持主流的B/S以及C/S架構的通訊。C/S架構可選的協議有多種,列如:TCP/IP、UDP、HTTP、等,而B/S架構一般只支持HTTP協議。數據庫

二、服務器

2.一、概念

服務器同常由硬件和軟件部分構成,對用戶提供相應的服務express

硬件:包括相應的CPU、內存、磁盤、等等api

軟件:包括操做系統、運行環境、服務端軟件、數據庫等等瀏覽器

2.二、Web服務器

web服務器是提供服務端程序運行的一個環境,它自己也是一個軟件緩存

列如:將咱們編寫的html文件放到web容器服務器中,那麼外界就能夠經過瀏覽器來訪問咱們的HTML頁面,tomcat

常見的web服務器有Apache、Tomcat、Jetty、Nginx等等,而Tomcat、Jetty、這些web服務器更準確地來講是一個Servlet容器服務器

 3. Web項⽬結構

錄,例
如:
myweb
ch01
一般存放靜態資源⽂件(如: html等等)
WEB-INF 這個⽬錄是當前項⽬私有的⼀個⽂件夾,只能提供給項⽬內部訪問,對於客戶端來講是訪問
不到了,一般這個⽬錄下存放的是Java源代碼、編譯後的字節碼⽂件以及Servlet的核⼼配置⽂件web.xml
src 存放Java源代碼的⽬錄
classes 存放編譯後的字節碼⽂件
llib lib⽬錄存放當前項⽬所須要的jar⽂件
jsp ⻚⾯ ⽤於存放JSP動態
web.xml 項⽬的配置⽂件,⽤於配置Servlet的請求映射、過濾器、監聽器等等信息。每⼀個web項⽬都對應⼀個web.xml配置⽂件

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

4. Servlet基礎

4.1 什麼是Servlet6

ServletJavaEE中的標準組件之⼀,專⻔⽤於處理客
戶端的HTTP請求。而且它必須依賴於Servlet容器
Tomcat就是⼀個標準的Servlet容器)才能夠運⾏,
⽽不能脫離這個環境⽽單獨執⾏。由於Servlet實例的
建立和銷燬都是由容器負責管理的,咱們不能⾃⾏經過
new關鍵去建立和使⽤它。

 

 

4.2 編寫⼀個簡單的Servlet

1.在任意地⽅建立⼀個myweb⽂件夾,這個⽂件夾相
當於⼀個項⽬根⽬錄
2.在根⽬錄下建立WEB-INF⼦⽬錄
3.WEB-INF⽬錄下建立srcclasses⼦⽬錄
4.src⽬錄下編寫⼀個類,繼承HttpServlet這個⽗類

public class HelloServlet extends HttpServlet { } 

 2.重寫⽗類的service⽅法,這個就是專⻔處理客戶端請
求的⽅法, web容器會爲這個⽅法傳⼊兩個參數
HttpServletRequestHttpServletResponse,而且這個
⽅法還須要拋出ServletExceptionIOException給容
器捕獲

public class HelloServlet extends HttpServlet { public void service(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException{ //設置響應類型及編碼 response.setContentType("text/html;charset =utf-8"); //獲取字符輸出流輸出html信息 response.getWriter().println(" <h1>Hello Servlet</h1>") } } 

 5.編譯Servlet,須要依賴servlet-api.jar⽂件,將它添加
classpath

javac -cp d:\servlet-api.jar; HelloServlet.java 

6.將編譯後的HelloServlet.class⽂件剪切到classes
錄中

7.WEB-INF⽬錄下建立並編輯web.xml⽂件,爲
servlet配置請求映射

 

<?xml version="1.0" encoding="utf-8"?> <!-- 配置根節點 --> <web-app> <!-- 配置servlet類 --> <servlet> <!-- 指定servlet的別名 --> <servlet-name>hello</servlet-name> <!-- 指定Servlet的完整類名--> <servlet-class>HelloServlet</servletclass> </servlet> <!-- 配置請求映射--> <servlet-mapping> <!-- 這⾥的servlet-name和上⾯的 servlet-name要⼀⼀對應 --> <servlet-name>hello</servlet-name> <!-- 配置請求映射的url,必須以「/」開頭--> <url-pattern>/hello</url-pattern> </servlet-mapping> </web-app> 

 8.將項⽬部署都tomcatwebapps⽬錄中,並執⾏bin
錄下的startup.bat啓動容器

9.打開瀏覽器,在地址欄輸⼊http://localhost:8080/m
yweb/hello訪問Servlet

4.3 Servlet的請求處理流程

瀏覽器發起http的請求,這個請求⾸先會被servlet容器
Tomcat)截獲,而後容器會根據web.xml⽂件中配
servlet的來找到相應的這個別名,而後再根據這個
別名找到具體Servlet的類,而後容器會建立這個
Servlet類的實例並調⽤service⽅法來處理這個請求。

4.4 Servlet的⽣命週期

所謂的⽣命週期,就是從Servlet的建立⼀直到它銷燬
的整個過程。而且它的這個⽣命週期都是由Servlet
器(Tomcat)負責管理和維護的。(補充:在Tomcat
中, Servlet是以單實例多線程的⽅式處理客戶端請
求)


4.4.1 Servlet對象建立的過程

當第⼀次請求某個Servlet的時候,容器會先查找以前
有沒有建立過這個Servlet的實例,若是沒有則建立⼀
個並緩存起來。後續相同的請求都由這個緩存的對象來
處理。(注意:這⾥說的是第⼀次請求時建立。另外⼀
種狀況則是在容器啓動的時候就建立Servlet的實例,

4.4.2 ⽣命週期⽅法

⽅法名  描述
init Servlet對象建立以後⽴即執⾏的初始化
⽅法,且只執⾏⼀次
service 核⼼的請求處理⽅法,這個⽅法能夠執⾏
屢次
destroy 容器準備銷燬Servlet實例以前執⾏這個⽅
法,也是執⾏⼀次

 


 

 

 

 

 

 

 

web.xml中爲Servlet指定配置,這個配置的值是⼀個整型,數值越⼩,則初始化的優先級別越⾼)

4.5 HTTP報⽂組成

4.5.1 請求報⽂

請求⾏:請求報⽂的第⼀⾏就是請求⾏。包括請求⽅
法、請求URL地址、 HTTP協議版本。
請求頭:請求⾏以後的信息就是請求頭,它是以名稱:
內容的格式體現。主要包括服務器主機地址及端⼝、
鏈接狀態、系統信息、編碼、語⾔等等。
請求體:請求頭結束以後會有⼀個空⾏,空⾏以後就是
請求體的內容。一般使⽤POST提交的數據信息會存放
在請求體當中,而後傳遞給服務器。
4.5.2 響應報⽂

狀態⾏:主要包括HTTP協議、響應狀態碼(例如:
200表示OK,成功響應)。
響應頭:主要包括服務器信息、響應的類型及編碼、內容的⻓度、響應的時間等。
響應體:服務端能夠將信息數據攜帶到響應體中,帶回客戶端。
4.6 HTTP請求⽅法

HTTP/1.1協議中,請求⽅法主要包括8個,下⾯列舉
常⽤的請求⽅法進⾏說明。

⽅法 說明
GET 向服務器請求指定的資源,並返回響應主
體。⼀般來講GET⽅法應該只⽤於數據的
讀取(相似於查詢)
POST 向指定的服務器提交數據(例如:表單數
據的提交、⽂件上傳等) ,而且提交的數據
會放⼊請求體中(相似於新增)
PUT 向服務器提交數據,可是和POST有所區
別。若是服務器不存在此資源的時候,則
執⾏新增,若是存在則執⾏修改(相似於
修改)
DELETE 根據uri的標識刪除服務器上的某個資源
(相似於刪除)
其餘 ...


 

 

 

 

 

 

 

 

 

 

 

 

 

 



備註: GETPOST區別:                

 


1.GET主要⽤於獲取數據, POST⽤於提交數據。
2.GET請求所帶的參數是放在請求⾏的url地址後⾯,⽽POST這是放在請求體中。
3.一般瀏覽器會對GET請求的url⻓度有所限制,⽽POST提交的數據在請求體中,能夠提交更多的內容。

⽅法 說明
service 能夠處理任何的請求類型
doGet 處理對應的GET請求
doPost 處理對應的POST請求
doPut 處理對應的PUT請求
doDelete 處理對應的DELETE請求
其餘 ...

 

 

 

 

 

 

 

 

 

 


4.瀏覽器會對GET請求進⾏緩存

說明:經過HttpServlet的源代碼得知,默認的全部請求都會先通過service⽅法,而後service⽅法根據請求
的⽅法類型判斷來決定交給doGet或者是doPost⽅法來處理請求。若是⼦類重寫了⽗類的service⽅法同時
還重寫了其餘的doXxx的⽅法,那麼只有service⽅法會處理請求,其餘⽅法將失效。
4.8 RequestResponse對象

web容器調⽤某個ServletService⽅法時,會建立⼀個HttpServletRequestHttpServletRespinse對象
做爲參數傳⼊到這個⽅法中,那麼咱們能夠經過HttpServletRequest來獲取相關的請求內容等,⽽響應客戶端

能夠利⽤HttpServletResponse對象來完成。

 4.9 Servlet之間的通訊

4.9.1轉發

所謂轉發就是在多個Servlet之間共享請求和響應對象,全部參與轉發的過程的Servlet均可以獲取同一個請求對象的信息。

在servlet的API中,轉發的操做有HttpServletRequest

示例代碼:

 

 

package edu.nf.ch06.servlet; import java.io.IOException; import javax.servlet.RequestDispatcher; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class ServletA extends HttpServlet{ public void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{ System.out.println("請求通過ServletA,準備轉發給ServletB..."); //獲取頁面提交的參數 String name = request.getParameter("userName"); System.out.println("ServletA獲取請求參數:"+name); //可使用請求做用域(requestScope)而外攜帶一些數據到ServletB request.setAttribute("age", 35); System.out.println("設置請求做用域:age = " + 35); //轉發由HttpServletRequest完成 //第一步先獲取一個請求轉發器RequestDispatcher //獲取請求轉發器的同時要告訴轉發器轉發到哪裏,轉發給誰 //若是要轉發給ServletB,那麼就是對應ServletB的url-pattern RequestDispatcher rd = request.getRequestDispatcher("servletB"); //調用轉發器的forward方法執行轉發,同時將request和response對象一併轉發ServletB rd.forward(request, response); } } 

 

 

package edu.nf.ch06.servlet; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class ServletB extends HttpServlet{ @Override protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { System.out.println("請求到達ServletB,並接收了同一個請求和響應對象"); //這裏在同一個請求中再次獲取頁面的參數 String name = request.getParameter("userName"); //從請求做用域中取出相應的值 Integer age = (Integer)request.getAttribute("age"); System.out.println("ServletB獲取請求參數:"+name); System.out.println("ServletB獲取請求做用域的值:"+age); } } 

 

 <servlet> <servlet-name>servletA</servlet-name> <servlet-class>edu.nf.ch06.servlet.ServletA</servlet-class> </servlet> <servlet-mapping> <servlet-name>servletA</servlet-name> <url-pattern>/servletA</url-pattern> </servlet-mapping> <servlet> <servlet-name>servletB</servlet-name> <servlet-class>edu.nf.ch06.servlet.ServletB</servlet-class> </servlet> <servlet-mapping> <servlet-name>servletB</servlet-name> <url-pattern>/servletB</url-pattern> </servlet-mapping> 

 

<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Insert title here</title> </head> <body> <a href="servletA?userName=wangl">測試轉發</a><br/> </body> </html> 

 

轉發的特色:

一、url的地址欄是不會發生改變的

二、轉發的過程是在服務端自動完成的

4.9.2 重定向

重定向的機制和轉發不一樣,一次重定向的過程當中會有兩次請求和兩次響應,服務器在接受第一次請求後悔先作一次302響應(302表示重定向狀態碼)

告訴客戶端瀏覽器必須發起一個新的請求地址,服務端再次接受這個請求處理,最後再次響應到客戶端。因爲會產生不一樣的響應對象,所以並不一樣共享同一個請求的參數

 

 

重定向是服務器通知瀏覽器去訪問另外一個地址,即再發出另外一個請求。

下面用一張圖來簡單描述下:

 

重定向的特色:

一、URL地址欄會發生改變

二、重定向的操做是在客戶端瀏覽器完成的

示例代碼:

 

package edu.nf.ch06.servlet; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class ServletC extends HttpServlet { @Override protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { System.out.println("請求到達ServletC"); System.out.println("ServletC獲取請求參數:"+request.getParameter("userName")); //執行重定向 //方式一:設置302響應狀態碼,並在響應頭中添加location屬性指定重定向的地址 //response.setStatus(302); //response.addHeader("location", "http://localhost:8080/ch06/servletD"); //方式二: response.sendRedirect("servletD"); } } 

 

package edu.nf.ch06.servlet; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class ServletD extends HttpServlet{ @Override protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { System.out.println("重定向到ServletD"); System.out.println("ServletD獲取請求參數:"+request.getParameter("userName")); } } 

 

<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Insert title here</title> </head> <body> <a href="servletC?userName=wangl">測試重定向</a> </body> </html> 

 

4.10會話跟蹤

因爲HTTP協議是無狀態的,服務器並不會記錄每個客服端的狀態,所以,若是想要實現服務器能記錄客服端的狀態的話,那麼就須要會話跟蹤技術

4.1.1cookie

cookie是客服端瀏覽器內部的一個文本文件,專門用於記錄服務器發送過來的一些文本信息,那麼再次請求的時候,都把這個cookie信息由提交回給

相應的服務器,那麼服務器就能夠獲取客服端保存的信息,達到會話跟蹤的目的,使用cookie的機制是基於客戶端瀏覽器來維護與服務端的狀態跟蹤

cookie的生命週期:

示例代碼:

 

默認cookie只會保存在瀏覽器進程的內存中,並不會寫入cookie文件,若是關閉了瀏覽器,那麼瀏覽器的進程也就會消失,那麼對應的內存就會釋放空間,

所以cookie也就銷燬。若是想要cookie寫入文件,那麼就必須設置cookie的生命時長,一旦設置了生命時長,那麼就表示這個cookie會在文件中保留多長

時間,到了這個時間以後,瀏覽器就會自動銷燬這個cookie

設置cookie:

 

public class SetCookieServlet extends HttpServlet{ protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //建立⼀個Cookie的實例 Cookie cookie = new Cookie("userId","10001"); //將cookie對象設置到響應對象中 response.addCookie(cookie); System.out.println("成功設置 cookie"); } } 

 

獲取cookie

public class GetCookieServlet extends HttpServlet{ @Override protected void service(HttpServletRequest request, HttpServletResponse repsonse) throws ServletException, IOException { //cookie是經過request對象來獲得的 //從請求中能夠獲取多個cookie對象 Cookie[] cookies = request.getCookies(); for (Cookie cookie : cookies) { //判斷cookie,只獲取name爲userId 的cookie對象 if("userId".equals(cookie.getName())) { System.out.println(cookie.getValue()); } } } } 

cookie保存中文 :

在保存cookie的時候若是須要保存中⽂,那麼中⽂信息
須要通過編碼後才能夠寫⼊cookie
示例代碼:
編碼使⽤URLEncoder

String str = URLEncoder.encode("張三", "utf-8"); Cookie cookie = new Cookie("userName", str); 

 解碼使⽤URLDecoder :

String str = URLDecoder.decode(cookie.getValue(),"utf-8"); System.out.println(str); 

 

 

設置cookie的存活時間:

示例代碼:

 

//設置爲0表示⽴即刪除cookie cookie.setMaxAge(0); //設置爲正數表示cookie在cookie⽂件的存活時間, 單位:秒 cookie.setMaxAge(5); //設置爲-1表示cookie只保留在瀏覽器器的進程中, 關閉瀏覽器以後會銷燬cookie cookie.setMaxAge(-1); 

 

4.4.2 Session

Session是基於服務端來保存用戶的信息,這個是和cookie最大的區別。不一樣的客服端在請求的服務器的時候,服務器會爲每個客服端建立一個

Session對象並保存在服務器端,Session對象是每個客服端所獨有的,相互之間不能訪問。服務器爲了區別不一樣的Session屬於哪個客戶端,所以Session

對象也有一個惟一標識,叫作SessionID.而這個SessionID是以cookie的機制保存在客戶端瀏覽器。每次請求的時候,瀏覽器都會把這個SessionID帶回服務端,服務端

根據這個SessionID就能夠找到對應的Session對象

示例代碼:

 

public class SessionServlet extends HttpServlet{ @Override protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //HttpSession對象是在第⼀次調⽤ request的getSession()⽅法時纔會建立 //注意: getSession()的⽅法會先判斷之 前是否爲客戶端建立了session實例, //若是建立了,則使⽤以前建立好的 Session對象,沒有則建立⼀個新的Session HttpSession session = request.getSession(); //建立HttpSession的同時,會建立⼀個惟 ⼀的標識SessionID //這個sessionId會保存在瀏覽器的cookie 中,每次請求會帶回這個id找到相應的session對象 String sessionId = session.getId(); System.out.println(sessionId); } }

 

Session的生命週期:Session是保存在瀏覽器的cookie中,可是不會寫入cookie文件中,這也就是表示當關閉瀏覽器以後,Sessionid就會銷燬,Sessionid銷燬以後,服務端

的Session就沒有如何做用了,可是,服務器並不會馬上銷燬這個Session對象,至於何時銷燬是由服務器本身決定的,除非咱們手動調用了Session.invalidate()

方法,服務器就會馬上銷燬這個session實例

例如:

HttpSession session = request.getSession();
//⽴即銷燬session
session.invalidate();

二、Session默認也有存活時間,服務器建立session的時候,session設置默認的存活時間爲30分鐘,若是在30分鐘以內,

客戶端沒有發起任何請求到服務器來到服務器,那麼服務器就會銷燬這個Session對象,咱們也能夠設置Session的存活時間,

能夠爲當前的Session設置,也能夠爲全局(服務端全部的Session)的Session設置

設置當前的Session的超時(存活)時間:

 

HttpSession session = request.getSession(); //設置當前Session的存活時間,單位:秒 session.setMaxInactiveInterval(3600);

 

設置全局的Session存活時間:

web.xml中進⾏設置 :

 

<!-- 設置全局Session的存活時間,單位:分鐘 --> <session-config> <session-timeout>60</session-timeout> </session-config>

 

Session的做用域:

當咱們須要一些數據信息出入Session的時候,就須要操做Session做用域(SessionScope),它和請求做用域相似,也有相應的setAttribute和getAttribute

的方法,只不過Session做用域的範圍要比請求做用域更寬,請求的做用域在一次請求響應以後,就會消失,(由於響應以後請求對象就會銷燬)。而Session

對象只要瀏覽器不關閉或者Session對象會一直駐留在服務器端,所以無論從新請求多少次仍是轉發和重定向,均可以重Session中獲取以前保存的數據信息

代碼示例:

 

User user = new User(); user.setUid("1001"); user.setUserName("wangl"); HttpSession session = request.getSession(); //將數據保存在會話做⽤域中 session.setAttribute("user", user);

重回復做用域中取值:

 

HttpSession session = request.getSession(); //取值 User user = (Object)session.getAttribute("user");


URL的重寫:

瀏覽器是能夠禁⽤cookie的,⼀旦禁⽤了cookie,那麼SessionId將⽆法寫⼊cookie的緩存中,這樣就致使⽆
法實現會話跟蹤了,所以解決辦法就是使⽤URL重寫。URL重寫的⽬的就是把SessionId在放在請求URL地址
的後⾯提交回服務器(相似GET請求後⾯帶上參數,⽽這個參數就是⼀個SessionId),服務器會解析這個
URL的地址並獲得SessionId

代碼示例:

 

//重寫請求的URL地址,這個地址後⾯會⾃動帶上 SessionId String url = response.encodeRedirectURL("getSession"); //重定向URL response.sendRedirect(url);

 

瀏覽器地址演示:

http://localhost:8080/ch07/getSession;jsess ionid=6F1BA8C92D7E5D7CC479ED8DD30D3ED0

 

4.11 Servlet上下文

web容器在啓動時會爲每個web應用建立惟一的上下文對象,這個對象就是Servlet上下文對象(ServletContext),這個上下文對象能夠理解爲是當前項目的一個共享內存空間,爲項目中的全部Servlet提供一個共享的區域。

經常使用API:

getContextPath() 獲取項目的相對路徑
getRealPath(String path) 獲取項目的絕對路徑
getInitParameter(String name) 獲取上下文的初始化參數(web.xml中配置的)
setAttribute(String name, String value) 將數據放入上下文做用域
getAttribute(String name) 從上下文做用域中去獲取數據

 

 

 

 

 

 



上下文做用域:

上下文做用域是爲當前項目全部Servlet提供的一個共享內存區域,能夠將須要的數據信息保存在做用域中。這個做用域的的範圍是最大的,只要容器沒有中止,它就會一直存在。

三種做用域:

結合前面所學的做用域,那麼一共有三個,分別是:請求做用域,會話做用域,上下文做用域。

範圍從小到大來劃分:

請求做用域>會話做用域>上下文做用域

4.12 過濾器

過濾器能夠在請求到達servlet以前和servlet響應客戶端以前進行攔截,至關於一個攔截器

主要用於進行一些請求和響應的預處理操做,一般用的場景有限制權限的控制、統一字符編碼

4.12.1編寫過濾器

要實現一個過濾器必需要實現一個Filter接口,只有實現了這個接口的類才稱之爲過濾器

示例代碼:

public class DemoFilter implements Filter { ... }

 

web.xml配置過濾器:
<filter> <filter-name>demoFilter</filter-name> <filter-class>edu.nf.ch09.filter.DemoFilter</filter-class> <!-- 初始化參數 --> <init-param> <param-name>param</param-name> <param-value>hello</param-value> </init-param> </filter> <filter-mapping> <filter-name>demoFilter</filter-name> <!-- 什麼請求能夠通過此過濾器,/*表示全部請求 --> <url-pattern>/*</url-pattern> </filter-mapping>

 4.12.2過濾器的生命週期

與servlet相似,Filter一樣也是容器負責建立和銷燬,與servlet的區別在於,容器會在啓動的時候最早建立全部

的顧慮器,並執行init方法進行初始化

生命週期的方法:

方法 說明
init 初始化方法,容器啓動時執行一次
doFilter 請求過濾方法,決定請求是否放行
destroy 容器銷燬過濾器以前執行的方法
 
 
 
 
 
 
 
 
 


 
 
 
實例代碼:
public class DemoFilter implements Filter{ @Override public void destroy() { System.out.println("準備銷燬DemoFilter"); }
 @Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { //FilterChain表示一個過濾鏈對象,由於過濾器可能會存在多個 //同時這個對象將決定是否放行當前請求, //放行的話則請求會繼續到達下一個過濾器或者servlet中 System.out.println("請求通過DemoFileer..放行"); chain.doFilter(request, response); System.out.println("響應前通過DemoFilter..."); } @Override public void init(FilterConfig config) throws ServletException { String name = config.getInitParameter("param"); System.out.println("初始化DemoFilter,獲取初始化參數:"+name); } }

4.12.3 過濾鏈

在一個web項目中可能存在多個過濾器,當有多個過濾器存在的時候就會造成一個過濾鏈。請求會按照過濾器鏈的順序一直傳遞下去,最終到達某個Servlet來處理請求。(注意:過濾鏈的順序是按照web.xml中的前後配置順序決定的)

配置示例:

<!-- 按前後順序配置 --> <!-- 配置第一個過濾器 --> <filter> <filter-name>firstFilter</filter-name> <filter-class>edu.nf.ch09.filter.FirstFilter</filter-class> </filter> <filter-mapping> <filter-name>firstFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <!-- 配置第二個過濾器--> <filter> <filter-name>secondFilter</filter-name> <filter-class>edu.nf.ch09.filter.SecondFilter</filter-class> </filter> <filter-mapping> <filter-name>secondFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>

 

 

4.13 監聽器

監聽器用於監聽對象的上的事件發生,在Servlet中監聽器主要監聽請求對象、會話對象、上下文對象以及監聽這些對象的做用域操做。JavaEE爲咱們提供了一系列的監聽器接口,開發時按需實現相應的接口便可。

4.13.1 監聽做做用域對象的建立與銷燬

監聽器 說明
ServletRequestListener 監聽請求對象的建立和銷燬
HttpSesisonListener 監聽會話對象的建立和銷燬
ServletContextListener 監聽Servlet上下文對象的建立和銷燬
 
 
 
 
 
 
 
 

 

1.請求對象監聽器

public class DemoRequestListener implements ServletRequestListener{ /** * 當請求對象銷燬後容器執行此方法 * 銷燬方法中一樣也有一個ServletRequestEvent事件對象 */ @Override public void requestDestroyed(ServletRequestEvent event) { //經過這個事件對象就能夠獲取當前的請求對象 HttpServletRequest request = (HttpServletRequest)event.getServletRequest(); System.out.println("銷燬請求對象..."+request); } /** * 當請求對象建立以後容器調用此方法 * ServletRequestEvent這個參數就是一個事件對象 */ @Override public void requestInitialized(ServletRequestEvent event) { //經過這個事件對象就能夠獲取當前的請求對象 HttpServletRequest request = (HttpServletRequest)event.getServletRequest(); System.out.println("初始化了請求對象..."+request); } }

 

 
web.xml配置
<!-- 配置監聽器 --> <listener> <!-- 指定監聽器的完整類名 --> <listener-class>edu.nf.ch10.listener.DemoRequestListener</listener-class> </listener>

 

 
二、會話監聽器
public class DemoSessionListener implements HttpSessionListener{ /** * 監聽HttpSession對象的建立 * HttpSessionEvent參數是一個事件對象 * 經過它能夠得到當前的HttpSession */ @Override public void sessionCreated(HttpSessionEvent event) { HttpSession session = event.getSession(); System.out.println("建立了Session對象"+session); } /** * 監聽HttpSession對象的銷燬 */ @Override public void sessionDestroyed(HttpSessionEvent event) { HttpSession session = event.getSession(); System.out.println("銷燬了Session對象"+session); } }

 

注意:當第一次調用了request.getSesison()方法建立Session時,監聽器纔會起做用。

web.xml配置

<listener> <!-- 指定監聽器的完整類名 --> <listener-class>edu.nf.ch10.listener.DemoSessionListener</listener-class> </listener>

 

3.Servlet上下文監聽器
public class DemoContextListener implements ServletContextListener{ /** * 監聽ServletContext的銷燬 */ @Override public void contextDestroyed(ServletContextEvent event) { //經過事件對象獲取ServletContext ServletContext sc = event.getServletContext(); System.out.println("銷燬了ServletContext對象..."+sc); } /** * 監聽SerlvetContext的建立 */ @Override public void contextInitialized(ServletContextEvent event) { //經過事件對象獲取ServletContext ServletContext sc = event.getServletContext(); System.out.println("建立了ServletContext對象..."+sc); } }

 

配置web.xml
<listener> <!-- 指定監聽器的完整類名 --> <listener-class>edu.nf.ch10.listener.DemoContextListener</listener-class> </listener>

 4.13.2 監聽做用域的操做

監聽器 說明
ServletRequestAttributeListener 監聽請求做用域的操做
HttpSessionAttributeListener 監聽會話做用域的操做
ServletContextAttributeListener 監聽Servlet上下文做用域的操做

 

 

 

 

 

 

 

示例代碼:這裏以HttpSessionAttributeListener說明,其餘做用於監聽器用法類似。

public class DemoSessionAttributeListener implements HttpSessionAttributeListener{ /** * 當有數據添加到會話做用域時,執行此方法 */ @Override public void attributeAdded(HttpSessionBindingEvent event) { //獲取存入做用域的鍵和值 System.out.println("存入會話做用域..."+event.getName() + " : " + event.getValue()); } /** * 當從會話做用域移除數據時,執行此方法 */ @Override public void attributeRemoved(HttpSessionBindingEvent event) { System.out.println("移除會話做用域..."+event.getName() + " : " + event.getValue()); } /** * 當替換了會話做用域中的某個數據時,執行此方法 */ @Override public void attributeReplaced(HttpSessionBindingEvent event) { HttpSession session = event.getSession(); //從session中獲取的是替換以後的值 System.out.println("替換的值: "+session.getAttribute("userName").toString()); //注意:這裏event.getValue()獲取到的是替換以前的值 System.out.println("替換會話做用域..."+event.getName() + " : " + event.getValue()); } }

 

 web.xml 配置

<listener> <!-- 指定監聽器的完整類名 --> <listener-class>edu.nf.ch10.listener.DemoSessionAttributeListener</listener-class> </listener>

4.14 註解配置

Servlet3.0開始提供了一系列的註解來配置Servlet、Fiilter、Listener等等。這種方式能夠極大的簡化在開發中大量的xml的配置。

從這個版本開始,web.xml能夠再也不須要,使用相關的註解一樣能夠完成相應的配置。徹底配置,

 

註解 說明
@WebServlet 這個註解標識在類上,用於配置Servlet。例如:@WebServlet(name="hello", urlPatterns="/hello") 也可簡化配置@WebServlet("/hello")
@WebFilter 這個註解標識在類上,用於配置Filter。例如:@WebFilter(filterName="encode",urlPatterns="/") 也可簡化配置@WebFilter("/"),
@WebListener 這個註解標識在類上,用於配置監聽器

 

 
 
 
 
 
 
 
 
 
 
 
 

5. JSP基礎

5.1 簡介

JSP全名爲java Server Pages,中文名叫java服務器頁面,是一種動態頁面技術,而HTML是屬於靜態頁面。JSP

能夠在HTML中嵌入java腳本代碼,由於JSP本質上仍是一個Servlet,所以JSP也必須依賴於web容器才能運行

JSP的出現並非爲了去掉Servlet,而是簡化了Servlet的工做,將Servlet中繁瑣的視圖呈現代碼脫離出來,交給

JSP來完成,讓Servlet專一於請求的處理,全部在開發中一般將jsp和Servlet結合一塊兒使用

5.2JSP引擎

因爲JSP本質上就是一個Servlet,那麼JSP文件轉義成一個Servlet的java源文件,而後經過javac將這個源文件編譯成class

字節碼文件並裝載到JVM中執行,JSP引擎的核心類是JSPServlet,位於Jasper.jar文件張總,而且在Tomcat的web

.xml中也默認就配置好了這個類(JSPServlet也是一個servlet,所以凡是以「.jsp」結尾的請求都會先通過JSPServlet

,那麼這個引擎就能夠開始工做了。一般引擎轉義和編譯後的文件放在容器的work工做目錄中)

注意:若是第一次訪問jsp文件的時候,因爲work目錄中並不存在源文件和字節碼文件,jsp引擎就必須完成這兩個工做,

所以,有可能在第一次訪問jsp時會比較緩慢,當字節碼編譯出來加載後,第二次訪問時的速度就會很快了

5.3JSP的三大元素

語法:<%@  %>

指令 說明
page指令 用於設置JSP頁面的相關信息以及編碼
include指令 用於靜態包含其餘的JSP頁面代碼,所謂靜態包含,就是在編譯期,將另外的JSP頁面的代碼合併到當前的JSP中,最終只會產生一個Java源文件
taglib指令 這個指令用於引入標籤庫
 
 
 
 
 
 
 
 
 

5.3.2 動做元素

語法:jsp:xxx

動做 說明
include 動態包含其餘JSP頁面的內容,所謂的動態包含是指在編譯期將不一樣的JSP文件轉義成不一樣的Java源文件,而後在運行時纔將目標內容包含到當前的JSP頁面中
forward 至關於Servlet中的轉發,轉發到其餘的JSP頁面或者Servlet
param 用於傳遞參數,一般結合其餘的動做一塊兒使用,例如轉發時須要提交一些而外的參數
useBean 用於在JSP頁面中使用JavaBean對象,一般結合setProperty和getProperty來使用,完成bean對象的賦值和取值操做
 
 
 
 
 
 
 
 





5.3.3 腳本元素          

腳本元素主要就是在JSP中嵌入Java腳本代碼,包括聲明、表達式、Java腳本

聲明語法:<%! %>

表達式: <%= %>

Java腳本: <% %>

代碼實例:

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Insert title here</title> </head> <body> <%-- 聲明變量和方法,這裏聲明的變量a是實例變量 --%> <%! int a = 10; public void say(){ System.out.println("hello"); } %> <%-- 表達式,注意:表達式後面是不容許有;號結束的 --%> 3 + 1 = <%=3+1%><br/> <%-- Java腳本,腳本代碼最終會生成在servlet中的service方法中做爲代碼片斷 --%> <table border="1"> <tr> <th>Name</th> <th>Age</th> </tr> <% for(int i=0;i<5;i++){%> <tr> <td>user<%=i%></td> <td><%=10+i%></td> </tr> <%}%> </table> </body> </html>

 

 

5.4 JSP內置對象

內置對象,是在容器運行時將建立好的9個對象內嵌在JSP中,在JSP裏能夠直接拿來使用的對象

對象 說明
out 字符流輸出對象
config 等同於Servlet中的ServletConfig
page 表示當前JSP頁面
request 等同於Servlet中的HttpServletRequest
response 等同於Servlet中的HttpServletResponse
session 等同於Servlet中的HttpSession
application 等同於Servlet中的ServletContext
pageContext 表示當前JSP頁面的上下文對象
exception 表示當前JSP中的異常對象
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Insert title here</title> </head> <body> <%-- 經常使用內置對象 --%> <% //使用request,API使用同HttpServletRequest同樣 request.getParameter("userName"); request.setAttribute("user", "user1"); request.getAttribute("user"); //使用session,API使用等同於HttpSession session.setAttribute("user", "user2"); session.getAttribute("user"); session.getId(); //使用response //response.sendRedirect("demo.jsp"); //out對象,等同於字符輸出流對象,在JSP頁面輸出相關內容 out.println("hello world"); //這個是輸出在控制中 System.out.println("hello"); //使用application,等同於ServletContext application.setAttribute("userName", "user3"); //pageContext使用 //從pageContext中獲取相關的其餘對象 HttpServletRequest req = (HttpServletRequest)pageContext.getRequest(); HttpServletResponse res = (HttpServletResponse)pageContext.getResponse(); HttpSession ses = pageContext.getSession(); ServletConfig conf = pageContext.getServletConfig(); ServletContext sc = pageContext.getServletContext(); //也能夠經過pageContext來統一設置不一樣的做用域 //第三個參數表示要放入到哪一個做用域,是一個int類型的參數 //1表明page做用域(當前頁面有效) //2表明請求做用域 //3表明會話做用域 //4表明上下文做用域 pageContext.setAttribute("userName", "zhangsan", 2); //也能夠指定中哪一個做用域取出相應的值 String name = (String)pageContext.getAttribute("userName", 2); out.println(name); %> </body> </html>

 

5.5 EL表達式

EL(Expression Language),全稱叫作表達式語言,是JSP2.0推出的一種技術。主要簡化了在JSP中使用Java腳本表達式。EL表達式的特色在於使用簡單,支持四則運算、邏輯運算等,而且還能夠對Servlet API中的對象進行數據訪問。EL的語法: ${expression}

運算:

示例 結果
${1+1} 2
${2*2} 4
${1==1} true
${2>5} false
其餘 ...

 

 

 

 

 

 

 



數據訪問:

1.使用「.」來訪問

示例 說明
${param.參數名} 獲取請求參數的值,至關於使用request.getParameter()方法
${requestScope.xxx} 從請求做用域中訪問數據
${sessionScope.xxx} 從會話做用域中訪問數據
${applicationScope.xxx} 從上下文做用域中訪問數據
${xxx} 不指定做用域範圍時,默認按照做用域範圍從小到大的順序自動查找
其餘 ...

 

 

 

 

 

 

 
 







2.使用"[]"來訪問
示例 說明
${requestScope[「userName」]} 從請求做用域中取值
${sessionScope[「userName」]} 從會話做用域取值
其餘... 同上
 
 
 
 
 
 
 
 
 
 


注意:一般使用"[]"來訪問數據的時候,主要是訪問一些特殊的名稱,例如:request.setAttribute("user.userName")

這種方式若是使用${requestScope.user.userName}是訪問不到的,應該改成

${requestScope["user.userName"]}來訪問

5.6 JSTL核心標籤庫

JSTL是JSP中的標準標籤庫,主要用於取代JSP中大量的Java腳本代碼,讓頁面看起來更趨向於HTML。使用也很簡單,一般結合EL表達式一塊兒使用

示例:

核心標籤庫(core) 說明
c:out 輸出標籤
c:set 聲明某個變量並存入指定的做用域
c:redirect 重定向標籤
c:if 條件判斷
c:forEach 循環標籤
其餘 ...
 
 
 
 
 
 
 
 
 
 
 





備註:其餘標籤庫請參閱相關官方文檔
 
 
 
 
 
 

 5.3.

相關文章
相關標籤/搜索