JavaWeb

Icfh發表於2024-03-04

JavaWeb

Java Web 元件

首先獻上Tomcat架構神圖:

img

Servlet

  • Servlet容器:

    執行在Web伺服器上的程式,作為來自HTTP客戶端的請求和HTTP伺服器上的資料庫或應用程式之間的中間層,它負責處理使用者的請求,並根據請求生成相應的返回資訊提供給使用者。

​ 大體原理圖如下:

架構

  • Servlet請求的處理過程:
  1. 瀏覽器發起http請求
  2. Servlet容器收到請求後,分別建立了HttpServletRequest物件和HttpServletResponse物件
  3. Servlet容器呼叫HttpServlet的init方法,init方法只在第一次請求時被呼叫
  4. Servlet容器讀取HttpServletRequest物件中讀取資訊,然後透過service()方法處理請求資訊,根據請求資訊找到對應的路由(業務邏輯)
  5. 處理完後將處理資訊封裝到HttpServletResponse物件,然後返回
  6. 容器關閉時,呼叫destory函式

img

  • Servlet生命週期
  1. 伺服器啟動時(web.xml中配置load-on-startup=1,預設為0)或者第一次請求該servlet時,就會初始化一個Servlet物件,也就是會執行初始化方法init(ServletConfig conf)。

  2. servlet物件去處理所有客戶端請求,在service(ServletRequest req,ServletResponse res)方法中執行

  3. 伺服器關閉時,銷燬這個servlet物件,執行destroy()方法。

  4. 由JVM進行垃圾回收。

Filter

  • Filter過濾器:

​ Filter也稱為過濾器,主要功能是在HttpServletRequest物件到達Servlet之前,攔截、檢查該物件,同時也可以對該HttpServletRequest物件的頭部資料進行相應的修改;同時,也會攔截HttpServletResponse,修改物件中的資料

​ 通俗來講就是用來過濾網站資料,用於處理中文亂碼、登入驗證等操作...

image-20240302155748650

  • Filter工作原理:

1、Filter 程式是一個實現了特殊介面的 Java 類,與 Servlet 類似,也是由 Servlet 容器進行呼叫和執行的。

2、當在 web.xml 註冊了一個 Filter 來對某個 Servlet 程式進行攔截處理時,它可以決定是否將請求繼續傳遞給 Servlet 程式,以及對請求和響應訊息是否進行修改。

3、當 Servlet 容器開始呼叫某個 Servlet 程式時,如果發現已經註冊了一個 Filter 程式來對該 Servlet 進行攔截,那麼容器不再直接呼叫 Servlet 的 service 方法,而是呼叫 Filter 的 doFilter 方法,再由 doFilter 方法決定是否去啟用 service 方法。

4、但在 Filter.doFilter 方法中不能直接呼叫 Servlet 的 service 方法,而是呼叫 FilterChain.doFilter 方法來啟用目標 Servlet 的 service 方法,FilterChain 物件時透過 Filter.doFilter 方法的引數傳遞進來的。

5、只要在 Filter.doFilter 方法中呼叫 FilterChain.doFilter 方法的語句前後增加某些程式程式碼,這樣就可以在 Servlet 進行響應前後實現某些特殊功能。

6、如果在 Filter.doFilter 方法中沒有呼叫 FilterChain.doFilter 方法,則目標 Servlet 的 service 方法不會被執行,這樣透過 Filter 就可以阻止某些非法的訪問請求。

  • 生命週期:

image-20240304220355773

Listener

​ 監聽,當涉及某個介面的操作時,會呼叫相關函式

  • ServletContextListener:對Servlet上下文的建立和銷燬進行監聽; ServletContextAttributeListener:監聽Servlet上下文屬性的新增、刪除和替換;

  • HttpSessionListener:對Session的建立和銷燬進行監聽。Session的銷燬有兩種情況,一箇中Session超時,還有一種是透過呼叫Session物件的invalidate()方法使session失效。

  • HttpSessionAttributeListener:對Session物件中屬性的新增、刪除和替換進行監聽;

  • ServletRequestListener:對請求物件的初始化和銷燬進行監聽; ServletRequestAttributeListener:對請求物件屬性的新增、刪除和替換進行監聽。

Maven

存在的必要性

  • 手動匯入:

​ 點選專案結構

image-20240303165048690

​ 然後選擇路徑匯入

image-20240303165120892

  • 使用Maven匯入

​ 我們可以透過pom.xml中編寫xml條目統一匯入庫

配置

  • 去官網下載,這不用說了吧
  • 編輯環境變數

去Maven官網下載,然後編輯環境變數
image-20240303165253844

image-20240303165311311

  • 配置映象源

在conf/setting.xml中寫入

image-20240303165703208

  • 配置倉庫地址

同樣位置下寫入如下條目

image-20240303165747784

  • 在IDEA中配置Maven

image-20240303170630821

使用

pom.xml:Maven的核心配置檔案,記錄該專案的資訊

image-20240303171002859

Maven的相關功能及其IDEA UI下的相關操作演示

一個專案中一般包含三個模組:生命週期、外掛、依賴

image-20240303171216674

Tomcat

Tomcat主要功能

tomcat作為web伺服器,主要有兩個核心元件

Connector(聯結器): HTTP伺服器功能,進行Socket通訊(基於TCP/IP),解析HTTP報文

