day01-tomcat&servlet入門

day01-tomcat&servlet入門

第一章 web相關知識概述【瞭解】

1、WEB簡介

Web(World Wide Web)即全球廣域網,也稱爲萬維網。網站,去網站瀏覽網頁,看視頻。程序員:數據庫,前端技術,web技術,這些技術的複合。

  1. web發展階段介紹
WEB1.0 網頁是用來閱讀,傳遞信息。 【公司主導】
WEB1.0的任務,是將以前沒有放在網上的人類知識,通過商業的力量,放到網上去;從內容產生者角度看,WEB1.0是商業公司爲主體把內容往網上搬。中國黃頁
WEB2.0 網頁用來交互的。【用戶主導】
例如: 微博、淘寶,社區、交友網站、視頻網站等等 。這類網站開發常用的技術:java,php,.net(微軟技術體系 asp.net c#.net vb.net) 、ruby、python ...
Web2.0 則更注重用戶的交互作用,用戶既是網站內容的瀏覽者,也是網站內容的製造者。
  1. JavaWeb概念說明
Javaweb: 用Java技術來解決相關web互聯網領域的技術總和(Web前端+Web後臺)。
簡而言之: 用java技術開發web服務應用(軟件)。比如:京東網站,就是用Java開發的。我們可以通過瀏覽器訪問。

2、軟件架構模式

​ 生活中,我們從網絡中獲取資源的方式通常有兩種:

1. 通過瀏覽器去訪問網絡資源(B/S);Broswer / Server
2. 打開特定的軟件訪問網絡資源(C/S);Client /Server

​ 例如,我們想要觀看優酷視頻就可以通過以下兩種方式:

【方式一】通過瀏覽器搜索並觀看
【方式二】打開優酷客戶端搜索並觀看
這兩種方式對應的正是我們的兩種軟件結構模式:BS架構和CS架構。

BS架構

B/S架構:又稱Browser/Server架構,即瀏覽器和服務器架構模式。它是通過瀏覽器 和後臺服務器 進行交互的,如淘寶,京東,12306等等。

1. 優點:
   1. 用戶只需要安裝一個瀏覽器即可訪問不同的服務器,不需要安裝很多客戶端,節約硬盤資源;
   2. 系統更新和升級比較方便;
   3. 跨平臺優勢;
2. 缺點:
   1. 動畫效果受瀏覽器限制;
   2. 網站的壓力集中在服務器端。

CS架構

C/S架構:又稱Client/Server架構,及客戶端和服務器架構模式。它是通過客戶端服務器 進行交互的,如QQ,迅雷,360等等。

1. 優點:
   1. 客戶端效果炫,用戶體驗好;
   2. 客戶端能夠進行部分計算功能,減輕服務器的壓力;
2. 缺點:
   1. 需要安裝客戶端,佔用硬盤空間;
   2. 系統升級麻煩;

發展前景

	B/S是基於網頁語言的、與操作系統無關,所以跨平臺也是它的優勢,而且以後隨着網頁語言以及瀏覽器的進步,B/S在表現能力上的處理以及運行的速度上會越來越快,它的缺點將會越來越少。比如,未來的HTML5,在圖形的渲染方面以及音頻、文件的處理上已經非常強大了。所以,B/S架構將是未來的軟件架構趨勢 。

【結論】B/S架構將是未來軟件架構的趨勢。

3、B/S通信模式

1、基於請求-響應交互模型
	客戶端瀏覽器向服務器 發送一個請求
	web服務器向客戶端瀏覽器回送 一個響應 
	一次請求、一次相應
2、必須先有請求 再有響應 
3、請求和響應成對出現

4、WEB資源

​ 通過瀏覽器從網絡中訪問的資源我們稱之爲WEB資源,這些資源可以分爲兩類:靜態資源和動態資源。

1. 靜態資源:指web頁面中供人們瀏覽的數據始終是不變。比如:HTML、CSS、JS、圖片、多媒體。

2. 動態資源:指web頁面中供人們瀏覽的數據是由程序產生的,不同時間點訪問web頁面看到的內容各不相同。
   比如:JSP/Servlet、ASP、PHP

5、URL請求路徑

​ URL (Uniform Resource Locator) ,統一資源定位符是對互聯網上資源位置的一種表示,互聯網上的每個文件都有一個唯一的URL。
書寫完整格式如下:

協議://ip:端口號/資源位置
協議,http、https、ftp等
域名,域名或IP地址,能夠幫我們定位到互聯網上的某一臺服務器
端口號,端口號是一個應用程序在一臺服務器上的編號。http協議的默認端:80
資源位置,用於描述WEB資源在服務器上的位置

參數=值,瀏覽器和服務器交互傳遞的數據。

如:

http://www.itcast.cn/
https://www.baidu.com/s?ie=UTF-8&wd=java

第二章 tomcat服務器

1、服務器概述

1.1 服務器硬件【硬件】

	服務器,也稱伺服器,是提供計算服務的設備。由於服務器需要響應服務請求,並進行處理,因此一般來說服務器應具備承擔服務並且保障服務的能力。
	服務器的構成包括處理器、硬盤、內存、系統總線等,和通用的計算機架構類似,但是由於需要提供高可靠的服務,因此在處理能力、穩定性、可靠性、安全性、可擴展性、可管理性等方面要求較高。併發性
	在網絡環境下,根據服務器提供的服務類型不同,分爲文件服務器,數據庫服務器,應用程序服務器,WEB服務器等。

【小結】可以把服務器理解成一臺電腦主機,只不過這臺電腦需要提供可靠的服務,因此在處理能力,穩定性,安全性方面要求更高。服務器只是一臺設備,必須安裝服務器軟件才能提供服務。

1.2 服務器軟件【軟件】

	服務器軟件本質上是一個應用程序(有代碼編寫而成),運行在服務器設備上。能夠接收請求並根據請求給客戶端響應數據,發佈資源(靜態和動態)。

1.3 常見的web服務器(軟件)

  1. Tomcat:Apache組織提供一個免費開源的小型的服務器軟件。支持Servlet和JSP規範,性能高。 開源,免費,性能高。
  2. WebLogic:Bea公司的一個收費的大型的服務器軟件,後被Oracle收購。支持JAVAEE的所有的規範 收費
  3. WebSphere:IBM公司的一個收費的大型的服務器軟件,支持EE的所有的規範。
  4. JBoss:是一個基於J2EE的開放源代碼的應用服務器。JBoss是一個管理EJB的容器和服務器,JBoss核心服務不包括支持servlet/JSP的WEB容器,一般與Tomcat或Jetty綁定使用。

規範具體表現 接口 實現接口

【注意】今天我們學習的是tomcat服務器。

2、tomcat服務器

2.1 簡介

​ tomcat服務器是一個免費的開源的web應用服務器。是Apache軟件基金會的Jakarta項目中的一個核心項目,由Apache,Sun和其他一些公司及個人共同開發而成。由於有了Sun的參與和支持,最新的Servlet和JSP規範總是能在Tomcat中得到體現。

​ 因爲tomcat技術先進,性能穩定,而且免費。因而深受Java愛好者的喜愛,是目前比較流行的Web應用服務器。

【作用】 運行web項目。

2.2 下載

  1. 官網地址:https://tomcat.apache.org 選擇tomcat8.5版本。

  2. 選擇要下載的版本;

【tomcat軟件類型介紹】

tar.gz 文件 是linux操作系統下的壓縮版本
exe文件是window操作系統下的安裝版本
zip文件是window操作系統下壓縮版本(我們選擇zip文件)

  1. 下載完成;

2.3 tomcat目錄

bin:腳本目錄
	啓動腳本:startup.bat
	停止腳本:shutdown.bat

conf:配置文件目錄 (config /configuration)
	核心配置文件:server.xml
	用戶權限配置文件:tomcat-users.xml
	所有web項目默認配置文件:web.xml

lib:依賴庫,tomcat和web項目中需要使用的jar包

logs:日誌文件.
	localhost_access_log..txt tomcat記錄用戶訪問信息,..表示時間。
	例如:localhost_access_log.2017-04-28.txt
	
temp:臨時文件目錄,文件夾內內容可以任意刪除。

webapps:默認情況下發布WEB項目所存放的目錄。

work:tomcat處理JSP的工作目錄。 

2.4 tomcat啓動和訪問

(1) 啓動

​ 雙擊tomcat解壓目錄/bin/startup.bat 文件即可啓動tomcat。

(2) 訪問

​ tomcat的默認端口爲8080,所以在瀏覽器的地址欄輸入:http://ip:8080即可訪問tomcat服務器。

(3)關閉
  1. 關閉startup.bat啓動窗口;
  2. 雙擊tomcat的/bin/shutdown.bat文件;
  3. Ctrl+C;

2.5 tomcat啓動失敗常見原因

(1) JAVA_HOME 配置

​ 如果沒有配置JAVA_HOME環境變量,在雙擊“startup.bat”文件運行tomcat時,將一閃立即關閉

​ 解決方式:需要正確配置JAVA_HOME環境變量,指向JDK的bin目錄的上一級目錄;

(2)端口號衝突

​ 一臺擁有ip地址的主機上可以提供多個服務(啓動多個軟件),每一個服務都有一個唯一的端口號。所以端口號不能重複。

【端口號衝突報錯信息】

嚴重: Failed to initialize end point associated with ProtocolHandler ["http-bio-8080"]
java.net.BindException: Address already in use: JVM_Bind <null>:8080
...
Caused by: java.net.BindException: Address already in use: JVM_Bind
...
控制檯將出現大量異常信息,描述的是8080端口被佔用。

【解決方案】

  1. 修改tomcat端口

通過修改tomcat目錄下conf/server.xml配置文件修改端口號。將8080修改成其他端口號。

<Connector port="8080" protocol="HTTP/1.1"
               connectionTimeout="20000"
               redirectPort="8443" />

2.端口號佔用

netstat –nao

使用任務管理器---->選擇詳細信息---->查看pid爲11604(查詢出來的 值),關閉結束進程即可

3、web項目

​ tomcat已經安裝完成,我們啓動tomcat後就能夠通過ip地址和端口訪問到這臺服務器了。但是,我們通過訪問http://ip:8080 看到的頁面只是tomcat提供的一個頁面。真實生活中,百度和淘寶可能使用的服務器都是tomcat,但是我們訪問百度和淘寶看到的卻是不同的頁面,這是因爲我們訪問的是百度和淘寶各自運行在tomcat中的web項目。

JavaWeb項目與java項目的區別:

  • java項目:後臺代碼;
  • JavaWeb項目:前端代碼+後臺代碼;

3.1 使用idea創建JavaWeb項目

【第一步】 File—New—Project

【第二步】 選擇Java Enterprise版本,然後配置tomcat
注意:這裏關聯的tomcat home指的是tomcat的解壓目錄(bin目錄的上一級目錄);

【第三步】 選擇使用模板創建項目

【第四步】 填寫項目名,併爲這個web項目配置tomcat

將tomcat配置到項目中。

【第五步】 創建完成

3.2 使用tomcat發佈JavaWeb項目

​ 我們的JavaWeb項目開發完成之後,必須發佈到tomcat中,並啓動tomcat才能夠被用戶訪問到。

【準備工作】

  1. 使用idea打開上面創建的web項目,在web目錄下新建一個index.html頁面;
  2. 在index.html中書寫內容;
  3. 將這個web項目拷貝出來;
方式一:直接發佈
  1. 將web項目複製到tomcat的webapps目錄下:

  2. 啓動tomcat:雙擊bin目錄下的startup.bat文件

  3. 訪問:http://ip:端口號/項目名/資源路徑

    訪問web目錄下的index.html的url爲:http://ip:8080/web-pro/web/index.html

方式二:IDEA配置tomcat直接發佈項目

第一步:配置JRE

​ 在Run Configurations中,選擇JRE。

第二步:啓動項目

【注】圖標1位正常啓動,圖標2位Debug模式啓動

​ 啓動成功之後,會自動彈出index.html頁面

第三章 Servlet入門

  1. 客戶端(瀏覽器)發送的數據會被提交到服務器;
  2. 服務器必須具備:1.接收請求數據;2.處理請求數據(業務邏輯的處理);3.給瀏覽器生成響應信息的能力;
  3. tomcat服務器遵從了JavaEE規範,Sun公司制定的動態資源規範Servlet實現這個功能;(運行在服務器端,能夠接收用戶請求,處理請求數據和給瀏覽器生成響應信息)
  4. 在java的世界裏制定規範往往是接口來實現的,所以Servlet是一個接口,裏邊只是定義了一些方法;
  5. 如果,我們對這個接口進行具體的實現,就能夠完成對用戶數據的接收,處理和生成響應信息;

1、什麼是Servlet

Servlet 運行在服務端的Java小程序,是sun公司提供一套規範,用來處理客戶端請求、響應給瀏覽器的動態web資源。
Servlet是JavaWeb三大組件之一(Servlet、Filter、Listener),是最重要的組件。

Servlet 的作用

  1. 接收請求 :接收客戶端發送的請求數據;
  2. 業務邏輯的處理;
  3. 響應結果 :將處理結果響應給客戶端(瀏覽器);

2、Servlet入門開發步驟

  1. 創建一個普通java類實現Servlet接口;
  2. 重寫Servelt接口中的所有抽象方法;
  3. 註冊這個類;
    1. 在web.xml中配置這個類的信息;
    2. 配置這個類的映射路徑;
  4. 在service方法中處理請求和響應的業務邏輯;
  5. 發佈項目,啓動項目之後,通過映射路徑訪問這個類;

3、Servlet入門案例

【案例】Servlet入門案例

需求分析

  1. 編寫一個Servlet,接收客戶端(瀏覽器)的請求;
  2. 在控制檯打印“service 方法被執行了。。。。”;

實現步驟

  1. 創建一個普通java類FirstServlet實現Servlet接口,並重寫Servlet接口的所有抽象方法;
package cn.itheima.servlet;

import javax.servlet.*;
import java.io.IOException;

/*
實現接口
ctrl + i
實現接口 複寫接口裏面的所有方法 只想實現業務
service()
 */
public class FirstServlet implements Servlet{
    @Override
    public void init(ServletConfig servletConfig) throws ServletException {

    }

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

    @Override
    public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
        //service 處理業務邏輯
        //可以調用JDBC  去數據庫進行查詢
        System.out.println("service 方法被執行了。。。。");
        System.out.println("去數據庫查詢用戶信息");
    }

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

    @Override
    public void destroy() {

    }
}

  1. 在web.xml中配置這個HelloServlet的類路徑和映射路徑,配置信息如下;

    【注意】 url-pattern 映射路徑前面必須添加"/";

   <servlet>
        <servlet-name>first</servlet-name>
        <servlet-class>cn.itheima.demo.FirstServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>first</servlet-name>
        <url-pattern>/first</url-pattern>
    </servlet-mapping>
  1. 在HelloServlet的service方法中書寫響應的代碼邏輯;
  @Override
    public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
        //service 處理業務邏輯
        //可以調用JDBC  去數據庫進行查詢
        System.out.println("service 方法被執行了。。。。");
        System.out.println("去數據庫查詢用戶信息");
    }

  1. 啓動tomcat,根據web.xml中的配置訪問HelloServlet。

