菜鳥學JavaWeb之——入門、Tomcat安裝,部署,創建Web項目、Servlet執行原理,生命週期

引入

相關概念

  • 軟件架構

    • C/S:客戶端 / 服務器端
    • B/S:瀏覽器 / 服務器端

    所謂CS是指 Client—Server(CS架構:客戶端和服務器要分離,分別要開發出來客戶端和服務器)

    ​ 優勢:傳輸的數據是可以自定義的、傳輸的通道時加密的、對於數據具有更好的安全性

    ​ 缺點:開發成本大、使用成本大(必須要下載客戶端裝上才能用)

    Java不適合做CS架構,做出來的用戶界面奇醜無比

    所謂的BS是指 Browser—Server

    ​ 特點:傳輸使用協議一般是HTTP協議(超文本傳輸協議),而HTTP承載層使用TCP協議,而對於開發人員,要做的事情就是去實現一個前端的界面,讓瀏覽器可以解析出來這個界面就可以了,傳輸的數據不是那麼的安全,傳輸數據的格式是既定的。

    ​ 優點:開發成本低,特別低、使用成本低,也特別低。

  • 資源分類

    • 靜態資源:所有用戶訪問後,得到的結果都是一樣的,稱爲靜態資源。靜態資源可以直接被瀏覽器解析。

      如:HTML、CSS、JavaScript

    • 動態資源:每個用戶 訪問相同資源後,得到的結果可能不一樣,稱爲動態資源。動態資源被訪問後,需要先轉換爲靜態資源,在返回給瀏覽器。

      如:servlet、jsp、php、asp

  • 網絡通信三要素

    • IP:電子設備(計算機)在網絡中的唯一標識

    • 端口:應用程序在計算機中的唯一標識。0~65535

    • 傳輸協議:規定了數據傳輸的規則(就比如瀏覽器和客戶端交流需要用什麼語言,英語?漢語?)

      TCP協議:安全,三次握手,速度慢

      UDP協議:不安全,速度快

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-ttvMma8I-1586143993118)(C:\Users\張澳琪\AppData\Roaming\Typora\typora-user-images\image-20200405164541347.png)]

一、Web服務器軟件

引入

服務器:安裝了服務器軟件的計算機

服務器軟件:接受用戶的請求,處理請求,做出響應

Web服務器軟件(也稱:Web容器):接受用戶的請求,處理請求,做出響應

  • 在Web服務器軟件中,可以部署Web項目,讓用戶通過瀏覽器訪問這個項目

常見的Java相關的網絡容器

  • webLogic(Oracle公司)、webSphere(IBM公司)、JBOSS(JBOSS公司):支持所有的JavaEE規範,收費
  • Tomcat:Apache基金組織,中小型JavaEE服務器,僅支持少量的JavaEE規範(如:Servlet、JSP)

1. Tomcat

Tomcat:Web容器

1.1 下載、安裝、啓動、配置、部署

官網:https://tomcat.apache.org/download-80.cgi

根據需求,下載zip壓縮包

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-qQo1uzNt-1586143993120)(C:\Users\張澳琪\AppData\Roaming\Typora\typora-user-images\image-20200405170738306.png)]

下載成功後解壓文件夾即安裝成功!

目錄結構:
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-QdL8rSDH-1586143993125)(C:\Users\張澳琪\AppData\Roaming\Typora\typora-user-images\image-20200405171425091.png)]
啓動

  • bin/startup.bat:運行即可
  • 訪問:瀏覽器輸入:http://localhost:8080
  • 可能遇到的問題
    • 黑框一閃而過(JAVA_HOME沒有配置)

正確配置方式

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-Jw9wxsXy-1586143993127)(C:\Users\張澳琪\AppData\Roaming\Typora\typora-user-images\image-20200405172212977.png)]

startup.bat是批處理文件,裏面寫的就是dos命令。

catalina.bat中有一條dos命令,使用環境變量的JAVA_HOME,找到JDK,然後才能運行Tomcat。Tomcat是純Java編寫的,他的啓動依賴於電腦上安裝的JDK

