Javaweb 筆記

Java web筆記

一、HTTP協(xié)議

HTTP(超文本傳輸協(xié)議)熏版,它是一種主流B/S架構(gòu)中應(yīng)用的通信協(xié)議咖驮。具有以下特點(diǎn):

1、無(wú)狀態(tài)

服務(wù)端不會(huì)記錄客戶(hù)端每次提交的請(qǐng)求启妹,服務(wù)器一旦相應(yīng)客戶(hù)端之后筛严,就會(huì)結(jié)束本次的通信過(guò)程∪拿祝客戶(hù)端下一次的請(qǐng)求是一個(gè)新的 連接脑漫,和上一次通信沒(méi)有任何關(guān)系。

2咙崎、簡(jiǎn)單靈活

HTTP是基于請(qǐng)求(request)和響應(yīng)(response)的模型

3、支持客戶(hù)端與服務(wù)端

支持主流的B/S架構(gòu)的通信以及C/S架構(gòu)的通信吨拍。

注意:C/S架構(gòu)可選的協(xié)議有多種褪猛,例如:TCP/IP,UDP,HTTP

? 而B(niǎo)/S架構(gòu)通常只支持HTTP協(xié)議

二、服務(wù)器

1羹饰、概念

服務(wù)器通常由硬件和軟件部分構(gòu)成伊滋,統(tǒng)一對(duì)用戶(hù)提供多種不同的服務(wù)。

1队秩、硬件:包括響應(yīng)的CPU笑旺、內(nèi)存、磁盤(pán)等等

2馍资、軟件:包括操作系統(tǒng)筒主、運(yùn)行環(huán)境、服務(wù)器軟件鸟蟹、數(shù)據(jù)庫(kù)等等

2乌妙、web服務(wù)器

web服務(wù)器是提供服務(wù)端程序運(yùn)行的一個(gè)環(huán)境,它本身也是一個(gè)軟件建钥。

例如:將我們編寫(xiě)HTML文件放入到web服務(wù)器中藤韵,那么外界就可以通過(guò)瀏覽器訪問(wèn)我們的html頁(yè)面

常見(jiàn)的web服務(wù)器有Apache,Tomcat熊经、Jetty泽艘、Nginx等等欲险。

而Tomcat、Jetty這些web服務(wù)器更準(zhǔn)確的說(shuō)是一個(gè)Servlet容器匹涮。

三天试、JavaWeb項(xiàng)目結(jié)構(gòu)

項(xiàng)目根目錄,例如:myweb焕盟、ch01 通常存放靜態(tài)資源文件(如:html等等)

WEB-INF 這個(gè)目錄是當(dāng)前項(xiàng)目私有的一個(gè)文件夾秋秤,只能提供給項(xiàng)目?jī)?nèi)部訪問(wèn),對(duì)于客戶(hù)端來(lái)說(shuō)是訪問(wèn)不到了脚翘,通常這個(gè)目錄下存放的是Java源代碼灼卢、編譯后的字節(jié)碼文件以及Servlet的核心配置文件web.xml

src 存放java源代碼的目錄

classes 存放編譯后的字節(jié)碼文件

lib lib目錄存放當(dāng)前項(xiàng)目所需要的jar文件

JSP 用于存放JSP動(dòng)態(tài)頁(yè)面

web.xml 項(xiàng)目的配置文件,用于配置Servlet的請(qǐng)求映射来农、過(guò)濾器鞋真、監(jiān)聽(tīng)器等等信息。每一個(gè)web項(xiàng)目都對(duì)應(yīng)一個(gè)web.xml配置文件

META-INF 配置應(yīng)用程序沃于、擴(kuò)展程序涩咖、類(lèi)加載服務(wù)等等

四、Servlet基礎(chǔ)

1繁莹、什么是Servlet

Servlet是JavaEE中標(biāo)準(zhǔn)組件檩互,專(zhuān)門(mén)用于處理客戶(hù)端提交的HTTP請(qǐng)求。并且它必須依賴(lài)于Servlet容器才可以運(yùn)行(Tomcat就是一個(gè)標(biāo)準(zhǔn)的Servlet容器)咨演,Servlet容器給Servlet提供一個(gè)運(yùn)行環(huán)境闸昨,所以Servlet組件必須要這個(gè)環(huán)境中可以運(yùn)行,而不能脫離這個(gè)環(huán)境而單獨(dú)執(zhí)行薄风。因?yàn)镾ervlet的實(shí)例是由容器創(chuàng)建和銷(xiāo)毀的饵较,并不是通過(guò)我們平常使用的new關(guān)鍵創(chuàng)建出來(lái)。

2遭赂、開(kāi)發(fā)一個(gè)Servlet的步驟

1.編寫(xiě)一個(gè)類(lèi)循诉,然后繼承HttpServlet這個(gè)父類(lèi)

2.重寫(xiě)父類(lèi)的service方法,這個(gè)就是專(zhuān)門(mén)處理客戶(hù)端請(qǐng)求的方法撇他,這個(gè)方法有兩個(gè)參數(shù)(HttpServletRequest茄猫,HttpServletResponse),同時(shí)這個(gè)方法會(huì)拋出兩個(gè)異常(ServletException逆粹,IOException)

按 Ctrl+C 復(fù)制代碼

import javax.servlet.*;

import javax.servlet.http.*;

import java.io.*;

//要讓當(dāng)前的類(lèi)是一個(gè)Servlet募疮,必須繼承HttpServlet

public class HelloServlet extends HttpServlet{

? ? //重寫(xiě)父類(lèi)的service方法,處理客戶(hù)端請(qǐng)求,

? ? //這個(gè)方法私有servlet容器去調(diào)用僻弹,

? ? //并且request和response參數(shù)都是由servlet容器傳遞進(jìn)來(lái)的

? ? public void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

? ? ? ? System.out.println("Hello Servlet");

? ? ? ? //響應(yīng)一些信息回饋給客戶(hù)端瀏覽器

? ? ? ? //1.設(shè)置要響應(yīng)的類(lèi)型阿浓,這里就響應(yīng)簡(jiǎn)單的html文本類(lèi)型

? ? ? ? //通過(guò)response參數(shù)來(lái)進(jìn)行設(shè)置,如:text/html,text/plain

? ? ? ? response.setContentType("text/html;charset=utf-8");

? ? ? ? //2.獲取輸出流并寫(xiě)回html數(shù)據(jù)

? ? ? ? response.getWriter().println("<h1>Hello Servlet</h1>");

? ? }

}

按 Ctrl+C 復(fù)制代碼

3.編譯Servlet,需要依賴(lài)servlet-api.jar文件

4.編寫(xiě)web.xml蹋绽,為servlet配置請(qǐng)求映射的URL

復(fù)制代碼

<?xml version="1.0" encoding="utf-8"?>

<!-- 配置根節(jié)點(diǎn) -->

<web-app>

? <!-- 配置servlet類(lèi) -->

? <servlet>

? ? ? ? <!-- 指定servlet的別名 -->

? ? ? ? <servlet-name>hello</servlet-name>

? ? ? ? <!-- 指定Servlet的完整類(lèi)名-->

? ? ? ? <servlet-class>HelloServlet</servlet-class>

? </servlet>

? <!-- 配置請(qǐng)求映射-->

? <servlet-mapping>

? ? ? ? ? <!-- 這里的servlet-name和上面的servlet-name要一一對(duì)應(yīng) -->

? ? ? ? <servlet-name>hello</servlet-name>

? ? ? ? <!-- 配置請(qǐng)求映射的url,必須以“/”開(kāi)頭-->

? ? ? ? <url-pattern>/test</url-pattern>

? </servlet-mapping>

</web-app>

復(fù)制代碼

5.將項(xiàng)目部署到Tomcat的webapps目錄中

3芭毙、servlet處理請(qǐng)求的流程

1.瀏覽器發(fā)起http的請(qǐng)求筋蓖,這個(gè)請(qǐng)求首先會(huì)被servlet容器(Tomcat)截獲,然后容器會(huì)根據(jù)web.xml文件中配置servlet的<url-pattern>來(lái)找到相應(yīng)的<servlet-name>這個(gè)別名退敦,然后再根據(jù)這個(gè)別名找到具體Servlet的類(lèi)粘咖,然后容器會(huì)創(chuàng)建這個(gè)Servlet類(lèi)的實(shí)例并調(diào)用Servlet方法來(lái)處理這個(gè)請(qǐng)求。

請(qǐng)求網(wǎng)頁(yè)地址: http://127.0.0.1:8080/ch02/test

4侈百、Servlet的生命周期

所謂的生命周期瓮下,就是從Servlet的創(chuàng)建一直到它銷(xiāo)毀的整個(gè)過(guò)程。并且它的 整個(gè)生命周期都是由Servlet容器(Tomcat)負(fù)責(zé)管理和維護(hù)的钝域。(補(bǔ)充:在Tomcat中讽坏,Servlet是以單實(shí)例多線程的方式處理客戶(hù)端請(qǐng)求)

4.1 Servlet對(duì)象創(chuàng)建的過(guò)程