訪問路徑爲:http://localhost:8080/first

【注意事項】

使用idea創建的web項目,可以通過配置,訪問路徑中不需要添加項目名,具體配置如下:

3.1 Servlet執行流程分析

​ 之前的java項目中,我們運行一段程序都是使用main方法來運行的。Servlet中沒有main方法,那它是怎麼運行的呢?

4、Servlet編程優化

​ 我們發現在上述的HelloServlet中,實現Servlet接口後能夠接收瀏覽器發送的請求並能夠響應數據給瀏覽器。但是Servlet是一個接口,我們實現接口後必須重寫接口中所有的方法。但是,我們在接口請求和響應數據的時候只需要一個service方法就足夠了。所以,我們需要有選擇地實現父類的方法。

​ 子類繼承父類時,可以根據子類的需求選擇性地重寫父類的方法。

4.1 方案一:GenericServlet優化方案

(1) GenericServlet簡介

GenericServlet類是一個抽象類,它實現了多個接口,其中有一個是Servlet,所以它重寫了Servlet接口中的所有方法。我們只需要繼承GenericServlet類,重寫其中的service方法即可。

(2)爲什麼要繼承GenericServlet
  1. GenericServlet實現了Servlet接口,我們繼承GenericServlet之後相當於間接實現了Servlet接口;
  2. GenericServlet中給我們提供了很多通用方法,這些方法已經幫我們實現了很多功能,繼承GenericServlet之後可以直接調用這些方法,所以說,GenericServlet相對於Servlet,進行了功能的擴展和衍生;
  3. GenericServlet是一個抽象類,裏邊只有一個抽象方法service(),我們繼承GenericServlet之後只需要重寫service()方法處理具體的業務邏輯即可,減少了直接實現Servlet接口帶來的代碼冗餘;
