response
第1章ServletContext接口
場(chǎng)景:
在線人數(shù):xxx萬,吸引用戶來注冊(cè)。
當(dāng)用戶進(jìn)入系統(tǒng),應(yīng)該當(dāng)前在線人數(shù)加一——servlet處理
當(dāng)用戶退出系統(tǒng),應(yīng)該當(dāng)前在線人數(shù)減一——servlet處理
需求:
有在線人數(shù)的數(shù)據(jù),必須,可以讓兩個(gè)servlet都可以獲取使用。
希望:有這么一個(gè)容器(保存數(shù)據(jù)),這個(gè)容器可以被多個(gè)servlet同時(shí)使用。
這個(gè)就是我們ServletContext容器:

ServletContext示意圖:他是一個(gè)存儲(chǔ)數(shù)據(jù)的容器

總結(jié):
1 容器可以存儲(chǔ)數(shù)據(jù)
2 操作容器set get remove
3 可以被多個(gè)Servlet使用共享。
當(dāng)tomcat啟動(dòng)時(shí),會(huì)為每個(gè)web應(yīng)用創(chuàng)建一個(gè)唯一的ServletContext對(duì)象代表當(dāng)前Web應(yīng)用.該對(duì)象不僅封裝了當(dāng)前web應(yīng)用的所有信息,而且實(shí)現(xiàn)了多個(gè)servlet的數(shù)據(jù)共享.
在每個(gè)項(xiàng)目中可以有多個(gè)Servlet程序,每個(gè)Servlet程序都是獨(dú)立的。Servlet中的配置信息可以使用ServletConfig獲取,而當(dāng)前這個(gè)項(xiàng)目的配置信息,就必須使用描述這個(gè)項(xiàng)目的ServletContext對(duì)象獲取。
1.1ServletContext容器的存取刪操作(重點(diǎn))
由于一個(gè)web應(yīng)用程序中的所有Servlet共享同一個(gè)ServletContxt對(duì)象,因此ServletContext中的屬性可以被Web應(yīng)用程序中的所有servlet訪問。在ServletContext中分別定義了用于 增加、刪除、獲取ServletContext屬性的4個(gè)方法:


代碼演示:
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
ServletContext servletContext = getServletContext();
servletContext.setAttribute("hehe", "呵呵");
String hehe = (String) servletContext.getAttribute("hehe");
System.out.println("hehe:"+hehe);
servletContext.removeAttribute("hehe");
String hehe2 = (String) servletContext.getAttribute("hehe");
System.out.println("hehe:"+hehe2);
}
效果:
hehe:呵呵
hehe:null
1.2讀取全局(整個(gè)項(xiàng)目)配置參數(shù)(讀取項(xiàng)目在web.xml中的配置信息)
我們?cè)趙eb.xml文件中是可以配置項(xiàng)目的初始化信息:
項(xiàng)目的配置信息需要在當(dāng)前這個(gè)web.xml的全局位置配置:

需求: 設(shè)置項(xiàng)目全局參數(shù) 公司=極客營(yíng) 地址=常武中路888號(hào)
1 在web.xml中配置全局(項(xiàng)目)參數(shù)信息

2 根據(jù)key獲取value

1.3ServletContext讀取Web工程中資源文件路徑
要讀取資源,必須先找到這個(gè)文件:
第一個(gè)要介紹的方法是:

String realPath = context.getRealPath("/WEB-INF/classes/c3p0-config.xml");
System.out.println(realPath);
效果:
C:\apache-tomcat-7.0.81\webapps\aa\WEB-INF\classes\c3p0-config.xml
//使用IO讀取展示到控制臺(tái):
BufferedReader reader = new BufferedReader(new FileReader(new File(realPath)));
String line = null;
while((line = reader.readLine()) != null){
System.out.println(line);
}
解析獲取到的資源的文件類型:

ServletContext context = getServletContext();
String realPath = context.getRealPath("/WEB-INF/classes/c3p0-config.xml");
System.out.println(context.getMimeType(realPath));
String realPath2 = context.getRealPath("/1.html"); System.out.println(context.getMimeType(realPath2));
//效果:
application/xml
text/html
第2章response介紹(服務(wù)器 ——>客戶端瀏覽器)
在之前學(xué)習(xí)servlet的時(shí)候,我們已經(jīng)可以處理請(qǐng)求和響應(yīng),針對(duì)請(qǐng)求和響應(yīng),我們servlet方法中提供了request對(duì)象和response對(duì)象,方便我們使用。
今天,我們主要來學(xué)習(xí)和使用response對(duì)象:

ServletResponse定義了基本的響應(yīng)數(shù)據(jù)的方法,但是不面對(duì)任何協(xié)議。

2.1response的狀態(tài)碼和響應(yīng)頭設(shè)置
設(shè)置狀態(tài)碼:

