第10章WEB10-request&response篇
? WEB工程下的文件的讀取
? 登錄系統後完成文件下載
? 商城系統註冊功能.
教學導航
教學目標
掌握response設置響應頭
掌握response重定向和轉發的區別
掌握request接收請求參數
掌握request域的作用範圍
教學方法
案例驅動法
1.1 上次課內容回顧:
HTTP :
- Http請求部分:
- 請求行:請求方式 請求路徑 協議版本.
- 請求方式:
- 請求有很多.常用的是GET和POST.
- 區別:get有大小限制,post沒有大小限制,get參數會顯示到地址欄,post不會顯示到地址欄,放入請求體中.
- 請求方式:
- 請求頭:鍵值對.
- Referer:網頁來源.
- User-Agent:瀏覽器信息.
- If-Modified-Since:
- 請求體
- POST提交參數.
- 請求行:請求方式 請求路徑 協議版本.
- Http響應部分:
- 響應行:協議版本 狀態碼 狀態碼描述
- 200,302,304,404,500
- 響應頭:鍵值對.
- Location:重定向.
- Refresh:定時跳轉
- Content-Disposition:文件下載
- Last-Modified
- 響應體
- 顯示到頁面的內容.
Servlet :
- 顯示到頁面的內容.
- 響應行:協議版本 狀態碼 狀態碼描述
- Servlet的概述:SUN公司提供動態網頁開發規範,就是一個小的java程序運行在服務器端的.
- Servlet的入門:
- Servlet的生命周期:
- 第一次訪問該Servlet的時候,服務器創建一個Servlet的實例,init方法就會執行.任何一次從客戶端發送的請求服務器都會創建一個新的線程執行service方法,在service方法內部根據請求方式調用不用的doXXX的方法.當項目從服務器中移除,或者關閉服務器的時候,就會銷毀Servlet,destroy方法就會執行.
- Servlet的相關配置:
- 啟動時加載:
- url-pattern:
- 完全路徑匹配
- 目錄匹配
- 擴展名匹配
- Servlet的繼承關系:
-
Servlet
GenericServletHttpServlet
-
- ServletConfig對象:用來獲得Servlet的配置信息.
-
ServletContext對象:
- 1.獲得全局初始化參數
- 2.獲得文件的MIME的類型
- 3.作為域對象存取數據.
-
4.讀取web項目中的文件.
1.2 案例一:讀取WEB工程下的文件.1.2.1 需求:
現在有一個配置文件在web工程的src下,項目要發布到tomcat中,需要編寫一段程序讀取文件.
【演示傳統方式讀取WEB工程文件】
/**- 傳統方式讀取文件:
-
- 使用的是相對路徑,相對的JVM的路徑.
-
- 但是現在是一個web項目,相對於JVM的路徑的.現在JVM已經交給tomcat管理.
- @throws FileNotFoundException
-
@throws IOException
*/
private void test1() throws FileNotFoundException, IOException {
InputStream is = new FileInputStream("src/db.properties");
Properties properties = new Properties();
properties.load(is);String driverClass = properties.getProperty("driverClass"); String url = properties.getProperty("url"); String username = properties.getProperty("username"); String password = properties.getProperty("password"); System.out.println(driverClass); System.out.println(url); System.out.println(username); System.out.println(password);
}
【使用ServletContext對象讀取WEB項目下的文件】
- InputStream getResourceAsStream(String path); --- 根據提供路徑讀取文件返回一個文件的輸入流.
- String getRealPath(String path); --- 返回一個路徑的磁盤絕對路徑.
1.2.3 代碼實現:1.2.3.1 使用getResourceAsStream讀取
/**
- 使用ServletContext中的getResourceAsStream讀取.
- @throws FileNotFoundException
- @throws IOException
*/
private void test2() throws FileNotFoundException, IOException {
// 獲得ServletContext:
ServletContext context = this.getServletContext();
InputStream is = context.getResourceAsStream("/WEB-INF/classes/db.properties");
Properties properties = new Properties();
properties.load(is);
String driverClass = properties.getProperty("driverClass");
String url = properties.getProperty("url");
String username = properties.getProperty("username");
String password = properties.getProperty("password");
System.out.println(driverClass);
System.out.println(url);
System.out.println(username);
System.out.println(password);
}1.2.3.2 使用getRealPath讀取文件:
/**
* 使用ServletContext中的getRealPath讀取.
* @throws FileNotFoundException
* @throws IOException
*/
private void test3() throws FileNotFoundException, IOException {
// 獲得ServletContext:
ServletContext context = this.getServletContext();
String realPath = context.getRealPath("/WEB-INF/classes/db.properties");
// 獲得該文件的磁盤絕對路徑.
System.out.println(realPath);
InputStream is = new FileInputStream(realPath);
Properties properties = new Properties();
properties.load(is);
String driverClass = properties.getProperty("driverClass");
String url = properties.getProperty("url");
String username = properties.getProperty("username");
String password = properties.getProperty("password");
System.out.println(driverClass);
System.out.println(url);
System.out.println(username);
System.out.println(password);
}
1.2.4 總結:1.2.4.1 ServletContext的功能:
【功能一:讀取全局初始化參數】
配置全局初始化參數:
<context-param>
<param-name>username</param-name>
<param-value>root</param-value>
</context-param>
<context-param>
<param-name>password</param-name>
<param-value>123</param-value>
</context-param>
代碼:
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String username = this.getServletContext().getInitParameter("username");
String password = this.getServletContext().getInitParameter("password");
System.out.println(username+" "+password);
Enumeration<String> e = this.getServletContext().getInitParameterNames();
while(e.hasMoreElements()){
String name = e.nextElement();
String value = this.getServletContext().getInitParameter(name);
System.out.println(name+" "+value);
}
}
【功能二:獲得文件的MIME的類型】
- 獲得文件的MIME的類型.
代碼實現:/** * 獲得文件的MIME的類型 */ private void test2() { String type = this.getServletContext().getMimeType("1.html"); System.out.println(type); }
【功能三:作為域對象存取數據】
範圍:整個web項目.而且全局的對象.
創建:服務器啟動的時候,服務器為每個web項目創建一個單獨的ServletContext對象.
銷毀:服務器關閉的時候銷毀ServletContext.
【功能四:讀取web項目下的文件】
1.2.4.2 類加載器讀取文件:(擴展)
public static void readFile() throws IOException{
// 使用類的加載器來讀取文件.
// 類的加載器用來加載class文件,將class文件加載到內存.
InputStream is = ReadFileUtils.class.getClassLoader().getResourceAsStream("db.properties");
Properties properties = new Properties();
properties.load(is);
String driverClass = properties.getProperty("driverClass");
String url = properties.getProperty("url");
String username = properties.getProperty("username");
String password = properties.getProperty("password");
System.out.println(driverClass);
System.out.println(url);
System.out.println(username);
System.out.println(password);
}
1.3 案例二:登錄成功後,完成文件的下載.1.3.1 需求:
在登錄成功後,頁面跳轉到文件下載的列表的頁面,點擊列表中的某些鏈接,下載文件.
1.3.2 分析:1.3.2.1 技術分析:
【Response的概述】
? Response:代表響應的對象.從服務器向瀏覽器輸出內容.
【Response的常用的API】
? 響應行:
- 設置狀態碼.
? 響應頭: - 針對一個key對應多個value的頭信息.
- 針對一個key對應一個value的頭信息.
? 響應體
【文件下載的方式】
? 一種:超鏈接下載.直接將文件的路徑寫到超鏈接的href中.---前提:文件類型,瀏覽器不支持.
? 二種:手動編寫代碼的方式完成文件的下載. - 設置兩個頭和一個流:
- Content-Type :文件的MIME的類型.
- Content-Disposition :以下載的形式打開文件.
- InputStream :文件的輸入流.
1.3.3 代碼實現1.3.3.1 步驟一:將之前的登錄功能準備好:
1.3.3.2 步驟二:在文件下載列表頁面上添加文件下載的鏈接:
1.3.3.3 步驟三:完成文件下載的代碼的實現:
public class DownloadServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 1.接收參數
String filename = request.getParameter("filename");
// 2.完成文件下載:
// 2.1設置Content-Type頭
String type = this.getServletContext().getMimeType(filename);
response.setHeader("Content-Type", type);
// 2.2設置Content-Disposition頭
response.setHeader("Content-Disposition", "attachment;filename="+filename);
// 2.3設置文件的InputStream.
String realPath = this.getServletContext().getRealPath("/download/"+filename);
InputStream is = new FileInputStream(realPath);
// 獲得response的輸出流:
OutputStream os = response.getOutputStream();
int len = 0;
byte[] b = new byte[1024];
while((len = is.read(b))!= -1){
os.write(b, 0, len);
}
is.close();
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
1.3.4 總結:1.3.4.1 中文文件的下載:
? IE瀏覽器下載中文文件的時候采用的URL的編碼.
? Firefox瀏覽器下載中文文件的時候采用的是Base64的編碼.
/**
* 文件下載的Servlet
*/
public class DownloadServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 1.接收參數
String filename = new String(request.getParameter("filename").getBytes("ISO-8859-1"),"UTF-8");
System.out.println(filename);
// 2.完成文件下載:
// 2.1設置Content-Type頭
String type = this.getServletContext().getMimeType(filename);
response.setHeader("Content-Type", type);
// 2.3設置文件的InputStream.
String realPath = this.getServletContext().getRealPath("/download/"+filename);
// 根據瀏覽器的類型處理中文文件的亂碼問題:
String agent = request.getHeader("User-Agent");
System.out.println(agent);
if(agent.contains("Firefox")){
filename = base64EncodeFileName(filename);
}else{
filename = URLEncoder.encode(filename,"UTF-8");
}
// 2.2設置Content-Disposition頭
response.setHeader("Content-Disposition", "attachment;filename="+filename);
InputStream is = new FileInputStream(realPath);
// 獲得response的輸出流:
OutputStream os = response.getOutputStream();
int len = 0;
byte[] b = new byte[1024];
while((len = is.read(b))!= -1){
os.write(b, 0, len);
}
is.close();
}
public static String base64EncodeFileName(String fileName) {
BASE64Encoder base64Encoder = new BASE64Encoder();
try {
return "=?UTF-8?B?"
+ new String(base64Encoder.encode(fileName
.getBytes("UTF-8"))) + "?=";
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
1.3.4.2 response輸出響應內容的方法:
向頁面響應的方法:
- getOutputStream();
- getWriter();
- 這兩個方法是互斥的.
- 做出響應的時候只能使用其中的一種流響應.
- 輸出中文亂碼的處理:
- 字節流:
- 設置瀏覽器默認打開的編碼:
- resposne.setHeader(“Content-Type”,”text/html;charset=UTF-8”);
- 設置中文字節取出的時候編碼.
- “中文”.getBytes(“UTF-8”);
- 設置瀏覽器默認打開的編碼:
- 字符流:
- 設置瀏覽器打開的時候的編碼
- resposne.setHeader(“Content-Type”,”text/html;charset=UTF-8”);
- 設置response的緩沖區的編碼
- response.setCharacterEncoding(“UTF-8”);
***** 簡化的寫法:response.setContentType(“text/html;charset=UTF-8”);
1.4 案例三:完成用戶註冊的功能:1.4.1 需求:
網站首頁上點擊註冊的鏈接,跳轉到註冊頁面,在註冊頁面中輸入信息.完成註冊:(將數據保存到數據庫中).
1.4.2 分析:1.4.2.1 技術分析:
【Request的概述】
? Request代表用戶的請求.
【Request的API】
功能一:獲得客戶機相關的信息
? 獲得請求方式:
? 獲得請求的路徑:
? 獲得客戶機相關的信息:
? 獲得工程名:
功能二:獲得從頁面中提交的參數:
功能三:作為域對象存取數據:
【演示request獲得客戶機的信息】
- response.setCharacterEncoding(“UTF-8”);
- 設置瀏覽器打開的時候的編碼
- 字節流:
public class RequestServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 獲得請求方式:
String method = request.getMethod();
System.out.println("請求方式:"+method);
// 獲得客戶機的IP地址:
String ip = request.getRemoteAddr();
System.out.println("IP地址:"+ip);
// 獲得用戶的請求的路徑:
String url = request.getRequestURL().toString();
String uri = request.getRequestURI();
System.out.println("獲得請求的URL:"+url);
System.out.println("獲得請求的URI:"+uri);
// 獲得發布的工程名:
String contextPath = request.getContextPath();
System.out.println("工程名:"+contextPath);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
1.4.3 代碼實現:1.4.3.1 步驟一:創建數據庫和表:
create database day10;
use day10;
create table user(
id int primary key auto_increment,
username varchar(20),
password varchar(20),
email varchar(20),
name varchar(20),
sex varchar(10),
telephone varchar(20)
);
1.4.3.2 步驟二:創建包和類:
1.4.3.3 步驟三:引入註冊頁面:
1.4.3.4 步驟四:註冊代碼的實現:
1.4.4 總結:1.4.4.1 處理request接收參數的中文亂碼的問題:
現在無論是GET還是POST提交中文的時候,都會出現亂碼的問題.
解決:
? POST的解決方案:
- POST的參數在請求體中,直接到達後臺的Servlet.數據封裝到Servlet中的request中.request也有一個緩沖區.request的緩沖區也是ISO-8859-1編碼.
- 設置request的緩沖區的編碼:
- request.setCharacterEncoding(“UTF-8”); --- 一定要在接收參數之前設置編碼就OK.
? GET的解決方案:
- request.setCharacterEncoding(“UTF-8”); --- 一定要在接收參數之前設置編碼就OK.
- 1.修改tomcat的字符集的編碼.(不推薦)
- 2.使用URLEncoder和URLDecoder進行編碼和解碼的操作.
- 3.使用String的構造方法:
1.4.4.2 Request作為域對象存取數據:
使用request對象存取數據: - setAttribute(String name,String value);
- Object getAttribute(String name);
request的作用範圍: - 作用範圍就是一次請求的範圍.
- 創建和銷毀:
- 創建:客戶端向服務器發送了一次請求以後,服務器就會創建一個request的對象.
- 銷毀:當服務器對這次請求作出了響應之後.
1.4.4.3 重定向和轉發的區別:(redirect和forward的區別)
- 1.重定向的地址欄會發生變化,轉發的地址欄不變.
- 2.重定向兩次請求兩次響應,轉發一次請求一次響應.
- 3.重定向路徑需要加工程名,轉發的路徑不需要加工程名.
- 4.重定向可以跳轉到任意網站,轉發只能在服務器內部進行轉發.
第10章WEB10-request&response篇