(3) 案例:使用GenericServlet優化Servlet接口編程

需求分析 :使用GenericServlet重寫入門案例

技術分析

 1. 創建一個普通的java類繼承GenericServlet;
 2. 在web.xml中配置這個GenericServlet的子類;
 3. 重寫service方法,在service方法中完成向瀏覽器響應數據的功能;

實現步驟

  1. 編寫一個普通的java類,SecondServlet,繼承GenericServlet;
package cn.itheima.servlet;

import javax.servlet.GenericServlet;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import java.io.IOException;

public class SecondServlet extends GenericServlet {
    @Override
    public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
        System.out.println("這是 SecondServlet。。");
    }
}

  1. 在web.xml配置ServletDemo1;
    
    <servlet>
        <servlet-name>second</servlet-name>
        <servlet-class>cn.itheima.demo.SecondServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>second</servlet-name>
        <url-pattern>/second</url-pattern>
    </servlet-mapping>
  1. 重寫service方法,並在service方法中書寫以下代碼,完成向頁面響應數據;
  @Override
    public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
        System.out.println("這是 SecondServlet。。");
    }
  1. 啓動tomcat並訪問:

http://localhost:8080/second

4.2 方案二:HttpServlet優化方案

問題:

	在實際的生活中,客戶端(瀏覽器)給我們發送的請求往往是HTTP協議下的請求,所以我們只需要處理HTTP的請求和響應即可。也就是說我們需要的知識一個與HTTP協議相關的Servlet。