當(dāng)?shù)谝淮握?qǐng)求某個(gè)Servlet的時(shí)候,容器會(huì)先查找之前有沒(méi)有創(chuàng)建過(guò)這個(gè)Servlet的實(shí)例例证,如果沒(méi)有則創(chuàng)建一個(gè)實(shí)例并緩存起來(lái)路呜。后續(xù) 所有請(qǐng)求這個(gè)Servlet的時(shí)候,都會(huì)使用這個(gè)緩存的對(duì)象來(lái)處理客戶(hù)端請(qǐng)求织咧。(注意“這里說(shuō)的是第一次請(qǐng)求時(shí)創(chuàng)建胀葱。另外一種情況則是在容器啟動(dòng)的時(shí)候就創(chuàng)建Servlet的實(shí)例,在web.xml中為Servlet指定<load-on-startup>配置笙蒙,這個(gè)配置的值是一個(gè)整形抵屿,數(shù)值越小,則初始化 的優(yōu)先級(jí)別越高)

4.2 生命周期方法

方法名 描述

init 在Servlet對(duì)象創(chuàng)建之后立即執(zhí)行的初始化方法捅位,且只執(zhí)行一次

service 核心的請(qǐng)求處理方法晌该,這個(gè)方法可以執(zhí)行多次

destroy 容器準(zhǔn)備銷(xiāo)毀Servlet實(shí)例之前執(zhí)行的方法,也是執(zhí)行一次

5绿渣、HTTP請(qǐng)求報(bào)文

5.1 請(qǐng)求報(bào)文

請(qǐng)求行:請(qǐng)求報(bào)文的第一行就是請(qǐng)求行。包括請(qǐng)求方法燕耿、請(qǐng)求URL地址中符、HTTP協(xié)議版本

請(qǐng)求頭:請(qǐng)求行之后的信息就是請(qǐng)求頭,它是以“名稱(chēng):內(nèi)容”的格式體現(xiàn)誉帅。主要包括服務(wù)器主機(jī)地址及端口號(hào)淀散、連接狀態(tài)、接收的數(shù)據(jù)類(lèi)型蚜锨、編碼档插、語(yǔ)言等等

請(qǐng)求體:請(qǐng)求頭結(jié)束之后會(huì)有一個(gè)空行,空行之后就是請(qǐng)求體的內(nèi)容亚再。通常使用POST提交的數(shù)據(jù)信息會(huì)存放在請(qǐng)求體中郭膛,然后傳遞給服務(wù)器。

5.2 響應(yīng)報(bào)文

狀態(tài)行:主要包括HTTP協(xié)議氛悬、響應(yīng)狀態(tài)碼(例如:200表示OK则剃,成功響應(yīng))

響應(yīng)頭:主要包括服務(wù)器信息耘柱、響應(yīng)的類(lèi)型及編碼、內(nèi)容的長(zhǎng)度棍现、響應(yīng)的時(shí)間等

響應(yīng)體:服務(wù)器將信息攜帶到響應(yīng)體中调煎,帶回客戶(hù)端。

6己肮、HTTP請(qǐng)求方法

在HTTP/1.1協(xié)議中士袄,請(qǐng)求方法主要包括8個(gè),下面列舉常用的請(qǐng)求方法進(jìn)行說(shuō)明谎僻。

請(qǐng)求方法 說(shuō)明

GET 向服務(wù)器請(qǐng)求指定的資源娄柳,并返回響應(yīng)主體。一般來(lái)說(shuō)GET方法應(yīng)該只用于數(shù)據(jù)的讀雀旮濉(類(lèi)似于查詢(xún))

POST 向指定的服務(wù)器提交數(shù)據(jù)(例如:表單數(shù)據(jù)的提交西土、文件上傳等),并且提交的數(shù)據(jù)會(huì)放入請(qǐng)求體中(類(lèi)似于新增)

PUT 向服務(wù)器提交數(shù)據(jù)鞍盗,但是和POST有所區(qū)別需了。如果服務(wù)器不存在此資源的時(shí)候,則執(zhí)行新增般甲,如果存在則執(zhí)行修改肋乍。(類(lèi)似于修改)

DELETE 根據(jù)uri的表示刪除服務(wù)器上的某個(gè)資源(類(lèi)似于刪除)

... ...

備注:GET與POST區(qū)別:

1.GET主要用于獲取數(shù)據(jù),POST用于提交數(shù)據(jù)敷存。

2.GET請(qǐng)求所帶的參數(shù)是放在請(qǐng)求行的url地址后面墓造,而POST這是放在請(qǐng)求體中。

3.通常瀏覽器會(huì)對(duì)GET請(qǐng)求的url長(zhǎng)度有所限制 锚烦,而POST通常在請(qǐng)求體中觅闽,可以提交更多的數(shù)據(jù)信息。

4.瀏覽器會(huì)對(duì)GET請(qǐng)求進(jìn)行緩存涮俄。

7蛉拙、Servlet的請(qǐng)求處理方法

方法 說(shuō)明

service 可以處理任何的請(qǐng)求類(lèi)型

doGet 處理對(duì)應(yīng)的GET請(qǐng)求

doPOST 處理對(duì)應(yīng)的POST請(qǐng)求

doPut 處理對(duì)應(yīng)的PUT請(qǐng)求

doDelete 處理對(duì)應(yīng)的DELETE請(qǐng)求

說(shuō)明:通過(guò)HttpServlet的源代碼得知,默認(rèn)的所有請(qǐng)求都會(huì)先經(jīng)過(guò)service方法彻亲,然后service方法根據(jù)請(qǐng)求的方法類(lèi)型判斷來(lái)決定交給doGet或者是doPOST方法來(lái)處理請(qǐng)求孕锄。如果子類(lèi)重寫(xiě)了service方法同時(shí)還重寫(xiě)了其他的doXxx的方法,那么只有service方法會(huì)處理請(qǐng)求苞尝,其他方法將失效畸肆。

8、請(qǐng)求和響應(yīng)對(duì)象

當(dāng)web容器調(diào)用某個(gè)Servlet的Service方法時(shí)宙址,會(huì)創(chuàng)建一個(gè)HTTPServletRequest和HTTPServletResponse對(duì)象作為參數(shù)傳入到這個(gè)方法中轴脐,那么我們可以通過(guò)HTTPServletRequest來(lái)獲取相關(guān)的請(qǐng)求內(nèi)容等,而響應(yīng)客戶(hù)端可以利用HttpServletResponse對(duì)象來(lái)完成。

8.1 HttpServletRequest常用API

方法 說(shuō)明

getParameter(String name) 獲取請(qǐng)求參數(shù)的值豁辉,根據(jù)請(qǐng)求參數(shù)的name指定

getParameterValues(String name) 獲取相同name的請(qǐng)求參數(shù)令野,返回的是字符串?dāng)?shù)組

getParameterMap() 獲取所有請(qǐng)求參數(shù),包括參數(shù)名稱(chēng)和值

getMethod() 獲取請(qǐng)求方法的類(lèi)型

getHeader(Stirng name) 根據(jù)請(qǐng)求頭的名稱(chēng)獲取響應(yīng)的信息

getRemoteAddr() 獲取遠(yuǎn)程客戶(hù)端的IP地址

getServletPath() 獲取Servlet的請(qǐng)求地址徽级,也就是url-pattern

getRequestURL() 獲取請(qǐng)求完整的URL地址

getRealPath(String path) 獲取項(xiàng)目的絕對(duì)路徑气破。(這個(gè)方法在request對(duì)象中已廢棄,建議通過(guò)ServletContext對(duì)象獲炔颓馈)

其他 ...

復(fù)制代碼

public void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{

? ? ? ? System.out.println("---------------獲取參數(shù)值----------------");

? ? ? ? //獲取請(qǐng)求參數(shù),根據(jù)請(qǐng)求的參數(shù)名

? ? ? ? String name = request.getParameter("uname");

? ? ? ? String age = request.getParameter("age");

? ? ? ? System.out.println(name);

? ? ? ? System.out.println(age);

? ? ? ? //獲取相同參數(shù)名的參數(shù)

? ? ? ? String[] addrs = request.getParameterValues("address");

? ? ? ? for (String addr : addrs) {

? ? ? ? ? ? System.out.println(addr);

? ? ? ? }

? ? ? ? System.out.println("--------------獲取參數(shù)名---------------");

? ? ? ? //獲取所有的參數(shù)名

? ? ? ? Enumeration<String> es = request.getParameterNames();

? ? ? ? //枚舉使用迭代器來(lái)循環(huán)遍歷

? ? ? ? while(es.hasMoreElements()) {

? ? ? ? ? ? String paramName = es.nextElement();

? ? ? ? ? ? System.out.println(paramName);

? ? ? ? }

? ? ? ? System.out.println("---------------獲取所有的參數(shù)名和參數(shù)值-------------------");

? ? ? ? //map泛型的第一個(gè)參數(shù)表示請(qǐng)求的參數(shù)名稱(chēng)现使,第二個(gè)參數(shù)是請(qǐng)求的參數(shù)值,值可以有多個(gè)旷痕,所以是數(shù)組

? ? ? ? Map<String,String[]> map = request.getParameterMap();

? ? ? ? //map的key對(duì)應(yīng)的是參數(shù)名碳锈,value就是參數(shù)的值

? ? ? ? for (String key : map.keySet()) {

? ? ? ? ? ? System.out.println("參數(shù)名:" + key);

? ? ? ? ? ? System.out.println("參數(shù)值: ");

? ? ? ? ? ? String[] values = (String[])map.get(key);

? ? ? ? ? ? for (String value : values) {

? ? ? ? ? ? ? ? System.out.println(value);

? ? ? ? ? ? }

? ? ? ? ? ? System.out.println("~~~~~~~~~~~");

? ? ? ? }

? ? ? ? System.out.println("-------------獲取客戶(hù)端的請(qǐng)求方法--------------");

? ? ? ? String method = request.getMethod();

? ? ? ? System.out.println("請(qǐng)求方法:" + method);

? ? ? ? System.out.println("--------------獲取請(qǐng)求頭部的信息---------------");

? ? ? ? String header = request.getHeader("Host");

? ? ? ? System.out.println("請(qǐng)求頭信息:" + header);

? ? ? ? System.out.println("--------------獲取遠(yuǎn)程客戶(hù)端的IP地址--------------");

? ? ? ? String addr = request.getRemoteAddr();

? ? ? ? System.out.println("客戶(hù)端的IP地址" + addr);

? ? ? ? System.out.println("------------獲取Servlet的url-pattern---------------");

? ? ? ? String servletPath = request.getServletPath();

? ? ? ? System.out.println("url-pattern: " + servletPath);

? ? ? ? System.out.println("------------獲取請(qǐng)求的完整URL---------------------------");

? ? ? ? String url = request.getRequestURL().toString();

? ? ? ? System.out.println(url);

? ? ? ? System.out.println("-------------獲取項(xiàng)目的絕對(duì)路徑------------------");

? ? ? ? String path = request.getServletContext().getRealPath("/");

? ? ? ? System.out.println(path);

? ? }