**修改端口號(默認是8080):**在conf/server.xml中修改

部署:

  • 直接將項目放在webapps目錄下即可。

    ​ 或者:將項目打包成war包,再將war包放在webapps目錄下。(war包會自動解壓縮)

2. 將Tomcat集成到IDEA中,並且創建JavaEE的項目,部署項目

2.1 手動集成Tomcat

Run—>Edit Configurations

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-CFLzHADU-1586143993127)(C:\Users\張澳琪\AppData\Roaming\Typora\typora-user-images\image-20200405175600327.png)]

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-gxGsRE7p-1586143993129)(C:\Users\張澳琪\AppData\Roaming\Typora\typora-user-images\image-20200405175737404.png)]

接下來點擊apply就成功了

2.2 創建Web項目

一般Tomcat的啓動都伴隨這Web項目的啓動。所以接下來創建Web項目(創建web項目時其實就會自動集成好了Tomcat)

File—>New—>Project

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-o8LOTqj0-1586143993129)(C:\Users\張澳琪\AppData\Roaming\Typora\typora-user-images\image-20200405175237969.png)]

部署:
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-VL5Z6BoL-1586143993130)(C:\Users\張澳琪\AppData\Roaming\Typora\typora-user-images\image-20200405184118817.png)]虛擬路徑指項目的訪問路徑

熱部署:
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-JSq0tCTT-1586143993130)(C:\Users\張澳琪\AppData\Roaming\Typora\typora-user-images\image-20200405180842783.png)]

二、Servlet

概念:server applet:運行在服務器端的小程序

  • Servlet就是一個接口,這個接口定義了Java類被瀏覽器訪問到(Tomcat識別)的規則

將來自定義一個類,實現Servlet接口,覆寫方法。

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-vzca7jWL-1586143993130)(C:\Users\張澳琪\AppData\Roaming\Typora\typora-user-images\image-20200405182857343.png)]

配置Servlet

寫一個Servlet就要配置一個Servlet

web.xml是Tomcat找到其他類的指路標,然後用類加載反射機制加載這些類,所以要在web-app裏寫好路標(xml其實就是用來寫後臺的配置文件用的)

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
         version="4.0">
    <servlet>
        <servlet-name>demo1</servlet-name>
        <servlet-class>com.home.java.service.ServletDemo1</servlet-class>  
    </servlet>
    
    <servlet-mapping>
        <servlet-name>demo1</servlet-name>
        <url-pattern>/demo1.do</url-pattern>
    </servlet-mapping>

</web-app>

1. Tomcat執行Servlet的執行原理:

  • 當服務器接受到客戶端瀏覽器的請求後,會解析請求URL路徑,獲取訪問的Servlet的資源路徑
  • 查找web.xml文件,看是否有對應的標籤體內容
  • 如果有,則在找到對應的全類名
  • Tomcat會將字節碼文件加載今內存,並創建其對象
  • 調用其方法

如圖:

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-Qxd7aX8P-1586143993131)(C:\Users\張澳琪\AppData\Roaming\Typora\typora-user-images\image-20200405190701042.png)]

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-10alyhiP-1586143993131)(C:\Users\張澳琪\AppData\Roaming\Typora\typora-user-images\image-20200406112950261.png)]

2. Servlet的生命週期

  • init():初始化方法,在Servlet被創建時執行。且只會執行一次
  • service():提供服務方法,每一次Servlet被訪問時,執行。執行多次
  • destroy():銷燬方法,在服務器正常關閉時,纔會執行。執行一次
package com.home.java.service;
/**
 * @author ZAQ
 * @create 2020-04-05 18:49
 */
public class ServletDemo1 implements Servlet {

    public ServletDemo1() {
        System.out.println("我是構造方法");
    }

    @Override
    public void init(ServletConfig servletConfig) throws ServletException {
        System.out.println("我是init方法");
    }

    @Override
    public ServletConfig getServletConfig() {
        return null;
    }

    @Override
    public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
        System.out.println("我是Service");
    }

    @Override
    public String getServletInfo() {
        return null;
    }

    @Override
    public void destroy() {

    }
}