解決方案:

Sun公司爲我們提供了HttpServlet,對GenericServlet再次進行擴展和功能加強。

實際開發中:我們編寫Servlet就可以採用 繼承HttpServlet來完成servlet的開發,這樣的Servlet我們可以獲取更多的業務功能。
(1)HttpServlet簡介:

​ HttpServlet是GenericServlet的一個子類。這個類是專門幫我們處理與HTTP協議相關的請求與響應的一個Servlet類,它裏邊的方法如下:

​ 因爲,在我們的日常生活中最常用的HTTP請求只有get請求和post請求。所以我們在繼承了HttpServlet之後只需要重寫裏邊的doGet()方法和doPost()方法即可滿足我們的需求:

(2)爲什麼要繼承HttpServlet
  1. HttpServlet繼承了GenericServlet,功能比GenericServlet更強大;
  2. GenericServlet中處理不同的請求都使用service()方法,HttpServlet根據不同的請求方式提供了不同的方法進行處理。等於是細化了service()方法;
  3. HttpServlet類中的方法參數爲HttpServletRequest對象和HttpServletResponse對象。使用這兩個對象的好處在於:
    1. HttpServletRequest繼承了ServletRequest,HttpServletResponse繼承了ServletResponse。功能更強大;
    2. HttpServletRequest和HttpServletResponse爲我們提供了很多處理HTTP協議相關的API,HTTP協議正是我們日常生活中使用得比較多的一種協議;