復(fù)制代碼

8.2 HttpServletResponse常用API

方法 說(shuō)明

setContentType(String str) 設(shè)置響應(yīng)內(nèi)容的類(lèi)型及編碼

getWriter() 獲取響應(yīng)字符輸出流

getOutputStream() 獲取字節(jié)輸出流

setHeader(String name,String value) 設(shè)置響應(yīng)頭信息,如果存在響應(yīng)頭信息欺抗,則執(zhí)行更新

addHeader(String name,String value) 設(shè)置響應(yīng)頭售碳,不管存不存在都會(huì)新加入一個(gè)

setStatus(int code) 設(shè)置響應(yīng)狀態(tài)碼

其他 ...

復(fù)制代碼

public void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

? ? ? ? //設(shè)置響應(yīng)的內(nèi)容類(lèi)型及編碼,包括(text/html,text/plain,application/json)

? ? ? ? response.setContentType("text/html;charset=utf-8");

? ? ? ? //設(shè)置響應(yīng)頭信息

? ? ? ? response.addHeader("myheader", "hello header");

? ? ? ? response.addHeader("myheader", "my servlet");

? ? ? ? //設(shè)置響應(yīng)的狀態(tài)碼

? ? ? ? response.setStatus(200);

? ? ? ? //獲取字節(jié)輸出流

? ? ? ? OutputStream os = response.getOutputStream();

? ? ? ? //獲取響應(yīng)的字符輸出流

? ? ? ? PrintWriter pw = response.getWriter();

? ? ? ? pw.println("<html>");

? ? ? ? pw.println("<head><title>index</title></head>");

? ? ? ? pw.println("<body>");

? ? ? ? pw.println("<h3>Hello Servlet</h3>");

? ? ? ? pw.println("</body>");

? ? ? ? pw.println("</html>");


? ? }

復(fù)制代碼

8.3 常見(jiàn)的響應(yīng)狀態(tài)碼

狀態(tài)碼 說(shuō)明

200 請(qǐng)求成功

401 禁止訪問(wèn),未授權(quán)

404 找不到請(qǐng)求的資源

405 請(qǐng)求的行的方法不被支持

500 服務(wù)器內(nèi)部錯(cuò)誤

其他 ...

9绞呈、Servlet之間的通信

9.1 轉(zhuǎn)發(fā)

所謂轉(zhuǎn)發(fā)贸人,就是在多個(gè)Servlet之間共享請(qǐng)求和響應(yīng)對(duì)象,所有參與轉(zhuǎn)發(fā)過(guò)程的Servlet都可以獲取同一個(gè)請(qǐng)求對(duì)象的信息佃声。在Servlet的API中艺智,轉(zhuǎn)發(fā)的操作是有HttpServletRequest對(duì)象完成的。

示例代碼:

復(fù)制代碼

public class ServletA extends HttpServlet{


? ? public void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{

? ? ? ? //獲取頁(yè)面提交的參數(shù)

? ? ? ? String name = request.getParameter("userName");


? ? ? ? //轉(zhuǎn)發(fā)由HttpServletRequest完成

? ? ? ? //第一步先獲取一個(gè)請(qǐng)求轉(zhuǎn)發(fā)器RequestDispatcher

? ? ? ? //獲取請(qǐng)求轉(zhuǎn)發(fā)器的同時(shí)要告訴轉(zhuǎn)發(fā)器轉(zhuǎn)發(fā)到哪里圾亏,轉(zhuǎn)發(fā)給誰(shuí)

? ? ? ? //如果要轉(zhuǎn)發(fā)給ServletB十拣,那么就是對(duì)應(yīng)ServletB的url-pattern

? ? ? ? RequestDispatcher rd = request.getRequestDispatcher("servletB");

? ? ? ? //調(diào)用轉(zhuǎn)發(fā)器的forward方法執(zhí)行轉(zhuǎn)發(fā),同時(shí)將request和response對(duì)象一并轉(zhuǎn)發(fā)ServletB

? ? ? ? rd.forward(request, response);


? ? }

}

復(fù)制代碼

復(fù)制代碼

public class ServletB extends HttpServlet{

? ? @Override

? ? protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {


? ? ? ? //這里在同一個(gè)請(qǐng)求中再次獲取頁(yè)面的參數(shù)

? ? ? ? String name = request.getParameter("userName");

? ? ? ? System.out.println("ServletB獲取請(qǐng)求參數(shù):"+name);

? ? }

}

復(fù)制代碼

轉(zhuǎn)發(fā)的特點(diǎn):

1、URL地址欄不會(huì)發(fā)生改變

2志鹃、轉(zhuǎn)發(fā)的過(guò)程是在服務(wù)端自動(dòng)完成

請(qǐng)求作用域:

每一個(gè)請(qǐng)求對(duì)象都有一個(gè)獨(dú)立的空間夭问,這個(gè)空間我們稱(chēng)之為請(qǐng)求作用域(RequestScope),可以為當(dāng)前這個(gè)請(qǐng)求攜帶額外的一些數(shù)據(jù)信息曹铃,這些信息同樣可以在多個(gè)Servlet之間進(jìn)行共享甲喝。

示例代碼:

復(fù)制代碼

public class ServletA extends HttpServlet{


? ? public void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{


? ? ? ? //在ServletA中為request對(duì)象設(shè)置請(qǐng)求作用域

? ? ? ? request.setAttribute("age", 35)

? ? }

}

復(fù)制代碼

復(fù)制代碼

public class ServletB extends HttpServlet{

? ? @Override

? ? protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

? ? ? ? //在ServletB中獲取統(tǒng)一個(gè)請(qǐng)求對(duì)象作用域的值域的值

? ? ? ? Integer age = (Integer)request.getAttribute("age");

? ? }

}

復(fù)制代碼

9.2 重定向

重定向的機(jī)制和轉(zhuǎn)發(fā)不同,一次重定向的過(guò)程中會(huì)有兩次請(qǐng)求和兩次響應(yīng)铛只,服務(wù)端在接收第一次請(qǐng)求后會(huì)先做一次302的響應(yīng)(302表示重定向狀態(tài)碼),告訴客戶(hù)端瀏覽器必須發(fā)起一個(gè)新的地址糠溜,服務(wù)端再次接收這個(gè)請(qǐng)求處理淳玩,最后再次響應(yīng)客戶(hù)端。

重定向特點(diǎn):

1非竿、URL地址欄會(huì)發(fā)生改變

2蜕着、重定向的操作是在客戶(hù)端瀏覽器完成的

示例代碼:

方式一:

復(fù)制代碼

public class ServletC extends HttpServlet {

? ? @Override

? ? protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

? ? ? ? //執(zhí)行重定向

? ? ? ? //方式一:設(shè)置302響應(yīng)狀態(tài)碼,并在響應(yīng)頭中添加location屬性指定重定向的地址

? ? ? ? response.setStatus(302);

? ? ? ? response.addHeader("location", "http://localhost:8080/ch06/servletD");

? ? }

}

復(fù)制代碼

方式二:

復(fù)制代碼

public class ServletC extends HttpServlet {

? ? @Override

? ? protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

? ? ? ? System.out.println("請(qǐng)求到達(dá)ServletC");

? ? ? ? System.out.println("ServletC獲取請(qǐng)求參數(shù):"+request.getParameter("userName"));

? ? ? ? //執(zhí)行重定向


? ? ? ? //方式二:使用response的sendRedirect方法

? ? ? ? response.sendRedirect("servletD");

? ? }

}

復(fù)制代碼

10、會(huì)話跟蹤

由于HTTP協(xié)議是無(wú)狀態(tài)的承匣,服務(wù)端并不會(huì)記錄每一個(gè)客戶(hù)端的狀態(tài)蓖乘,因此,如果想要實(shí)現(xiàn)服務(wù)器能記錄客戶(hù)端的狀態(tài)的話韧骗,那么就需要會(huì)話跟蹤技術(shù)嘉抒。

10.1 cookie

cookie是客戶(hù)端瀏覽器的內(nèi)部的一個(gè)文本文件,專(zhuān)門(mén)用于記錄服務(wù)器發(fā)送過(guò)來(lái)的一些文本信息袍暴,那么在每次請(qǐng)求的時(shí)候些侍,客戶(hù)端都把這個(gè)cookie信息由提交回給相應(yīng)的服務(wù)器,那么服務(wù)器就可以獲取cookie的信息政模,達(dá)到會(huì)話跟蹤的目的岗宣。使用cookie的機(jī)制是基于客戶(hù)端瀏覽器來(lái)維護(hù)與服務(wù)器的狀態(tài)跟蹤。

