1. 程式人生 > >第10章WEB10-request&response篇

第10章WEB10-request&response篇

javaweb 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

      GenericServlet

      HttpServlet

  • ServletConfig對象:用來獲得Servlet的配置信息.
  • ServletContext對象:

    • 1.獲得全局初始化參數
    • 2.獲得文件的MIME的類型
    • 3.作為域對象存取數據.
    • 4.讀取web項目中的文件.
      1.2 案例一:讀取WEB工程下的文件.1.2.1 需求:
      現在有一個配置文件在web工程的src下,項目要發布到tomcat中,需要編寫一段程序讀取文件.

      1.2.2 分析:1.2.2.1 技術分析:
      【演示傳統方式讀取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獲得客戶機的信息】
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的解決方案:
  • 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篇