(3)HttpServlet編程

【Servlet優化二】HttpServlet編程ThrServlet.java

package cn.itheima.servlet;

import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class ThrServlet extends HttpServlet {
    /*
    ctrl + o   複寫裏面非抽象方法
     */

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) {
        System.out.println("post方法。。");
    }

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) {
        System.out.println("get方法。。");
    }
}

thr.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h1>post</h1>
<form action="/thr" method="post">
    用戶名:<input type="text" name="username"><br>
    密碼:<input type="password" name="password"><br>
    <input type="submit" value="提交">
</form>
<h1>get</h1>
<form action="/thr" method="get">
    用戶名:<input type="text" name="username"><br>
    密碼:<input type="password" name="password"><br>
    <input type="submit" value="提交">
</form>
</body>
</html>

web.xml

 <servlet>
        <servlet-name>thr</servlet-name>
        <servlet-class>cn.itheima.demo.ThrServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>thr</servlet-name>
        <url-pattern>/thr</url-pattern>
    </servlet-mapping>
(4)請求是怎麼到達doGet()和doPost()的

​ 在我們繼承HttpServlet之後,重寫了doGet()和doPost()方法。瀏覽器發送的get請求會被doGet()接收並處理,瀏覽器發送的post請求會被doPost()請求接收並處理。服務器端是怎麼辨別我的請求是get還是post請求的呢?下面,我們看一下HttpServlet的源碼中的service方法:

  1. 實際處理請求的還是HttpServlet的service()方法;
  2. service方法中,接收請求之後獲取了請求方式,
 protected void service(HttpServletRequest req, HttpServletResponse resp)
        throws ServletException, IOException {
		
        //獲取數據的請求方式
        String method = req.getMethod();
		//根據請求方式的不同,調用不同的方法
        if (method.equals(METHOD_GET)) {
            long lastModified = getLastModified(req);
            if (lastModified == -1) {
                //調用doGet()方法
                doGet(req, resp);
            } else {
                long ifModifiedSince;
                try {
                    ifModifiedSince = req.getDateHeader(HEADER_IFMODSINCE);
                } catch (IllegalArgumentException iae) {
                    // Invalid date header - proceed as if none was set
                    ifModifiedSince = -1;
                }
                if (ifModifiedSince < (lastModified / 1000 * 1000)) {
                    maybeSetLastModified(resp, lastModified);
                    doGet(req, resp);
                } else {
                    resp.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
                }
            }

        } else if (method.equals(METHOD_HEAD)) {
            long lastModified = getLastModified(req);
            maybeSetLastModified(resp, lastModified);
            doHead(req, resp);
		//調用doPost()方法
        } else if (method.equals(METHOD_POST)) {
            doPost(req, resp);

        } else if (method.equals(METHOD_PUT)) {
            doPut(req, resp);

        } else if (method.equals(METHOD_DELETE)) {
            doDelete(req, resp);

        } else if (method.equals(METHOD_OPTIONS)) {
            doOptions(req,resp);

        } else if (method.equals(METHOD_TRACE)) {
            doTrace(req,resp);

        } else {
             String errMsg = lStrings.getString("http.method_not_implemented");
            Object[] errArgs = new Object[1];
            errArgs[0] = method;
            errMsg = MessageFormat.format(errMsg, errArgs);

            resp.sendError(HttpServletResponse.SC_NOT_IMPLEMENTED, errMsg);
        }
    }