示例代碼:

設(shè)置cookie

復(fù)制代碼

public class SetCookieServlet extends HttpServlet{

? ? protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

? ? ? ? //創(chuàng)建一個(gè)Cookie的實(shí)例

? ? ? ? Cookie cookie = new Cookie("userId","10001");

? ? ? ? //將cookie對(duì)象設(shè)置到響應(yīng)對(duì)象中

? ? ? ? response.addCookie(cookie);

? ? ? ? System.out.println("成功設(shè)置cookie");

? ? }

}

復(fù)制代碼

獲取cookie

復(fù)制代碼

public class GetCookieServlet extends HttpServlet{

? ? @Override

? ? protected void service(HttpServletRequest request, HttpServletResponse repsonse) throws ServletException, IOException {

? ? ? ? //cookie是通過(guò)request對(duì)象來(lái)得到的

? ? ? ? //從請(qǐng)求中可以獲取多個(gè)cookie對(duì)象

? ? ? ? Cookie[] cookies = request.getCookies();

? ? ? ? for (Cookie cookie : cookies) {

? ? ? ? ? ? //判斷cookie淋样,只獲取name為userId的cookie對(duì)象

? ? ? ? ? ? if("userId".equals(cookie.getName())) {

? ? ? ? ? ? ? ? System.out.println(cookie.getValue());

? ? ? ? ? ? }

? ? ? ? }

? ? }? ?

}

復(fù)制代碼

cookie保存中文:

在保存cookie的時(shí)候如果需要保存中文耗式,那么中文信息需要經(jīng)過(guò)編碼后才可以寫(xiě)入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的生命周期:

默認(rèn)cookie只會(huì)保存在瀏覽器進(jìn)程的內(nèi)存中,并不會(huì)寫(xiě)入cookie文件趁猴,如果關(guān)閉了瀏覽器刊咳,那么瀏覽器的進(jìn)程也就消失了,那么對(duì)應(yīng)的內(nèi)存就會(huì)釋放空間躲叼,因此cookie的也就銷(xiāo)毀芦缰。如果想將cookie寫(xiě)入文件,那么就必須設(shè)置cookie的生命時(shí)長(zhǎng)枫慷,一旦設(shè)置了生命時(shí)長(zhǎng)让蕾,那么就表示這個(gè)cookie會(huì)在文件中保留多長(zhǎng)時(shí)間,到了這個(gè)時(shí)間之后或听,瀏覽器就會(huì)自動(dòng)銷(xiāo)毀這個(gè)cookie探孝。

設(shè)置cookie存活時(shí)間:

復(fù)制代碼

//設(shè)置為0表示立即刪除cookie

cookie.setMaxAge(0);

//設(shè)置為正數(shù)表示cookie在cookie文件的存活時(shí)間,單位:秒

cookie.setMaxAge(5);

//設(shè)置為-1表示cookie只保留在瀏覽器的進(jìn)程中誉裆,關(guān)閉瀏覽器之后會(huì)銷(xiāo)毀cookie

cookie.setMaxAge(-1);

復(fù)制代碼

10.2 Session

Session是基于服務(wù)端來(lái)保存用戶(hù)的信息顿颅,這個(gè)是和cookie的最大區(qū)別。不同的客戶(hù)端在請(qǐng)求服務(wù)器的時(shí)候足丢,服務(wù)器會(huì)為每一個(gè)客戶(hù)端創(chuàng)建一個(gè)Session對(duì)象并保存在服務(wù)器端粱腻,這個(gè)Session對(duì)象是每個(gè)客戶(hù)端所獨(dú)有的,相互之間不能訪問(wèn)斩跌。服務(wù)器為了區(qū)別不同的Session屬于哪一個(gè)客戶(hù)端绍些,因此Session對(duì)象也有一個(gè)唯一標(biāo)識(shí),叫做SessionID耀鸦。而這個(gè)SessionID是以cookie的機(jī)制保存在客戶(hù)端瀏覽器柬批。每次請(qǐng)求的時(shí)候啸澡,瀏覽器都會(huì)把這個(gè)SessionID帶回服務(wù)端,服務(wù)端根據(jù)這個(gè)SessionID就可以找到對(duì)應(yīng)的Session對(duì)象氮帐。

示例代碼:

復(fù)制代碼

public class SessionServlet extends HttpServlet{

? ? @Override

? ? protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

? ? ? ? //HttpSession對(duì)象是在第一次調(diào)用request的getSession()方法時(shí)才會(huì)創(chuàng)建

? ? ? ? //注意:getSession()的方法會(huì)先判斷之前是否為客戶(hù)端創(chuàng)建了session實(shí)例嗅虏,

? ? ? ? //如果創(chuàng)建了,則使用之前創(chuàng)建好的Session對(duì)象上沐,沒(méi)有則創(chuàng)建一個(gè)新的Session

? ? ? ? HttpSession session = request.getSession();

? ? ? ? //創(chuàng)建HttpSession的同時(shí)皮服,會(huì)創(chuàng)建一個(gè)唯一的標(biāo)識(shí)SessionID

? ? ? ? //這個(gè)sessionId會(huì)保存在瀏覽器的cookie中,每次請(qǐng)求會(huì)帶回這個(gè)id找到相應(yīng)的session對(duì)象

? ? ? ? String sessionId = session.getId();

? ? ? ? System.out.println(sessionId);

? ? }

}

復(fù)制代碼

session的生命周期:

1. SessionId是保存在瀏覽器的cookie中奄容,但是不會(huì)寫(xiě)入cookie文件冰更,這也就表示當(dāng)關(guān)閉瀏覽器之后SessionId就會(huì)銷(xiāo)毀。SessionId銷(xiāo)毀以后昂勒,服務(wù)端的Session就沒(méi)有任何作用了蜀细。但是服務(wù)器并不會(huì)立刻銷(xiāo)毀這個(gè)Session對(duì)象,至于什么時(shí)候銷(xiāo)毀是由服務(wù)器自己決定的戈盈。除非我們手動(dòng)調(diào)用了session.invalidate()方法奠衔,服務(wù)器就會(huì)立即銷(xiāo)毀這個(gè)session實(shí)例。

示例代碼:

HttpSession session=request.getSession();

//立即銷(xiāo)毀session

session.invalidate();

2.Session默認(rèn)也有存活時(shí)間,服務(wù)器在創(chuàng)建Session的時(shí)候?yàn)镾ession設(shè)置默認(rèn)的存活時(shí)間為30分鐘,如果在30分鐘之內(nèi)司训,客戶(hù)端沒(méi)有發(fā)起任何到服務(wù)器,那么服務(wù)器就會(huì)銷(xiāo)毀這個(gè)Session對(duì)象脏里。我們也可以設(shè)置Session的存活時(shí)間『缡铮可以為當(dāng)前的Session設(shè)置迫横,也可以為全局(服務(wù)器端的所有Session)的Session設(shè)置。

設(shè)置當(dāng)前Session的存活時(shí):

HttpSession session=request.getSession();

//設(shè)置當(dāng)前Session的存活時(shí)間酝碳,單位:秒

session.setMaxInactiveInterval(3600);

設(shè)置 全局的Session的存活時(shí)間 :

在web.xml中進(jìn)行設(shè)置

<!-- 設(shè)置全局Session的存活時(shí)間矾踱,單位:分鐘 -->

<session-config>

? ? <session-timeout>60</session-timeout>

</session-config>

Session的作用域:

當(dāng)我們需要將一些數(shù)據(jù)信息存入Session的時(shí)候,就需要操作Session作用域(SessionScope)疏哗,它和請(qǐng)求作用域類(lèi)似呛讲,也有相應(yīng)setAttitude和getAttribute方法,只不過(guò)Session作用域的范圍要比請(qǐng)求作用域更寬返奉。請(qǐng)求作用域在一次請(qǐng)求響應(yīng)只有就會(huì)消失(因?yàn)轫憫?yīng)之后請(qǐng)求就會(huì)銷(xiāo)毀)贝搁。而Session對(duì)象只要瀏覽器不關(guān)閉或者未超時(shí),那么Session對(duì)象會(huì)一直駐留在服務(wù)器端芽偏,因此不管重新請(qǐng)求 多少次還是轉(zhuǎn)發(fā)和重定向雷逆,都可以從Session中獲取之前保存的數(shù)據(jù)信息。

示例代碼:

復(fù)制代碼

User user = new User();

user.setUid("1001");

user.setUserName("wangl");

HttpSession session = request.getSession();

//將數(shù)據(jù)保存在會(huì)話作用域中

session.setAttribute("user", user);

復(fù)制代碼

?

從會(huì)話作用域取值

HttpSession session = request.getSession();

//取值

User user = (User)session.getAttribute("user");

URL重寫(xiě):

瀏覽器是可以禁用cookie的哮针,一旦禁用了cookie,那么SessionID將無(wú)法寫(xiě)入cookie的緩存中,這樣就導(dǎo)致無(wú)法實(shí)現(xiàn)會(huì)話跟蹤了十厢,因此解決辦法就是使用URL重寫(xiě)等太。URL重寫(xiě)的目的就是把SessionID放在請(qǐng)求URL地址的后面提交回服務(wù)器(類(lèi)似GET請(qǐng)求后面帶上參數(shù),而這個(gè)參數(shù)就是一個(gè)SessionID)蛮放,服務(wù)器會(huì)解析和這個(gè)URL的地址并得到SessionID缩抡。

