1. 程式人生 > >第9章WEB09-Servlet篇

第9章WEB09-Servlet篇

Servlet篇 javaweb

今日任務
? 完成系統的登錄的功能
? 完成登錄系統後頁面定時跳轉
? 記錄系統登錄成功後,系統被訪問多少次
教學導航
教學目標
了解HTTP協議
掌握Servlet的編寫
了解ServletConfig的使用
掌握ServletContext對象的使用
教學方法
案例驅動法
1.1 上次課內容回顧:
XML :

  • XML的概述:
    • 什麽是XML:可擴展標記語言.
    • XML的作用:作為軟件的配置文件,傳輸和存取數據.
    • XML的使用:
      • XML的基本語法:
        • 標簽必須有開始和結束.
        • 必須有跟標簽
        • 區分大小寫.
        • 正確嵌套.
      • XML的文檔聲明:<?xml version=”1.0” encoding=”UTF-8”?>
      • XML的註釋:<!-- 註釋 -->
      • XML的元素:
        • 命名規範:不能以數字開頭,標簽包含字母或數字,不能以xml開頭,不能出現空格 冒號.
      • XML的屬性:
        • 命名規範:與元素一致.屬性必須加引號.
      • XML的特殊字符和CDATA區.
  • XML的解析:
    • XML的解析方式有哪些:
      • DOM和SAX:
        • DOM一次性將文檔加載到內存,形成樹形結構.如果文檔過大容易導致內存溢出.方便增刪改的操作.
        • SAX邊讀邊解析的方式,如果文檔大,不會導致內存溢出,但是不能進行增刪改.
    • 常見的解析XML的API:
      • JAXP,JDOM,DOM4J...
    • 使用DOM4J解析XML:
  • XML的約束:(了解)
    • XML的約束有哪些區別是什麽?
      • DTD和Schame:
        • DTD的語法是自成一體,Schema使用的XML的語法.
        • Schema有比DTD更強大的語義和語法的約束.
        • Schema支持名稱空間.
          Tomcat
  • WEB的相關的內容:
    • 軟件架構:
    • 服務器:就是一臺電腦,這臺電腦上安裝了服務器的軟件.
    • 常見的WEB服務器:WebSphere,WebLogic,Tomcat,JBoss,IIS,apache...
    • 使用Tomcat:
  • 下載和安裝Tomcat:
  • Tomcat的目錄的結構:
    • tomcat/conf:
    • tomcat/webapps:
    • tomcat/logs:
    • tomcat/bin:
  • 發布一個web項目到服務器的方式:
    • 一、復制項目到webapps下.
    • 二、修改server.xml,配置<Context path=”” docBase=””/>
    • 三、在conf/Catalina/localhost/xxx.xml 配置<Context docBase=””/>
  • 使用STS配置Tomcat:
    1.2 案例一:使用Servlet完成一個用戶登錄的案例.1.2.1 需求:
    在網站的首頁上,登錄的鏈接,點擊登錄的鏈接,可以跳轉到登錄的頁面.在登錄的頁面中輸入用戶名和密碼點擊登錄的案例.完成登錄的功能.
    技術分享圖片
    1.2.2 分析:1.2.2.1 技術分析:
    【HTTP的協議的概述】
    ? 協議:
  • 什麽是協議:規定雙方需要遵守的規則.
    ? HTTP協議:
  • 什麽是HTTP協議:用來規定瀏覽器與服務器之前需要遵守的規則.
    技術分享圖片
    ? HTTP協議的作用:規範瀏覽器和服務器之間的數據傳遞.
    ? HTTP協議的特點:
  • 基於請求和響應的模型.
    • 必須先有請求後有響應.
    • 請求和響應必須成對出現.
  • 默認的端口號是80.
    ? HTTP協議的版本:
  • 1.0 :每次響應後即刻關閉了連接.
  • 1.1 :現在使用.不是每次響應後掛斷,等待長時間以後沒有請求會掛斷.
    【HTTP協議的演示】
    抓包分析:GET方式:
  • 請求部分:
    GET /day09/demo1-http/demo2.html?name=aaa&age=23 HTTP/1.1
    Accept: text/html, application/xhtml+xml, /
    X-HttpWatch-RID: 59176-10011
    Referer: http://localhost:8080/day09/demo1-http/demo1.html
    Accept-Language: zh-CN
    User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64; Trident/7.0; rv:11.0) like Gecko
    Accept-Encoding: gzip, deflate
    Host: localhost:8080
    DNT: 1
    Connection: Keep-Alive
    抓包分析:POST方式:
    POST /day09/demo1-http/demo2.html HTTP/1.1
    Accept: text/html, application/xhtml+xml, /
    X-HttpWatch-RID: 59176-10031
    Referer: http://localhost:8080/day09/demo1-http/demo1.html
    Accept-Language: zh-CN
    User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64; Trident/7.0; rv:11.0) like Gecko
    Content-Type: application/x-www-form-urlencoded
    Accept-Encoding: gzip, deflate
    Host: localhost:8080
    Content-Length: 15
    DNT: 1
    Connection: Keep-Alive
    Cache-Control: no-cache
    name=bbb&age=38
  • 響應部分:
    HTTP/1.1 200 OK
    Server: Apache-Coyote/1.1
    Accept-Ranges: bytes
    ETag: W/"145-1461807615933"
    Last-Modified: Thu, 28 Apr 2016 01:40:15 GMT
    Content-Type: text/html
    Content-Length: 145
    Date: Thu, 28 Apr 2016 01:43:52 GMT
    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="UTF-8">
    <title>Insert title here</title>
    </head>
    <body>
    <h1>Demo2.html</h1>
    </body>
    </html>
    【HTTP協議的詳解】
    ? 請求部分
  • 請求行
    • 提交方式:
      • 提交方式有很多,常用的GET和POST:
      • GET和POST的區別:
        • GET的提交的參數會顯示到地址欄上,而POST不顯示.
        • GET往往是有大小限制的,而POST沒有大小的限制.
        • GET沒有請求體,而POST有請求體.
    • 提交路徑:
    • 協議版本:
  • 請求頭
    • 都是鍵值對的形式顯示的.一般一個key對應一個value,也有個別的是一個key對應多個value.
    • User-Agent :代表瀏覽器的類型. --- 文件下載:下載中文文件:IE使用URLEncodor進行編碼,而Firefox使用Base64編碼.
    • Referer :代表的是網頁的來源. --- 防盜鏈.
    • If-Modified-Since :通常與響應中的頭Last-Modified一起使用查找本地緩存.
  • 請求體
    • 就是POST提交方式的提交的參數.
      ? 響應部分
  • 響應行:
    • 協議版本
    • 狀態碼 :
      • 200 :成功
      • 302 :重定向
      • 304 :查找本地緩存
      • 404 :資源不存在
      • 500 :服務器內部錯誤
    • 狀態碼描述
  • 響應頭:鍵值對,一般一個key對應一個value,也有一個key對應多個value.
    • Last-Modified :與請求中的If-Modified-Since一起使用查找本地緩存.
    • Content-Dispostion :文件下載的使用使用的一個頭信息.
    • Location :重定向的跳轉的路徑.
    • Refresh :定時刷新/定時跳轉.
  • 響應體:顯示瀏覽器的頁面的內容.
    【Servlet的概述】
    ? 什麽是Servlet:
  • 就是一個運行在WEB服務器上的小的Java程序,用來接收和響應從客戶端發送過來的請求,通常使用HTTP協議.
  • Servlet就是SUN公司提供的一個動態網頁開發技術.
    ? Servlet的作用:
  • 用來處理從客戶端瀏覽器發送的請求,並且可以對請求作出響應
    ? 使用Servlet:
  • 編寫一個類實現Servlet接口.
  • 將編寫的這個類配置到服務器中.
    ? Servlet的入門:
  • 編寫類:
    public class ServletDemo1 implements Servlet{@Override
    br/>@Override
  • 為用戶處理請求和響應的方法.
    */
    public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
    res.getWriter().println("Hello Servlet...");
    }
    ...
    }
  • 配置:

    test1 com.itheima.a_servlet.ServletDemo1 test1 /ServletDemo1
  • 訪問:
    http://localhost:8080/day09/ServletDemo1
    【使用ServletRequest接收參數】
    技術分享圖片
  • String getParameter(String name); ---用於接收一個名稱對應一個值的數據.
  • String[] getParameterValues(String name);---用於接收一個名稱對應多個值的數據.
  • Map getParameterMap(); ---用於接收表單中的所有的數據,Map的key是表單提交的參數名稱,Map的value是提交參數的值.
  • Enumeration getParameterNames() ---用於獲取表單中提交的所有的參數的名稱.
    【Servlet的訪問流程】
    【Servlet的實現的關系】
    Servlet :接口

    GenericServlet :通用的Servlet

    HttpServlet :HttpServlet

  • 編寫一個類繼承HttpServlet,重寫doGet和doPost方法.
  • 配置
    1.2.3 代碼實現1.2.3.1 步驟一:創建數據庫和表:
  • create database day09;
    use day09;
    create table user(
    id int primary key auto_increment,
    username varchar(20),
    password varchar(20),
    nickname varchar(20)
    );
    insert into user values (null,‘aaa‘,‘111‘,‘小鳳‘);
    insert into user values (null,‘bbb‘,‘111‘,‘小童童‘);

    1.2.3.2 步驟二:創建包和類:
    1.2.3.3 步驟三:引入jar包

    • mysql的數據庫的驅動包
    • c3p0連接池的jar包
    • dbutils的包
      1.2.3.4 引入login的頁面
      1.2.3.5 編寫Servlet-->Service-->DAO
      1.2.4 總結:1.2.4.1 Servlet的生命周期:(*****)
      ? 生命周期:就是一個對象從創建到銷毀的過程.
      ? Servlet生命周期:Servlet從創建到銷毀的過程.
    • 何時創建:用戶第一次訪問Servlet創建Servlet的實例
    • 何時銷毀:當項目從服務器中移除的時候,或者關閉服務器的時候.
      ? 用戶第一次訪問Servlet的時候,服務器會創建一個Servlet的實例,那麽Servlet中init方法就會執行.任何一次請求服務器都會創建一個新的線程訪問Servlet中的service的方法.在service方法內部根據請求的方式的不同調用doXXX的方法.(get請求調用doGet,post請求調用doPost).當Servlet中服務器中移除掉,或者關閉服務器,Servlet的實例就會被銷毀,那麽destroy方法就會執行.
      1.2.4.2 Servlet的相關的配置:
      【啟動時創建Servlet】
      Servlet默認是在第一次訪問的時候創建的.現在讓Servlet在服務器啟動的時候創建好.進行對Servlet的配置:
      在web.xml中在<servlet></servlet>標簽中配置:
    • <load-on-startup>2</load-on-startup> --- 傳入正整數,整數越小,被創建的優先級就越高.
      【url-pattern的配置】
      url-pattern配置方式共有三種:
      1.完全路徑匹配 :以 / 開始 例如: /ServletDemo4 , /aaa/ServletDemo5 , /aaa/bbb/ServletDemo6
      2.目錄匹配 :以 / 開始 需要以 結束. 例如: / ,/aaa/ ,/aaa/bbb/
      3.擴展名匹配 :不能以 / 開始 以 開始的. 例如: .do , *.action
      * 錯誤的寫法 : /.do
      有如下的配置:
      <servlet>
      <servlet-name>ServletDemo4</servlet-name>
      <servlet-class>com.itheima.a_servlet.ServletDemo4</servlet-class>
      </servlet>
      <servlet-mapping>
      <servlet-name>ServletDemo4</servlet-name>
      <url-pattern>/ServletDemo4</url-pattern>
      </servlet-mapping>
      <servlet>
      <servlet-name>ServletDemo5</servlet-name>
      <servlet-class>com.itheima.a_servlet.ServletDemo5</servlet-class>
      </servlet>
      <servlet-mapping>
      <servlet-name>ServletDemo5</servlet-name>
      <url-pattern>/
      </url-pattern>
      </servlet-mapping>
      <servlet>
      <servlet-name>ServletDemo6</servlet-name>
      <servlet-class>com.itheima.a_servlet.ServletDemo6</servlet-class>
      </servlet>
      <servlet-mapping>
      <servlet-name>ServletDemo6</servlet-name>
      <url-pattern>.do</url-pattern>
      </servlet-mapping>
      如果訪問地址:
      http://localhost:8080/day09/ServletDemo4 :第一個
      http://localhost:8080/day09/aaa.do :第二個
       完全路徑匹配 > 目錄匹配 > 擴展名匹配
      1.2.4.3 開發中的路徑的編寫:
      ? 相對路徑:都是需要找位置相對關系.不能以 / 開始的.
    • ./ 當前路徑 ../上一級目錄
    • 使用相對路徑訪問:
      • http://localhost:8080/day09/demo4-url/demo1.html
      • http://localhost:8080/day09/ServletDemo6
        ? 絕對路徑:不需要找位置相對關系. 以 / 開始的.
    • 絕對路徑中分為客戶端路徑和服務器端路徑:

      • 客戶端路徑一定要加工程名. /day09/ServletDemo6
      • 服務器端路徑不需要加工程名. /ServletDemo6
        1.3 案例二:登錄成功以後5秒鐘跳轉到另一個頁面.1.3.1 需求:
        在登錄成功後,頁面5秒鐘跳轉到其他的一個頁面.
        1.3.2 分析:1.3.2.1 技術分析:
        【使用Http協議中的Refresh頭信息】
        Refresh之前已經介紹可以定時頁面跳轉.需要使用程序設置頭信息才可以.
        【response中設置響應頭】
        技術分享圖片
    • addHeader(String name,String value); --- 針對一個key對應多個value的響應頭.
      • addDateHeader(String name,long date);
      • addIntHeader(String name,int value);
    • setHeader(String name,String value); --- 針對一個key對應一個value的響應頭.
      • setDateHeader(String name,long date);
      • setIntHeader(String name,int value);
        例如:頭信息: xxx:aaa
      • addHeader(“xxx”,”bbb”); -->xxx:aaa,bbb
      • setHeader(“xxx”,”bbb”); -->xxx:bbb
        1.3.3 代碼實現:
    在登錄成功後的代碼上,定時的跳轉.
    public class UserRefreshServlet extends HttpServlet {
    private static final long serialVersionUID = 1L;
    
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    try {
    // 解決向頁面輸出中文的亂碼問題!!!
    response.setContentType("text/html;charset=UTF-8");
    // 1.接收表單提交的參數.
    String username = request.getParameter("username");
    String password = request.getParameter("password");
    // 2.封裝到實體對象中.
    User user = new User();
    user.setUsername(username);
    user.setPassword(password);
    // 3.調用業務層處理數據.
    UserService userService = new UserService();
    User existUser = userService.login(user);
    // 4.根據處理結果顯示信息(頁面跳轉).
    if(existUser == null){
    // 登錄失敗
    response.getWriter().println("<h1>登錄失敗:用戶名或密碼錯誤!~</h1>");
    }else{
    // 登錄成功
    // response.getWriter().println("Login Success...");
    response.getWriter().println("<h1>登錄成功!您好:"+existUser.getNickname()+"</h1>");
    response.getWriter().println("<h3>頁面將在5秒後跳轉!</h3>");
    response.setHeader("Refresh", "5;url=/day09/demo5-refresh/index.html");
    }
    } catch (Exception e) {
    e.printStackTrace();
    }
    }
    
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    doGet(request, response);
    }
    
    }

    1.3.4 總結:1.3.4.1 使用JS控制讀秒的效果.

    <script type="text/javascript">
    var time = 5;
    window.onload = function(){
    setInterval(‘changeTime()‘,1000);
    }
    function changeTime(){
    time--;
    document.getElementById("s1").innerHTML = time;
    }
    </script>

    1.4 案例三:記錄網站的登錄成功的人數.1.4.1 需求:
    登錄成功後,5秒後跳轉到某個頁面,在頁面中顯示您是第x位登錄成功的用戶.
    1.4.2 分析:1.4.2.1 技術分析:
    【ServletContext對象】
    ***** ServletContext對象存取數據,存的數據都是有一定的作用的範圍的.這種對象稱為是域對象.

    • 用來存取數據:
      技術分享圖片
    • 用來向ServletContext中存入數據.
      技術分享圖片
    • 用來從ServletContext中獲取數據.
      技術分享圖片
    • 用來從ServletContext中移除數據.
      1.4.3 代碼實現:
    /**
     * 登錄代碼的Servlet
     */
    public class UserCountServlet extends HttpServlet {
    private static final long serialVersionUID = 1L;
    
    @Override
    public void init() throws ServletException {
    // 初始化一個變量count的值為0.
    int count = 0;
    // 將這個值存入到ServletContext中.
    this.getServletContext().setAttribute("count", count);
    }
    
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    try {
    response.setContentType("text/html;charset=UTF-8");
    // 1.接收表單提交的參數.
    String username = request.getParameter("username");
    String password = request.getParameter("password");
    // 2.封裝到實體對象中.
    User user = new User();
    user.setUsername(username);
    user.setPassword(password);
    // 3.調用業務層處理數據.
    UserService userService = new UserService();
    User existUser = userService.login(user);
    // 4.根據處理結果顯示信息(頁面跳轉).
    if(existUser == null){
    // 登錄失敗
    response.getWriter().println("<h1>登錄失敗:用戶名或密碼錯誤!</h1>");
    }else{
    // 登錄成功
    // 記錄次數:
    int count = (int) this.getServletContext().getAttribute("count");
    count++;
    this.getServletContext().setAttribute("count", count);
    response.getWriter().println("<h1>登錄成功:您好:"+existUser.getNickname()+"</h1>");
    response.getWriter().println("<h3>頁面將在5秒後跳轉!</h3>");
    response.setHeader("Refresh", "5;url=/day09/CountServlet");
    }
    } catch (Exception e) {
    e.printStackTrace();
    }
    }
    
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    doGet(request, response);
    }
    
    }
    
    public class CountServlet extends HttpServlet {
    private static final long serialVersionUID = 1L;
    
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    // 獲得Count的值。
    response.setContentType("text/html;charset=UTF-8");
    int count = (int) this.getServletContext().getAttribute("count");
    response.getWriter().println("<h1>您是第"+count+"位登錄成功的用戶!</h1>");
    }
    
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    doGet(request, response);
    }
    
    }

    1.4.4 總結:1.4.4.1 ServletConfig:了解.獲得Servlet的配置信息.
    技術分享圖片

    • String getServletName(); ---獲得Servlet在web.xml中配置的name的值.
    • String getInitParameter(String name); ---獲得Servlet的初始化參數的.
    • Enumeration getInitParameterNames(); ---獲得所有Servlet的初始化參數的名稱.
      1.4.4.2 ServletContext:重要
      ServletContext的作用:
    • 1.用來獲得全局初始化參數.
    • 2.用來獲得文件的MIME的類型.
    • 3.作為域對象存取數據.
      ServletContext是一個域對象.
      • 作用範圍:整個web工程.
      • 創建:服務器啟動的時候,tomcat服務器為每個web項目創建一個單獨ServletContext對象.
      • 銷毀:服務器關閉的時候,或者項目從服務器中移除的時候.
    • 4.用來讀取web項目下的文件.

    第9章WEB09-Servlet篇