4.3 Servlet編程優化小結

  1. Servlet編程的作用:接收瀏覽器的請求,處理請求數據,給瀏覽器響應數據;
  2. Servlet接口:
    1. Sun公司規定如果想要在服務端接收和響應客戶端的數據,必須實現Servlet接口;
    2. 由於Servlet是一個接口,實現Servlet接口後必須重寫其中所有的方法;
  3. GenericServlet:
    1. GenericServlet:是一個抽象類,它實現了Servlet接口,與協議無關;
    2. 繼承GenericServlet,只需要重寫service方法即可接收和響應數據;
  4. HttpServlet:
    1. HttpServlet:是一個抽象類,它繼承了GenericServlet,爲HTTP請求定製的;
    2. 繼承HttpServlet,重寫doGet和doPost方法,能夠更加方便地處理不同請求的數據;

5、Servlet生命週期

​ 生命週期指的是一個對象從創建到銷燬的過程。我們的Servlet是由誰創建的,何時創建的,創建之後做了哪些工作,工作完成之後又是何時銷燬的呢?下面我們就來看一下Serlvet的生命週期。

1. 誰創建:tomcat創建;
2. 何時創建:第一次訪問這個Servlet的時候,只創建一次,創建完成後會調用init()方法;
3. 如何工作:每次請求到這個Servlet時,由service方法處理請求和響應信息;
4. 何時銷燬:服務器正常關閉,銷燬前會調用destory()方法;

【測試代碼】

public interface Servlet {

    /*
    * Servlet對象創建的時候會調用init()方法
    */
    public void init(ServletConfig config) throws ServletException;