示例代碼:

//重寫(xiě)請(qǐng)求的URL地址,這個(gè)地址后面會(huì)自動(dòng)帶上SessionId

String url = response.encodeRedirectURL("getSession");

//重定向URL

response.sendRedirect(url);

瀏覽器地址演示

http://localhost:8080/ch07/getSession;jsessionid=6F1 BA8C92D7E5D7CC479ED8DD30D3ED0

注意:“包颁;”后面跟著就是SessionID

11瞻想、Servlet上下文

web容器在啟動(dòng)時(shí)會(huì)為每一個(gè)web應(yīng)用創(chuàng)建唯一的上下文對(duì)象,這個(gè)對(duì)象就是Servlet上下文對(duì)象(ServletContext)娩嚼,這個(gè)上下文對(duì)象可以理解為是當(dāng)前項(xiàng)目的一個(gè)共享內(nèi)存空間蘑险,為項(xiàng)目中的所有Servlet提供一個(gè)共享的區(qū)域。

常用API:

方法 說(shuō)明

getContextPath() 獲取項(xiàng)目的相對(duì)路徑

getRealPath(String path) 獲取項(xiàng)目的絕對(duì)路徑

getInitParameter(String name) 獲取上下文的初始化參數(shù)(web.xml中配置的)

setAttribute(String name, String value) 將數(shù)據(jù)放入上下文作用域

getAttribute(String name) 從上下文作用域中去獲取數(shù)據(jù)

上下文作用域:

上下文作用域是為當(dāng)前項(xiàng)目所有Servlet提供的一個(gè)共享內(nèi)存區(qū)域岳悟,可以將需要的數(shù)據(jù)信息保存在作用域中佃迄。這個(gè)作用域的的范圍是最大的,只要容器沒(méi)有停止贵少,它就會(huì)一直存在呵俏。

三種作用域:

結(jié)合前面所學(xué)的作用域,那么一共有三個(gè)滔灶,分別是:請(qǐng)求作用域普碎,會(huì)話作用域,上下文作用域录平。

范圍從小到大來(lái)劃分:

請(qǐng)求作用域<會(huì)話作用域<上下文作用域

12麻车、過(guò)濾器

過(guò)濾器可以在請(qǐng)求到達(dá)Servlet之前和Servlet響應(yīng)客戶(hù)端之前進(jìn)行攔截,相當(dāng)于一個(gè)攔截器萄涯,主要用于進(jìn)行一些請(qǐng)求和響應(yīng)的預(yù)處理操作绪氛。常用的場(chǎng)景有權(quán)限的控制、統(tǒng)一字符編碼等等涝影。

12.1 編寫(xiě)過(guò)濾器

要實(shí)現(xiàn)一個(gè)過(guò)濾器枣察,必須實(shí)現(xiàn)一個(gè)Filter接口,只有實(shí)現(xiàn)了這個(gè)接口的類(lèi)才稱(chēng)之為過(guò)濾器燃逻。

示例代碼

public class DemoFilter implements Filter{

? ? ...

}

web.xml配置過(guò)濾器:

復(fù)制代碼

<filter>

? ? ? ? <filter-name>demoFilter</filter-name>

? ? ? ? <filter-class>edu.nf.ch09.filter.DemoFilter</filter-class>

? ? ? ? <!-- 初始化參數(shù) -->

? ? ? ? <init-param>

? ? ? ? ? ? <param-name>param</param-name>

? ? ? ? ? ? <param-value>hello</param-value>

? ? ? ? </init-param>

? ? </filter>

? ? <filter-mapping>

? ? ? ? <filter-name>demoFilter</filter-name>

? ? ? ? <!-- 什么請(qǐng)求可以經(jīng)過(guò)此過(guò)濾器序目,/*表示所有請(qǐng)求 -->

? ? ? ? <url-pattern>/*</url-pattern>

? ? </filter-mapping>

復(fù)制代碼

12.2 過(guò)濾器的生命周期

與Servlet類(lèi)似,F(xiàn)ilter同樣也是有容器負(fù)責(zé)創(chuàng)建和銷(xiāo)毀伯襟,與Servlet的區(qū)別在于猿涨,容器會(huì)在啟動(dòng)的時(shí)候最先創(chuàng)建所有的過(guò)濾器,并執(zhí)行init方法進(jìn)行初始化姆怪。

生命周期方法:

方法 說(shuō)明

init 初始化方法叛赚,容器啟動(dòng)時(shí)執(zhí)行一次

doFilter 請(qǐng)求過(guò)濾方法澡绩,決定請(qǐng)求是否放行

destroy 容器銷(xiāo)毀過(guò)濾器之前執(zhí)行的方法

示例代碼:

復(fù)制代碼

public class DemoFilter implements Filter{

?

? ? @Override

? ? public void destroy() {


? ? ? ? System.out.println("準(zhǔn)備銷(xiāo)毀DemoFilter");

? ? }

?

? ? @Override

? ? public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)

? ? ? ? ? ? throws IOException, ServletException {

? ? ? ? //FilterChain表示一個(gè)過(guò)濾鏈對(duì)象,因?yàn)檫^(guò)濾器可能會(huì)存在多個(gè)

? ? ? ? //同時(shí)這個(gè)對(duì)象將決定是否放行當(dāng)前請(qǐng)求俺附,

? ? ? ? //放行的話則請(qǐng)求會(huì)繼續(xù)到達(dá)下一個(gè)過(guò)濾器或者servlet中

? ? ? ? System.out.println("請(qǐng)求經(jīng)過(guò)DemoFileer..放行");

? ? ? ? chain.doFilter(request, response);

? ? ? ? System.out.println("響應(yīng)前經(jīng)過(guò)DemoFilter...");

? ? }

?

? ? @Override

? ? public void init(FilterConfig config) throws ServletException {

? ? ? ? String name = config.getInitParameter("param");

? ? ? ? System.out.println("初始化DemoFilter肥卡,獲取初始化參數(shù):"+name);

? ? }

?

}

復(fù)制代碼

12.3 過(guò)濾鏈

在一個(gè)web項(xiàng)目中可能存在多個(gè)過(guò)濾器,當(dāng)有多個(gè)過(guò)濾器存在的時(shí)候就會(huì)形成一個(gè)過(guò)濾鏈事镣。請(qǐng)求會(huì)按照過(guò)濾器鏈的順序一直傳遞下去步鉴,最終到達(dá)某個(gè)Servlet來(lái)處理請(qǐng)求。(注意:過(guò)濾鏈的順序是按照web.xml中的先后配置順序決定的)

配置示例:

復(fù)制代碼

<!-- 按先后順序配置 -->

? ? <!-- 配置第一個(gè)過(guò)濾器 -->

? ? <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>

? ? <!-- 配置第二個(gè)過(guò)濾器 -->

? ? <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>

復(fù)制代碼

13璃哟、監(jiān)聽(tīng)器

監(jiān)聽(tīng)器用于監(jiān)聽(tīng)對(duì)象的上的事件發(fā)生氛琢,在Servlet中監(jiān)聽(tīng)器主要監(jiān)聽(tīng)請(qǐng)求對(duì)象、會(huì)話對(duì)象随闪、上下文對(duì)象以及監(jiān)聽(tīng)這些對(duì)象的作用操作阳似。JavaEE為我們提供了一系列的監(jiān)聽(tīng)器接口,開(kāi)發(fā)時(shí)按需實(shí)現(xiàn)響應(yīng)的接口即可蕴掏。

13.1 監(jiān)聽(tīng)作用域?qū)ο蟮膭?chuàng)建于銷(xiāo)毀

監(jiān)聽(tīng)器 說(shuō)明

ServletRequestListener 監(jiān)聽(tīng)請(qǐng)求對(duì)象的創(chuàng)建和銷(xiāo)毀

HttpSessionListener 監(jiān)聽(tīng)會(huì)話對(duì)象的創(chuàng)建和銷(xiāo)毀

ServletContextListener 監(jiān)聽(tīng)Servlet上下文對(duì)象的創(chuàng)建和銷(xiāo)毀

代碼實(shí)例:

1.請(qǐng)求對(duì)象監(jiān)聽(tīng)器

復(fù)制代碼

public class DemoRequestListener implements ServletRequestListener{

?

? ? /**

? ? * 當(dāng)請(qǐng)求對(duì)象銷(xiāo)毀后容器執(zhí)行此方法

? ? * 銷(xiāo)毀方法中同樣也有一個(gè)ServletRequestEvent事件對(duì)象

? ? */

? ? @Override

? ? public void requestDestroyed(ServletRequestEvent event) {

? ? ? ? //通過(guò)這個(gè)事件對(duì)象就可以獲取當(dāng)前的請(qǐng)求對(duì)象

? ? ? ? HttpServletRequest request = (HttpServletRequest)event.getServletRequest();

? ? ? ? System.out.println("銷(xiāo)毀請(qǐng)求對(duì)象..."+request);

? ? }

?

? ? /**

? ? * 當(dāng)請(qǐng)求對(duì)象創(chuàng)建之后容器調(diào)用此方法

? ? * ServletRequestEvent這個(gè)參數(shù)就是一個(gè)事件對(duì)象

? ? */

? ? @Override

? ? public void requestInitialized(ServletRequestEvent event) {

? ? ? ? //通過(guò)這個(gè)事件對(duì)象就可以獲取當(dāng)前的請(qǐng)求對(duì)象

? ? ? ? HttpServletRequest request = (HttpServletRequest)event.getServletRequest();

? ? ? ? System.out.println("初始化了請(qǐng)求對(duì)象..."+request);

? ? }