Container(容器):Servlet容器功能:載入和管理Servlet,由Servlet具體負責處理Request請求

img

Connector聯結器

Connector由如下元件構成:

  • EndPoint:進行socket通訊,將位元組寫入位元組的輸入流中然後傳給Processor,或者將位元組輸出流轉化成位元組
  • Processor:將位元組流物件轉成Request物件,或者將Response物件轉成位元組流物件
  • Adapter:將Request物件解析成ServletRequest物件

Endpoint與Processor有一個組合名稱為ProtocolHandler

img

Container容器

在Container中有四種容器:

  • Engine 表示整個 Catalina 的 Servlet 引擎,用來管理多個虛擬站點,一個 Service 最多隻能有一個 Engine,但是一個引擎可包含多個 Host
  • Host 代表一個虛擬主機,或者說一個站點,可以給 Tomcat 配置多個虛擬主機地址,而一個虛擬主機下可包含多個 Context
  • Context 表示一個 Web 應用程式,每一個Context都有唯一的path,一個Web應用可包含多個 Wrapper
  • Wrapper 表示一個Servlet,負責管理整個 Servlet 的生命週期,包括裝載、初始化、資源回收等

img

JavaWeb元件 + Tomcat 開發

Servlet

(嚴重踩坑:注意Tomcat + Servlet + Java 的版本匹配問題,可以參考:https://tomcat.apache.org/whichversion.html)

使用方法如下:

  • 繼承HttpServlet抽象類,然後重寫doGet等方法

  • 註冊Servlet,路由對映:

    • 在高版本的Servlet中可以使用@WebServlet註解指明路由

    • 低版本中在web.xml中註冊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;
import java.io.PrintWriter;

@WebServlet()
public class HelloServlet extends HttpServlet{
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//        ServletOutputStream outputStream = resp.getOutputStream();
        PrintWriter writer = resp.getWriter();  // 響應流
        writer.print("Hello,Serlvet");
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        super.doPost(req, resp);
    }
}

web.xml

<web-app>
  <display-name>Archetype Created Web Application</display-name>

  <servlet>
    <servlet-name>HelloServlet</servlet-name>
    <servlet-class>HelloServlet</servlet-class>
  </servlet>
  <servlet-mapping>
    <servlet-name>HelloServlet</servlet-name>
    <url-pattern>/hello</url-pattern>
  </servlet-mapping>


</web-app>

image-20240304203245828

Filter

Filter:過濾器,用來過濾網站的資料

  • 處理中文亂碼
  • 登入驗證

Filter:

package filter;

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

public class TestFilter implements Filter {

    public void init(FilterConfig filterConfig) throws ServletException{
        System.out.println("Test Filter Init");
        System.out.println(System.currentTimeMillis());
    }


    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException{

        servletResponse.getWriter().write("Before TestFilter:\n");
        System.out.println("Before TestFilter:");
        System.out.println(System.currentTimeMillis());
        filterChain.doFilter(servletRequest, servletResponse);
        servletResponse.getWriter().write("After TestFilter\n");
        System.out.println("After TestFilter");
        System.out.println(System.currentTimeMillis());
    }


    public void destroy(){
        System.out.println("Test Filter Destroy");
        System.out.println(System.currentTimeMillis());
    }

}

web.xml

  <filter>
    <filter-name>TestFilter</filter-name>
    <filter-class>filter.TestFilter</filter-class>
  </filter>
  <filter-mapping>
    <filter-name>TestFilter</filter-name>
    <url-pattern>/show</url-pattern>
  </filter-mapping>

image-20240304221408652

Listener

步驟:

  • 實現監聽器的介面
  • 在web.xml中配置路由

實現介面:

package listener;

import javax.servlet.ServletContext;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;

public class OnlineCountListener implements HttpSessionListener {


    // 建立session監聽(session建立時會觸發這個函式)
    public void sessionCreated(HttpSessionEvent sessionEvent) {
        System.out.println("SessionCreated");

        // 獲取session上下文
        ServletContext ctx = sessionEvent.getSession().getServletContext();

        // 讀
        Integer onlineCount = (Integer) ctx.getAttribute("OnlineCount");
        if(onlineCount == null){
            onlineCount = new Integer(1);
        }else {
            int count = onlineCount.intValue();
            onlineCount = new Integer(count+1);
        }

        // 寫
        ctx.setAttribute("OnlineCount",onlineCount);
    }

    // 銷燬session監聽(session銷燬時會觸發這個函式)
    public void sessionDestroyed(HttpSessionEvent sessionEvent){
        System.out.println("SessionDestroyed");

        ServletContext ctx = sessionEvent.getSession().getServletContext();

        // 讀
        Integer onlineCount = (Integer) ctx.getAttribute("OnlineCount");
        if(onlineCount == null){
            onlineCount = new Integer(0);
        }else {
            int count = onlineCount.intValue();
            onlineCount = new Integer(count-1);
        }

        // 寫
        ctx.setAttribute("OnlineCount",onlineCount);
    }
}

web.xml

 <listener>
    <listener-class>listener.OnlineCountListener</listener-class>
 </listener>

image-20240304225327361

參考文獻

  1. https://github.com/Y4tacker/JavaSec/blob/main/5.記憶體馬學習/Tomcat/Tomcat介紹/Tomcat介紹.md#connector聯結器