    /*
    * Servlet對象創建後,每次的請求都由service方法處理
    */
    public void service(ServletRequest req, ServletResponse res)
            throws ServletException, IOException;

    /*
    * Servlet對象銷燬前會調用destory方法。主要是用於釋放一些資源。
    */
    public void destroy();
}

【實現類】

package cn.itheima.servlet;

import javax.servlet.*;
import java.io.IOException;

public class LifeCycleServlet implements Servlet {
    @Override
    public void init(ServletConfig servletConfig) throws ServletException {
        System.out.println("LifeCycleServlet 被創建了。。。");
    }

    @Override
    public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
        System.out.println("每一次請求都會被執行。。。。");
    }

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

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

    @Override
    public void destroy() {
        System.out.println("LifeCycleServlet 被銷燬了。。。。");
    }
}

xml

<servlet>
        <servlet-name>life</servlet-name>
        <servlet-class>cn.itheima.demo.LifeCycleServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>life</servlet-name>
        <url-pattern>/life</url-pattern>
    </servlet-mapping>

【小結】

1. Servlet對象的創建:
	1. 創建者:tomcat;創建時機:在Servlet第一次被訪問的時候;
	2. 特點:
		1. 只會創建一次(單例);
		2. 對象創建完成之後,會調用init()方法;
2. Servlet運行:
	1. service()方法接收用戶的請求,和處理響應;
	2. 特點:
		1. 每次對這個Servlet的訪問都會由service()方法來處理;
		2. service()方法的兩個參數:request和response對象專門用來處理請求和響應;
3. Servlet銷燬:
	1. Servlet對象在服務器正常關閉的時候銷燬;
	2. 特點:
		1. 銷燬的時候會調用destory()方法;

【注意】Servlet對象是單例的,會不會產生線程安全問題?

答:線程安全問題的產生是因爲要爭奪共同的資源,所以只要不在Servlet類中設置成員變量就可以避免。

6、 Servlet映射路徑配置規範

​ url-pattern中的映射路徑配置存在以下幾種方式:

1. 完全匹配  		 /user/hello		  資源路徑爲/user/hello時可以訪問
2. 目錄匹配			/user/*				 資源路徑中含有/user目錄均可訪問
3. 後綴名匹配	    *.do			     資源路徑中以.do結尾的均可訪問
4. 缺省路徑			/			         訪問的路徑找不到,就會去找缺省路徑
tomcat獲得匹配路徑時,優先級順序:1 >2 > 3 > 4

​ 開發中一般使用完全匹配,即一個Servlet對應一個映射路徑。

UserServlet.java

package cn.itheima.demo;

import javax.servlet.GenericServlet;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import java.io.IOException;
/*
當前路徑以及子路徑  都會訪問servlet
 */
public class UserServlet extends GenericServlet {
    @Override
    public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
        System.out.println("處理業務邏輯");
    }
}