?

}

復(fù)制代碼

web.xml 配置

<!-- 配置監(jiān)聽(tīng)器 -->

? <listener>

? ? <!-- 指定監(jiān)聽(tīng)器的完整類(lèi)名 -->

? ? <listener-class>edu.nf.ch10.listener.DemoRequestListener</listener-class>

? </listener>

2.會(huì)話對(duì)象監(jiān)聽(tīng)器

復(fù)制代碼

public class DemoSessionListener implements HttpSessionListener{

?

? ? /**

? ? * 監(jiān)聽(tīng)HttpSession對(duì)象的創(chuàng)建

? ? * HttpSessionEvent參數(shù)是一個(gè)事件對(duì)象

? ? * 通過(guò)它可以獲得當(dāng)前的HttpSession

? ? */

? ? @Override

? ? public void sessionCreated(HttpSessionEvent event) {

? ? ? ? HttpSession session = event.getSession();

? ? ? ? System.out.println("創(chuàng)建了Session對(duì)象"+session);

? ? }

?

? ? /**

? ? * 監(jiān)聽(tīng)HttpSession對(duì)象的銷(xiāo)毀

? ? */

? ? @Override

? ? public void sessionDestroyed(HttpSessionEvent event) {

? ? ? ? HttpSession session = event.getSession();

? ? ? ? System.out.println("銷(xiāo)毀了Session對(duì)象"+session);

? ? }

}

復(fù)制代碼

注意:當(dāng)?shù)谝淮握{(diào)用了request.getSession()方法創(chuàng)建Session時(shí)障般,監(jiān)聽(tīng)器才會(huì)起作用。

web.xml配置

<listener>

? ? <!-- 指定監(jiān)聽(tīng)器的完整類(lèi)名 -->

? ? <listener-class>edu.nf.ch10.listener.DemoSessionListener</listener-class>

? </listener>

3.Servlet上下文監(jiān)聽(tīng)器

復(fù)制代碼

public class DemoContextListener implements ServletContextListener{

?

? ? /**

? ? * 監(jiān)聽(tīng)ServletContext的銷(xiāo)毀

? ? */

? ? @Override

? ? public void contextDestroyed(ServletContextEvent event) {

? ? ? ? //通過(guò)事件對(duì)象獲取ServletContext

? ? ? ? ServletContext sc = event.getServletContext();

? ? ? ? System.out.println("銷(xiāo)毀了ServletContext對(duì)象..."+sc);

? ? }

?

? ? /**

? ? * 監(jiān)聽(tīng)SerlvetContext的創(chuàng)建

? ? */

? ? @Override

? ? public void contextInitialized(ServletContextEvent event) {

? ? ? ? //通過(guò)事件對(duì)象獲取ServletContext

? ? ? ? ServletContext sc = event.getServletContext();

? ? ? ? System.out.println("創(chuàng)建了ServletContext對(duì)象..."+sc);

? ? }

}

復(fù)制代碼

web.xml


<listener>

? ? <!-- 指定監(jiān)聽(tīng)器的完整類(lèi)名 -->

? ? <listener-class>edu.nf.ch10.listener.DemoContextListener</listener-class>

? </listener>

13.2 監(jiān)聽(tīng)作用域的操作

監(jiān)聽(tīng)器 說(shuō)明

ServletRequestAttributeListener 監(jiān)聽(tīng)請(qǐng)求作用域的操作

HttpSessionAttributeListener 監(jiān)聽(tīng)會(huì)話作用域的操作

ServletContextAttributeListener 監(jiān)聽(tīng)Servlet上下文作用域的操作

示例代碼:

這里以HttpSessionAttributeListener說(shuō)明盛杰,其他作用域監(jiān)聽(tīng)器用法相似挽荡。

復(fù)制代碼

public class DemoSessionAttributeListener implements HttpSessionAttributeListener{

?

? ? /**

? ? * 當(dāng)有數(shù)據(jù)添加到會(huì)話作用域時(shí),執(zhí)行此方法

? ? */

? ? @Override

? ? public void attributeAdded(HttpSessionBindingEvent event) {

? ? ? ? //獲取存入作用域的鍵和值

? ? ? ? System.out.println("存入會(huì)話作用域..."+event.getName() + " : " + event.getValue());


? ? }

?

? ? /**

? ? * 當(dāng)從會(huì)話作用域移除數(shù)據(jù)時(shí)即供,執(zhí)行此方法

? ? */

? ? @Override

? ? public void attributeRemoved(HttpSessionBindingEvent event) {

? ? ? ? System.out.println("移除會(huì)話作用域..."+event.getName() + " : " + event.getValue());


? ? }

?

? ? /**

? ? * 當(dāng)替換了會(huì)話作用域中的某個(gè)數(shù)據(jù)時(shí)定拟,執(zhí)行此方法

? ? */

? ? @Override

? ? public void attributeReplaced(HttpSessionBindingEvent event) {

? ? ? ? HttpSession session = event.getSession();

? ? ? ? System.out.println("替換的值: "+session.getAttribute("userName").toString());

? ? ? ? //注意:這里event.getValue()獲取到的是被替換的值

? ? ? ? System.out.println("替換會(huì)話作用域..."+event.getName() + " : " + event.getValue());

? ? }

}

復(fù)制代碼

web.xml

<listener>

? ? <!-- 指定監(jiān)聽(tīng)器的完整類(lèi)名 -->

? ? <listener-class>edu.nf.ch10.listener.DemoSessionAttributeListener</listener-class>

? </listener>

14、注解配置

Servlet3.0開(kāi)始提供了一系列的注解來(lái)配置Servlet逗嫡、Filter青自、Listener等等。這種方式可以極大的簡(jiǎn)化在開(kāi)發(fā)中大量的xml的配置驱证。從這個(gè)版本開(kāi)始延窜,web.xml可以不再需要,使用相關(guān)的注解同樣可以完成相應(yīng)的配置抹锄。

注解 說(shuō)明

@WebServlet 這個(gè)注解標(biāo)識(shí)在類(lèi)上逆瑞,用于配置Servlet。例如:@WebServlet(name="hello",urlPatterns="/hello")也可以簡(jiǎn)化配置@WebServlet("/hello")

@WebFilter 這個(gè)注解標(biāo)識(shí)在類(lèi)上伙单,用于配置Filter获高。例如:@WebFilter(filterName="encode",urlPatterns="/*")也可以簡(jiǎn)化配置@WebFilter("/*")

@WebListener 這個(gè)注解標(biāo)識(shí)在類(lèi)上,用于配置監(jiān)聽(tīng)器

15吻育、文件上傳

從Servlet3.0開(kāi)始提供了文件上傳的功能念秧,操作起來(lái)更加的簡(jiǎn)單和方便。

15.1

想要使用這個(gè)功能布疼,首先必須在web.xml或者使用注解開(kāi)啟Servlet的上傳功能摊趾,否則無(wú)效

xml配置:

復(fù)制代碼

<servlet>

? ? ? ? <servlet-name>upload</servlet-name>

? ? ? ? <servlet-class>edu.demo.UploadServlet</servlet-class>

? ? ? ? <!-- 開(kāi)啟上傳功能 -->

? ? ? ? <multipart-config/>

? ? </servlet>

? ? <servlet-mapping>

? ? ? ? <servlet-name>upload</servlet-name>

? ? ? ? <url-pattern>/upload</url-pattern>

? ? </servlet-mapping>

復(fù)制代碼

注解配置:

@WebServlet("/login")

@MultipartConfig //開(kāi)啟上傳功能

public class LoginServlet extends HttpServlet{

? ? ...

}

參數(shù)說(shuō)明:

參數(shù) 說(shuō)明

location 指定文件上傳的目錄

maxFileSize 限制單個(gè)文件上傳的大小

maxRequestSize 限制一次請(qǐng)求上傳總文件的大小

fileSizeThreshold 設(shè)置緩存的大小币狠,當(dāng)達(dá)到緩存大小的時(shí)候,會(huì)將內(nèi)存的數(shù)據(jù)寫(xiě)入location指定的目錄中(也就是寫(xiě)入磁盤(pán))

15.2

文件上傳的核心接口是Part砾层,通過(guò)HTTPServletRequest對(duì)象可獲得該接口的實(shí)體類(lèi)對(duì)象

//獲取單個(gè)文件的Part

Part part = request.getPart("name");

//獲取多個(gè)上傳文件的Part

Collection<Part> cool=request.getParts();

常用API:

方法 說(shuō)明

getContentType() 獲取上傳的文件類(lèi)型

getSize() 獲取上傳文件的大小

getSubmittedFileName() 獲取上傳文件的文件名

write() 將文件上傳(寫(xiě)入)到指定位置

5.13

當(dāng)客戶(hù)端使用form表單來(lái)上傳文件時(shí)总寻,必須將表單的enctype屬性設(shè)置為"multipart/form-data"

復(fù)制代碼

<form method="post" action="upload" enctype="multipart/form-data">

? ? Username:<input type="text" name="userName"/><br/>

? ? <!-- input使用file類(lèi)型 -->

? ? File:<input type="file" name="file"/><br/>

? ? <input type="submit" value="submit"/>

</form>

復(fù)制代碼

案例:

復(fù)制代碼

@WebServlet("/upload")

@MultipartConfig

public class UploadServlet extends HttpServlet {

?

? ? @Override

? ? protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

? ? ? ? //指定上傳的路徑

? ? ? ? String uploadPath = "/Users/wangl/uploads";

? ? ? ? //創(chuàng)建文件夾,如果不存在的情況下

? ? ? ? File dir = new File(uploadPath);

? ? ? ? if(!dir.exists()){

? ? ? ? ? ? dir.mkdir();

? ? ? ? }

?

? ? ? ? //上傳單個(gè)文件梢为,參數(shù)對(duì)用input的name屬性的值

? ? ? ? //Part part = req.getPart("file");

? ? ? ? //uploadPath = uploadPath + "/" + part.getSubmittedFileName();

? ? ? ? //執(zhí)行上傳

? ? ? ? //part.write(uploadPath);

? ? ? ? //獲取文件的類(lèi)型

? ? ? ? //System.out.println(part.getContentType());

? ? ? ? //獲取文件的大小

? ? ? ? //System.out.println(part.getSize());

? ? ? ? //獲取上傳的文件名

? ? ? ? //System.out.println(part.getSubmittedFileName());

?

? ? ? ? //上傳多個(gè)文件

? ? ? ? Collection<Part> parts = req.getParts();

? ? ? ? for (Part p : parts) {

? ? ? ? ? ? p.write(uploadPath + "/" + p.getSubmittedFileName());

? ? ? ? }

? ? }

}