Servlet什麼時候被創建?

  • 默認情況下,第一次被訪問時,Servlet被創建

  • 但是也可以配置執行Servlet的創建時機

    在標籤下配置

    • 設置第一次被訪問時創建

      <load-on-startup>的值爲負數

    • 設置在服務器啓動時創建

      <load-on-startup>的值爲0或正整數

執行順序:先執行ServletDemo1()方法創建對象(構造器),然後執行init()方法,然後是Service()方法

Servlet的init方法只執行一次,說明一個Servlet在內存中只存在一個對象,Servlet是單例的

  • 多個用戶同時訪問時,可能存在線程安全問題
  • 解決:儘量不要在servlet中定義成員變量。即使定義了成員變量,也不要修改其值

destroy()方法在Servlet被銷燬之前執行,一般用於釋放資源(init()用於加載資源)

3. Servlet註解配置

由於每個Servlet都要在xml文件中配置,過於麻煩,所以引入註解配置,方便快捷

註解配置:只需要在類上面寫@WebServlet("/demo1.do")即可

路徑定義規則:

  • /xxx
  • *.do(注意沒有 / )

Tomcat真正訪問的是“Tomcat部署的web項目”,“Tomcat部署的web項目”對應着“工作空間項目”的web目錄下的所有資源。

WEB-INF目錄下的資源不能被瀏覽器直接訪問。

4. Servlet的體系結構

Servlet—接口

  • GenericServlet—抽象類(實現了Servlet接口)
    • HttpServlet—抽象類(繼承GenericServlet)

GenericServlet:將Servlet接口中的其他的方法做了默認空實現,只將service()方法作爲抽象

HttpServlet:對Http協議的一種封裝,簡化操作

  • 定義類繼承HttpServlet
  • 覆寫doGet/doPost方法

前端通過form表單發送數據到Servlet中,我們可以通過Servlet中的service()裏的一些操作獲取這些數據。所以service()裏的第一件事就是獲取數據,但是在獲取數據之前要判斷form表單的請求方式。這個過程是繁瑣的,並且是每個Servlet都要完成的操作,所以Sun公司提供了一個HttpServlet類,他幫助我們完成了這些操作,以後我們不再需要寫判斷請求方式的過程,只需要重寫doGet()、doPost()方法即可。

HttpServlet源碼:

protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String method = req.getMethod();//獲取請求方式
        long lastModified;
    	//判斷是那種請求方式,如果是GET就...如果是Post就...
        if (method.equals("GET")) {
            lastModified = this.getLastModified(req);
            if (lastModified == -1L) {
                this.doGet(req, resp);
            } else {
                long ifModifiedSince;
                try {
                    ifModifiedSince = req.getDateHeader("If-Modified-Since");
                } catch (IllegalArgumentException var9) {
                    ifModifiedSince = -1L;
                }

                if (ifModifiedSince < lastModified / 1000L * 1000L) {
                    this.maybeSetLastModified(resp, lastModified);
                    this.doGet(req, resp);//如果是GET請求,則調用doGet
                } else {
                    resp.setStatus(304);
                }
            }
        } else if (method.equals("HEAD")) {
            lastModified = this.getLastModified(req);
            this.maybeSetLastModified(resp, lastModified);
            this.doHead(req, resp);
        } else if (method.equals("POST")) {
            this.doPost(req, resp);//如果是Post請求,則調用doPost
        } else if (method.equals("PUT")) {
            this.doPut(req, resp);
        } else if (method.equals("DELETE")) {
            this.doDelete(req, resp);
        } else if (method.equals("OPTIONS")) {
            this.doOptions(req, resp);
        } else if (method.equals("TRACE")) {
            this.doTrace(req, resp);
        } else {
            String errMsg = lStrings.getString("http.method_not_implemented");
            Object[] errArgs = new Object[]{method};
            errMsg = MessageFormat.format(errMsg, errArgs);
            resp.sendError(501, errMsg);
        }

    }

內容持續更新中…

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章