xml

 <servlet>
        <servlet-name>user</servlet-name>
        <servlet-class>cn.itheima.demo.UserServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>user</servlet-name>
        <url-pattern>/user/*</url-pattern>
    </servlet-mapping>

DoServlet.java

package cn.itheima.demo;

import javax.servlet.GenericServlet;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import java.io.IOException;

public class DoServlet extends GenericServlet {
    @Override
    public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
        System.out.println("DoServlet執行了。。。。");
    }
}

web.xml

<servlet>
        <servlet-name>do</servlet-name>
        <servlet-class>cn.itheima.demo.DoServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>do</servlet-name>
        <url-pattern>*.action</url-pattern>
    </servlet-mapping>

【關於缺省路徑】web.xml

URL輸入http://localhost:8080/ 如何讀取文件? 
1)到當前day10應用下的web.xml文件查找是否有匹配的url-pattern。 
2)如果沒有匹配的url-pattern,則交給tomcat的內置的DefaultServlet處理。 
3)DefaultServlet程序到day10應用的根目錄下查找是否存在一個名稱爲index.html的靜態文件。 
4)如果找到該文件,則讀取該文件內容,返回給瀏覽器。 
5)如果找不到該文件,則返回404錯誤頁面。

7.服務器啓動,立刻加載Servlet對象

問題:普通的Servlet對象在我們第一次訪問的時候創建, 開發中,如果我們需要在服務器啓動的時候,初始化Servlet對象應該如何編寫呢?

需求:服務器tomcat啓動,立刻加載配置文件,獲取配置文件信息,爲項目後續代碼提供數據支持。

解決:此時的業務場景,我們需要在web.xml文件中給指定的Servlet添加一個標籤<load-on-startup>

實現步驟:在web.xml中在**標籤內部中配置**:

2 — 傳入正整數,整數越小,被創建的優先級就越高。12345

第四章 Servlet3.0註解開發

​ 在我們上面創建的Servlet中,Servlet的配置信息都是在web.xml中完成的。如果,我們創建的Servlet非常多,就會導致web.xml中的配置非常臃腫,不便於管理。Servlet3.0爲我們提供了註解支持,創建Servlet的時候。在這個Servlet類上面添加註解就可以完成Servlet的配置。Servlet3.0除了提供註解支持,還提供了以下新特性:

1、Servlet3.0新特性

  • 註解支持

    該版本新增了若干註解,用於簡化 Servlet、過濾器(Filter)和監聽器(Listener)的聲明,這使得 web.xml 部署描述文件從該版本開始不再是必選的了。

  • 支持web模塊(servlet filter Listener)

  • 支持Servlet異步處理

  • 文件上傳API簡化

【注意】詳細信息請參考《Servlet3.0新特性全解.md

2、爲什麼要使用註解

  1. web.xml中配置過多servlet不便於管理,容易出錯;
  2. 註解開發使得開發更敏捷,效率更高;
  3. 註解開發是一種趨勢;

3、使用IDEA創建3.0版本的Servlet

​ 新版的IDEA(2017版本)創建的Servlet默認是3.0版本的,所以我們只需要新建一個Servlet,然後用註解配置即可。具體步驟如下:

第一步:新建一個Servlet;

​ 在包上面點擊鼠標右鍵New–>Servlet

給這個Servlet取個名,然後點擊OK

第二步:配置Servlet

​ 創建完成後,Servlet類上面會默認添加一個註解@WebServlet(name="Servlet3Demo") 。這個@WebServlet註解就是用來配置當前這個Servlet的。這個註解中常用的有兩個屬性:

  1. name屬性: 相當於web.xml的 ;
  2. urlPatterns屬性: 編寫訪問servlet的路徑 類似於

所以,我們需要手動在@WebServlet 註解中添加urlPatterns屬性,來設置映射路徑。

package com.heima.servlet;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * @author buguniao
 * @date 2018-06-24 22:19
 *
 * 1. name屬性: 相當於web.xml的 <servlet-name>;
 * 2. urlPatterns屬性: 編寫訪問servlet的路徑  類似於 <url-pattern>
 */
@WebServlet(name = "Servlet3Demo",urlPatterns = "/servlet3")
public class Servlet3Demo extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

    }

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

    }
}

第三步:啓動tomcat並訪問

訪問路徑:`http://localhost:8080/ano ;

運行結果:AnoServlet.java

package cn.itheima.servlet;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@WebServlet("/ano")
public class AnoServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("註解servlet被訪問了。。。。");
        System.out.println("get請求和post請求都會執行doGet()");

        //dopost請求業務 寫在doGet()就可以了。。
    }
}

不需要MXL配置

4、優化

4.1 優化一

在doPost方法中調用doGet方法。這樣我們的代碼都在goGet()方法裏寫就可以了。

1535469904205

4.2 優化二

​ 基於IDEA的模板,快速創建Servlet。

【模板配置代碼】

#if (${PACKAGE_NAME} && ${PACKAGE_NAME} != "")package ${PACKAGE_NAME};#end
#parse("File Header.java")
@javax.servlet.annotation.WebServlet("/${Entity_Name}")
public class ${Class_Name} extends javax.servlet.http.HttpServlet {
    protected void doPost(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response) throws javax.servlet.ServletException, java.io.IOException {
        doGet(request,response);
    }

    protected void doGet(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response) throws javax.servlet.ServletException, java.io.IOException {

    }
}

5、Servlet開發最終版本

package cn.itheima.demo;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@WebServlet("/ano")
public class AnoServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
       doGet(request,response);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("AnoServlet被訪問了。。。");
        //post業務邏輯  get業務邏輯
    }
}

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