復(fù)制代碼

?

upload.html

復(fù)制代碼

<!DOCTYPE html>

<html lang="en">

<head>

? ? <meta charset="UTF-8">

? ? <title>Title</title>

</head>

<body>

<h2>文件上傳</h2>

<form method="post" action="upload" enctype="multipart/form-data">

? ? Username:<input type="text" name="userName"/><br/>

? ? File1:<input type="file" name="file"/><br/>

? ? File2:<input type="file" name="file"/><br/>

? ? <input type="submit" value="submit"/>

</form>

</body>

</html>

復(fù)制代碼

五、JSP基礎(chǔ)

1轰坊、簡(jiǎn)介

JSP全名為Java Server Pages铸董,中文名叫java服務(wù)器頁(yè)面,是一種動(dòng)態(tài)頁(yè)面技術(shù)肴沫,而HTML是屬于靜態(tài)頁(yè)面JSP可以在HTML中嵌入java腳本代碼粟害,因?yàn)镴SP本質(zhì)上還是一個(gè)Servlet,因此JSP也必須依賴(lài)于web容器才能運(yùn)行颤芬。JSP的出現(xiàn)并不是為了取代Servlet悲幅,而是簡(jiǎn)化了Servlet的工作,將Servlet中繁瑣的視圖呈現(xiàn)代碼脫離出來(lái)站蝠,交給JSP來(lái)完成汰具,讓Servlet專(zhuān)注于請(qǐng)求的處理,所以在開(kāi)發(fā)中通常將JSP和Servlet結(jié)合一起使用菱魔。

2留荔、JSP引擎

由于JSP本質(zhì)上就是一個(gè)Servlet,那么JSP引擎主要負(fù)責(zé)將JSP文件轉(zhuǎn)義成一個(gè)Servlet的java源文件澜倦,然后再通過(guò)javac將這個(gè)源文件聚蝶,編譯成class字節(jié)碼文件并裝載到JVM中執(zhí)行。JSP引擎的核心類(lèi)是JSPServlet藻治,位于Jasper.jar文件中碘勉,并且在Tomcat的web.xml中也默認(rèn)就配置好了這個(gè)類(lèi)(JspServlet也是一個(gè)Servlet)。因此桩卵,凡是以".jsp"結(jié)尾的請(qǐng)求都會(huì)先經(jīng)過(guò)JspServlet验靡,那么這個(gè)引擎就可以開(kāi)始工作。通常引擎轉(zhuǎn)義和編譯后的文件放在容器的work工作目錄中吸占。

注意:如果第一次訪問(wèn)Jsp文件的時(shí)候晴叨,由于work目錄中并不存在源文件和字節(jié)碼文件,JSP引擎就必須完成這兩個(gè)工作矾屯,因此兼蕊,有可能在第一次訪問(wèn)JSP時(shí)會(huì)比較緩慢。當(dāng)字節(jié)碼編譯出來(lái)加載后件蚕,第二次訪問(wèn)時(shí)速度就會(huì)很快了孙技。

3产禾、JSP的三大元素

3.1 指令元素

語(yǔ)法:<%@ %>

指令 說(shuō)明

page指令 用于設(shè)置JSP頁(yè)面的相關(guān)信息以及編碼

include指令 用于靜態(tài)包含其他的JSP頁(yè)面代碼,所謂靜態(tài)包含牵啦,就是在編譯期亚情,將另外的JSP頁(yè)面的代碼合并到當(dāng)前的JSP中,最終只會(huì)產(chǎn)生一個(gè)java源文件

taglib 這個(gè)指令用于引入標(biāo)簽庫(kù)

3.2 動(dòng)作元素

語(yǔ)法:< jsp:xxx >

動(dòng)作 說(shuō)明

include 動(dòng)態(tài)包含其他JSP頁(yè)面的內(nèi)容哈雏,所謂的動(dòng)態(tài)包括是指在編譯期將不同的JSP文件轉(zhuǎn)義成不同java源文件楞件,然后在運(yùn)行時(shí)在將目標(biāo)內(nèi)容包含到當(dāng)前的JSP頁(yè)面中

forward 相當(dāng)于Servlet中的轉(zhuǎn)發(fā),轉(zhuǎn)發(fā)到其他的JSP頁(yè)面或者Servlet

param 用于傳遞參數(shù)裳瘪,通常結(jié)合其他的動(dòng)作一起使用土浸,例如轉(zhuǎn)發(fā)時(shí)需要提交一些額外的參數(shù)

useBean 用于在JSP頁(yè)面中使用JavaBean對(duì)象,通常結(jié)合setProperty和getProperty來(lái)使用彭羹,完成bean對(duì)象的賦值和取值操作

3.3 腳本元素

腳本元素主要就是在JSP中嵌入java腳本代碼黄伊,包括聲明、表達(dá)式派殷、java腳本

聲明語(yǔ)法:<%! %>

表達(dá)式:<%= %>

java腳本:<% %>

示例代碼:

復(fù)制代碼

<%@ 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是實(shí)例變量 --%>

? <%!

? ? ? ? int a = 10;

? ? ? ? public void say(){

? ? ? ? ? ? System.out.println("hello");

? ? ? ? }

? ? %>


? ? <%-- 表達(dá)式,注意:表達(dá)式后面是不允許有;號(hào)結(jié)束的 --%>

? ? 3 + 1 = <%=3+1%><br/>


? ? <%-- Java腳本,腳本代碼最終會(huì)生成在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>

復(fù)制代碼

4、JSP內(nèi)置對(duì)象

內(nèi)置對(duì)象毡惜,是在容器運(yùn)行時(shí)將創(chuàng)建好的9個(gè)對(duì)象內(nèi)嵌在JSP中拓轻,在JSP里可以直接拿來(lái)使用的對(duì)象。

對(duì)象 說(shuō)明

out 字符流輸出對(duì)象

config 等同于Servlet中的ServletConfig

page 表示當(dāng)前JSP頁(yè)面经伙,類(lèi)似于Java類(lèi)中的this關(guān)鍵字

request 等同于 Servlet中的HTTPServletRequest

response 等同于 Servlet中的HTTPServletResponse

session 等同于Servlet中的HTTPSession

application 等同于Servlet中的Servlet

pageContext 表示當(dāng)前JSP頁(yè)面的上下文對(duì)象

exception 表示當(dāng)前JSP中的異常對(duì)象

示例代碼:

復(fù)制代碼

<%@ 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>

? <%-- 常用內(nèi)置對(duì)象 --%>

? <%

? ? //使用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對(duì)象悦即,等同于字符輸出流對(duì)象,在JSP頁(yè)面輸出相關(guān)內(nèi)容

? ? out.println("hello world");

? ? //這個(gè)是輸出在控制中

? ? System.out.println("hello");


? ? //使用application,等同于ServletContext

? ? application.setAttribute("userName", "user3");


? ? //pageContext使用

? ? //從pageContext中獲取相關(guān)的其他對(duì)象

? ? HttpServletRequest req = (HttpServletRequest)pageContext.getRequest();

? ? HttpServletResponse res = (HttpServletResponse)pageContext.getResponse();

? ? HttpSession ses = pageContext.getSession();

? ? ServletConfig conf = pageContext.getServletConfig();

? ? ServletContext sc = pageContext.getServletContext();

? ? //也可以通過(guò)pageContext來(lái)統(tǒng)一設(shè)置不同的作用域

? ? //第三個(gè)參數(shù)表示要放入到哪個(gè)作用域橱乱,是一個(gè)int類(lèi)型的參數(shù)

? ? //1代表page作用域(當(dāng)前頁(yè)面有效)PageContext.APPLICATION_SCONPE

? ? //2代表請(qǐng)求作用域 PageContext.SESSION_SCOPE

? ? //3代表會(huì)話作用域 PageContext.REQUEST_SCOPE

? ? //4代表上下文作用域 PageContext.PAGE_SCOPE

? ? pageContext.setAttribute("userName", "zhangsan", 2);

? ? //也可以指定中哪個(gè)作用域取出相應(yīng)的值

? ? String name = (String)pageContext.getAttribute("userName", 2);

? ? out.println(name);

? %>

</body>

</html>

復(fù)制代碼