int sc 是狀態(tài)碼(200,302,404,500),不要設(shè)置不存在的響應(yīng)狀態(tài)碼
默認(rèn)是200;
設(shè)置響應(yīng)頭信息:

name : 表示響應(yīng)頭 name的值
value : 響應(yīng)頭對(duì)應(yīng)的值
2.2常用的響應(yīng)頭演示:
2.2.1Refresh: 3;url=http://(頁面自動(dòng)刷新)
3 表示是的時(shí)間,3秒
url 地址
到3秒后,頁面刷新url
測(cè)試代碼:
response.setHeader("Refresh", "5;url=http://www.jd.com");
2.2.2Location: http://
通常告知瀏覽器 馬上向該地址發(fā)送請(qǐng)求 通常 和 302 一起使用!!
(重點(diǎn)) 結(jié)合302完成重定向 操作 Location重定向后地址
代碼演示一:
response.setStatus(302);
response.setHeader("Location", " http://localhost:9090/day02/1.html ");
代碼演示二:
response.sendRedirect("http://localhost:9090/day02/1.html ");
重定向的細(xì)節(jié):

瀏覽器發(fā)送了兩次請(qǐng)求,第一次請(qǐng)求中:

指定了讓瀏覽器再次發(fā)送請(qǐng)求的地址
請(qǐng)求轉(zhuǎn)發(fā)和重定向的區(qū)別:

重定向和轉(zhuǎn)發(fā)的區(qū)別:
1 轉(zhuǎn)發(fā)操作發(fā)生在服務(wù)器內(nèi)部,重定向是瀏覽器執(zhí)行操作
2 轉(zhuǎn)發(fā)地址欄不變,重定向,地址欄變化
3 轉(zhuǎn)發(fā)在一次請(qǐng)求中完成,重定向是兩次請(qǐng)求
4 轉(zhuǎn)發(fā)可以在一次請(qǐng)求中共享數(shù)據(jù),重定向不行。
2.2.3Content-Type: text/html; charset=utf-8
告訴瀏覽器以什么樣的方式打開資源,和使用編碼集
代碼演示:
response.setContentType("text/html;charset=utf-8");
response.getWriter().write("<h1>哈哈哈<h1>");
~~
效果:
哈哈哈
如果設(shè)置普通文本形式:text/plain
response.setContentType("text/plain;charset=utf-8");
response.getWriter().write("<h1>哈哈哈<h1>");
效果:
<h1>哈哈哈</h1>
2.3設(shè)置響應(yīng)體
應(yīng)用場(chǎng)景: 瀏覽器顯示的內(nèi)容, 下載文件等.
response 以流的形式,將內(nèi)容輸出給瀏覽器
response.getWriter() 獲取響應(yīng)體的字符輸出流,輸出頁面的時(shí)候使用
response.getOutputStream() 獲取響應(yīng)體的字節(jié)輸出流,輸出文件(圖片,avi等。。。。)的時(shí)候使用
通過這兩個(gè)流可以向?yàn)g覽器輸出 響應(yīng)體內(nèi)容.
注意問題:
1 文件數(shù)據(jù)傳輸: getOutputStream 手動(dòng)生成響應(yīng)內(nèi)容時(shí) 使用 getWriter
2 getOutputStream 和 getWriter 相互排斥,不能同時(shí)使用,否則會(huì)沖突.
3 tomcat會(huì)自動(dòng)調(diào)用response輸出流的 close方法和flush方法, 因此不需要我們手動(dòng)關(guān)閉流.
2.3.1需求: 向?yàn)g覽器輸出一個(gè)百度的超鏈接 的html頁面
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 需求: 向?yàn)g覽器輸出一個(gè)百度的超鏈接 的html頁面
response.setContentType("text/html;charset=utf-8");
response.getWriter().println("<html>");
response.getWriter().println("<head><title>百度超鏈接</title></head>");
response.getWriter().println("<body>");
response.getWriter().println("<a );
response.getWriter().println("</body>");
response.getWriter().println("</html>");
}
頁面效果:

2.4下載介紹
2.4.1下載方式介紹
文件的下載有2種方式可以完成:
1、超鏈接形式:
<a href=”資源的路徑” >資源名稱</a>
問題:
1 中文文件名亂碼
2 圖片和文本直接解析而不是下載
3 只有rar壓縮文件,才直接下載
2、使用Servlet通知瀏覽器下載:
1 修改請(qǐng)求路徑,將要下載的文件名稱,發(fā)送給服務(wù)器的servlet,讓servlet進(jìn)行處理
2 加載服務(wù)器上的文件資源
3 提示瀏覽器,以下載的方式,獲取服務(wù)器資源
4 使用IO的方式,將文件數(shù)據(jù)輸出到瀏覽器(response.getOutputStream();)
2.4.2服務(wù)器端寫程序下載(重點(diǎn):必須掌握)
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
request.setCharacterEncoding("utf-8");
response.setCharacterEncoding("utf-8");
// 1.獲取下載的文件名
String fileName = request.getParameter("fileName");
//fileName = new String(fileName.getBytes("iso-8859-1"), "utf-8");
// 2.獲取資源在服務(wù)器上的位置
ServletContext context = config.getServletContext();
String dir = context.getRealPath("/WEB-INF/file");
File file = new File(dir, fileName);
// 3.告知瀏覽器,打開對(duì)話框
// Content-Type 設(shè)置文件媒體格式
response.setContentType(context.getMimeType(fileName));
// 處理中文文件名亂碼
// 谷歌
fileName = URLEncoder.encode(fileName, "utf-8");
//fileName=new String (fileName.getBytes("iso-8859-1"),"utf-8");
// Content-Disposition 設(shè)置要被下載的文件名
response.setHeader("Content-Disposition", "attachment;fileName=" + fileName);
// 4.使用IO技術(shù),將數(shù)據(jù)發(fā)送(使用response對(duì)象發(fā)送數(shù)據(jù))
// 獲取輸入流
FileInputStream ins = new FileInputStream(file);
// 獲取輸出流
ServletOutputStream out = response.getOutputStream();
byte[] buf = new byte[8192];
int len = 0;
while ((len = ins.read(buf)) != -1) {
out.write(buf, 0, len);
}
ins.close();
}
<body>
<a href="DownLoadServlet?fileName=cat.jpg">cat.jpg</a>
<a href="DownLoadServlet?fileName=2.jpg">2.jpg</a>
<a href="DownLoadServlet?fileName=3.txt">3.txt</a>
<a href="DownLoadServlet?fileName=heidisql.rar">heidisql.rar</a>
<a href="DownLoadServlet?fileName=極客營(yíng).txt">極客營(yíng).txt</a>
</body>
注意:如果MyEclipse10.0無法使用BASE64Encoder這個(gè)類(無法導(dǎo)入這個(gè)包),按一下方式解決。
解決方法:按照如下方法設(shè)置Eclipse導(dǎo)入%JAVA_HOME%\jre\lib目錄下的rt.jar包即可,Project->Properties,選擇Java Build Path設(shè)置項(xiàng),再選擇Libraries標(biāo)簽,Add External Jars添加%JAVA_HOME%\jre\lib\rt.jar就可以使用
如果還是不行,可以再修改項(xiàng)目的JDK,將JDK版本改成本地安裝的JDK版本
小結(jié):
1)先修改頁面——發(fā)送要下載的文件的文件名

2)定位要被下載的文件的位置(獲取文件名的時(shí)候,處理中文亂碼問題)
3)設(shè)置文件的媒體格式
4)解決中文文件名問題(先要判斷瀏覽器,根據(jù)不同的瀏覽器,不同編碼處理)
5)設(shè)置要被下載的文件名
6)使用IO技術(shù)將數(shù)據(jù)發(fā)送給瀏覽器(response獲取的out輸出流,不用手動(dòng)關(guān)閉,自己使用的輸入流,需要手動(dòng)關(guān)閉)
附錄:學(xué)員問題解答
問題1 :ServletContext的getContext(),getContextPath(),getRealPath() 以及HttpServletRequst的getContextPath(),getRequestURI() getRequestURL() getServletPath() 這些方法獲得路徑有什么區(qū)別和聯(lián)系
答: ServletContext
getContext() :獲取指定路徑的項(xiàng)目,它的ServletContext對(duì)象,但是,處于安全考慮,如果獲取其他的項(xiàng)目ServletContext都會(huì)拿到null,所以方法不常用
getContextPath():獲取當(dāng)前項(xiàng)目根路徑
getRealPath():獲取當(dāng)前項(xiàng)目中,指定資源的路徑
HttpServletRequst:
getContextPath():獲取當(dāng)前項(xiàng)目根路徑(同上)
getRequestURI(): 獲取請(qǐng)求地址,不包含協(xié)議,地址,端口
getRequestURL(): 獲取請(qǐng)求地址,包含協(xié)議,地址,端口
問題2 :ServletContext 與Servlet的在服務(wù)器中存在形式被稱為什么? 使用ServletContext會(huì)出現(xiàn)并發(fā)問題么?如何解決
答:1 對(duì)象
ServletContext tomcat在底層的實(shí)現(xiàn)類是org.apache.catalina.core.ApplicationContextFacade,這是一個(gè)容器存取數(shù)據(jù)的
Servlet 是處理請(qǐng)求和響應(yīng)的對(duì)象,由我們自己實(shí)現(xiàn)
2 ServletContext對(duì)象在存取數(shù)據(jù)的時(shí)候使用ConcurrentHashMap,線程安全。