5辜梳、EL表達(dá)式

EL(Expression Language),全球叫做表達(dá)式語(yǔ)言泳叠,是JSP2.0推出的一種技術(shù)作瞄。主要簡(jiǎn)化了在JSP中使用Java腳本表達(dá)式。EL表達(dá)式的特點(diǎn)在于使用簡(jiǎn)單危纫,支持四則運(yùn)算宗挥、邏輯運(yùn)算等,并且還可以對(duì)Servlet API中的對(duì)象進(jìn)行數(shù)據(jù)訪問(wèn)种蝶。EL的語(yǔ)法:${expression}

運(yùn)算:

示例 結(jié)果

${1+1} 2

${2*2} 4

${1==1} true

${2>5} false

${"10"==10} true

其他 ...

數(shù)據(jù)訪問(wèn):

1.使用“.”來(lái)訪問(wèn)

示例 說(shuō)明

${param.參數(shù)名} 獲取請(qǐng)求參數(shù)的值,相當(dāng)于使用request.getParameter()方法

${requestScope.xxx} 從請(qǐng)求作用域中訪問(wèn)數(shù)據(jù)

${sessionScope.xxx} 從會(huì)話作用域中訪問(wèn)數(shù)據(jù)

${applicationScope.xxx} 從上下文作用域中訪問(wèn)數(shù)據(jù)

${xxx} 不指定作用域范圍時(shí),默認(rèn)按照作用域范圍從小到大的順序自動(dòng)查找

其他 ...

示例代碼:

復(fù)制代碼

姓名:${param.userName}<br/>

? <%-- 訪問(wèn)請(qǐng)求作用域 --%>

? 請(qǐng)求作用域:${requestScope.userName}<br/>

? 會(huì)話作用域: ${sessionScope.userName}<br/>

? 上下文作用域: ${applicationScope.userName}<br/>

? 自動(dòng)從作用域中取值: ${userName}<br/>


? <h2>訪問(wèn)對(duì)象中的屬性</h2>

? Name:${userName}<br/>

? Age:${age}

復(fù)制代碼

2.使用"[]"來(lái)訪問(wèn)

示例 說(shuō)明

${requestScope[“userName”]} 從請(qǐng)求作用域中取值

${sessionScope[“userName”]} 從會(huì)話作用域取值

其他... 同上

示例代碼:

<h2>使用"[]"來(lái)訪問(wèn)數(shù)據(jù)</h2>

<!-- 可以獲取使用帶.的參數(shù)名稱(chēng)-->

? 請(qǐng)求作用域:${requestScope["user.userName"]}<br/>

? 會(huì)話作用域: ${sessionScope["user.userName"]}<br/>

? 上下文作用域: ${applicationScope["user.userName"]}<br/>

注意:通常使用"[]"來(lái)訪問(wèn)數(shù)據(jù)的時(shí)候契耿,主要是訪問(wèn)一些特殊的名稱(chēng),例如:request.setAttribute("user.userName")

這種方式如果使用${requestScope.user.userName}是訪問(wèn)不到的螃征,應(yīng)該改為

${requestScope["user.userName"]}來(lái)訪問(wèn)

6搪桂、JSTL核心標(biāo)簽庫(kù)

JSTL是JSP中的標(biāo)準(zhǔn)標(biāo)簽庫(kù),主要用于取代JSP中大量的Java腳本代碼,讓頁(yè)面看起來(lái)更趨向于HTML踢械。使用也很簡(jiǎn)單酗电,通常結(jié)合EL表達(dá)式一起使用

示例:

核心標(biāo)簽庫(kù)(core) 說(shuō)明

c:out 輸出標(biāo)簽

c:set 聲明某個(gè)變量并存入指定的作用域

c:redirect 重定向標(biāo)簽

c:if 條件判斷

c:forEach 循環(huán)標(biāo)簽

其他 ...

備注:其他標(biāo)簽庫(kù)請(qǐng)參閱相關(guān)官方文檔

代碼示例:

復(fù)制代碼

<%@ page language="java" contentType="text/html; charset=UTF-8"

? ? pageEncoding="UTF-8"%>

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>?

<!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>JSTL</title>

</head>

<body>

? <%

? ? out.println("hello JSTL");

? %>

? <!-- 使用輸出標(biāo)簽替換上面的腳本 -->

? <c:out value="hello JSTL"></c:out>


? <%

? ? session.setAttribute("userName", "wangl");

? %>

? <!-- 使用set標(biāo)簽替換上面的腳本,var指定變量名,value指定值内列,scope指定要放入的作用域 -->

? <c:set var="userName" value="wangl" scope="session"></c:set>

? <!-- 重定向標(biāo)簽 -->

? <%--<c:redirect url="demo.jsp"/>--%>


? <!-- 使用條件判斷 -->

? <c:set var="age" value="70"/>

? <c:if test="${age<=18}">

? ? <h2>很年輕</h2>

? </c:if>

? <c:if test="${age>18 && age<50}">

? ? <h2>還好</h2>

? </c:if>

? <c:if test="${age>60}">

? ? <h2>老了</h2>

? </c:if>

</body>

</html>

復(fù)制代碼

復(fù)制代碼

<%@ page language="java" contentType="text/html; charset=UTF-8"

? ? pageEncoding="UTF-8"%>

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>? ? ?

<!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>

? <!-- 聲明變量i撵术,起始為0, 到10結(jié)束 -->

? <%--

? <c:forEach var="i" begin="0" end="10">

? ? ${i}<br/>

? </c:forEach>

? --%>

? <table border="1">

? ? <tr>

? ? ? ? <th>姓名</th>

? ? ? ? <th>年齡</th>

? ? ? ? <th>性別</th>

? ? ? ? <th>籍貫</th>

? ? ? ? <th>班級(jí)</th>

? ? </tr>

? ? <!-- list中存放的map “List<Map<String,Object>>”-->

? ? <%--

? ? <c:forEach items="${list}" var="m">

? ? ? ? <tr>

? ? ? ? ? ? <td>${m.s_name}</td>

? ? ? ? ? ? <td>${m.s_age}</td>

? ? ? ? ? ? <td>${m.s_sex}</td>

? ? ? ? ? ? <td>${m.origin}</td>

? ? ? ? ? ? <td>${m.c_name}</td>

? ? ? ? </tr>

? ? </c:forEach>

? ? --%>


? ? <!-- list中放的是Object[]? “List<Object[]>” -->

? ? <c:forEach items="${requestScope.list}" var="o">

? ? ? ? <tr>

? ? ? ? ? ? <td>${o[0]}</td>

? ? ? ? ? ? <td>${o[1]}</td>

? ? ? ? ? ? <td>${o[2]}</td>

? ? ? ? ? ? <td>${o[3]}</td>

? ? ? ? ? ? <td>${o[4]}</td>

? ? ? ? </tr>

? ? </c:forEach>

? </table>


</body>

</html>

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末话瞧,一起剝皮案震驚了整個(gè)濱河市嫩与,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌交排,老刑警劉巖蕴纳,帶你破解...
    沈念sama閱讀 212,686評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異个粱,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)翻翩,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,668評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門(mén)都许,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人嫂冻,你說(shuō)我怎么就攤上這事胶征。” “怎么了桨仿?”我有些...
    開(kāi)封第一講書(shū)人閱讀 158,160評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵睛低,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我服傍,道長(zhǎng)钱雷,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,736評(píng)論 1 284
  • 正文 為了忘掉前任吹零,我火速辦了婚禮罩抗,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘灿椅。我一直安慰自己套蒂,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,847評(píng)論 6 386
  • 文/花漫 我一把揭開(kāi)白布茫蛹。 她就那樣靜靜地躺著操刀,像睡著了一般。 火紅的嫁衣襯著肌膚如雪婴洼。 梳的紋絲不亂的頭發(fā)上骨坑,一...
    開(kāi)封第一講書(shū)人閱讀 50,043評(píng)論 1 291
  • 那天,我揣著相機(jī)與錄音柬采,去河邊找鬼卡啰。 笑死静稻,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的匈辱。 我是一名探鬼主播振湾,決...
    沈念sama閱讀 39,129評(píng)論 3 410
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼亡脸!你這毒婦竟也來(lái)了押搪?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 37,872評(píng)論 0 268
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤浅碾,失蹤者是張志新(化名)和其女友劉穎大州,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體垂谢,經(jīng)...
    沈念sama閱讀 44,318評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡厦画,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,645評(píng)論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了滥朱。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片根暑。...
    茶點(diǎn)故事閱讀 38,777評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖徙邻,靈堂內(nèi)的尸體忽然破棺而出排嫌,到底是詐尸還是另有隱情,我是刑警寧澤缰犁,帶...
    沈念sama閱讀 34,470評(píng)論 4 333
  • 正文 年R本政府宣布淳地,位于F島的核電站,受9級(jí)特大地震影響帅容,放射性物質(zhì)發(fā)生泄漏颇象。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,126評(píng)論 3 317
  • 文/蒙蒙 一并徘、第九天 我趴在偏房一處隱蔽的房頂上張望夯到。 院中可真熱鬧,春花似錦饮亏、人聲如沸耍贾。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,861評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)荐开。三九已至,卻和暖如春简肴,著一層夾襖步出監(jiān)牢的瞬間晃听,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,095評(píng)論 1 267
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留能扒,地道東北人佣渴。 一個(gè)月前我還...
    沈念sama閱讀 46,589評(píng)論 2 362
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像初斑,于是被迫代替她去往敵國(guó)和親辛润。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,687評(píng)論 2 351