【防忘筆記】Spring+Struts2古董框架學習

dayceng發表於2024-08-18

Spring+Struts2專案框架梳理

若基於Spring+Struts2的方式進行開發,前後端的互動邏輯會與boot系以及MCV的組織結構有所不同

這裡是對於學習過程的一些記錄

前置通用知識

Struts2框架資料

img

Struts2基礎篇之基本概念

Java之struts2框架學習

一般情況的Spring前後端除錯流程

要理解基於Spring開發的系統中前後端資料流,可以按照以下步驟進行:

1. 前端操作與瀏覽器除錯

  • 開啟瀏覽器除錯工具:在瀏覽器中開啟你要除錯的網頁(例如賬戶查詢頁面)。按下 F12(或右鍵點選頁面,選擇“檢查”)開啟瀏覽器的開發者工具。
  • 切換到網路(Network)標籤:在開發者工具中,切換到“網路”(Network)選項卡。這一部分會顯示所有的網路請求,包括AJAX請求、資源載入等。
  • 執行查詢操作:在前端頁面上執行“賬戶查詢”的操作。例如,輸入查詢條件,然後點選“查詢”按鈕。
  • 觀察請求:在“網路”標籤中,你會看到一個新的網路請求被髮出。這個請求通常是一個HTTP請求,型別可能是GET或POST。

2. 分析網路請求

  • 請求URL:點選請求,可以檢視詳細資訊,包括請求的URL、請求方法(GET或POST)、請求頭、請求體(如果是POST請求)。
  • 請求引數:如果是GET請求,請求引數通常會出現在URL中;如果是POST請求,引數會在請求體中。你可以看到前端是如何將使用者輸入的資料傳送給後端的。
  • 檢視響應:同樣在這個請求的詳細資訊中,可以看到伺服器返回的響應資料。通常會是JSON、XML等格式的資料。這個資料就是後端處理請求後的結果,前端將其拿到後再渲染到頁面上。

3. 後端除錯

  • 找到對應的後端控制器:根據請求的URL,你可以在Spring專案中找到對應的控制器(通常是帶有@Controller@RestController註解的類)。例如,如果請求的URL是/api/accounts,你可以在專案中搜尋這個路徑,找到對應的方法。
  • 跟蹤後端處理流程:在控制器的方法中,可以看到如何接收請求引數、呼叫服務層(Service層)處理業務邏輯,最終返回資料。
  • 日誌輸出:你可以透過在後端程式碼中新增日誌來除錯,記錄請求的接收、處理過程,以及最終返回的資料。

4. 結合前後端資料流

  • 前端傳送請求:透過觀察瀏覽器中的網路請求,瞭解前端是如何將使用者輸入的資料傳送到後端的。
  • 後端處理請求並返回響應:透過分析後端程式碼,理解請求是如何在後端處理的,以及如何將處理結果返回給前端。
  • 前端接收並處理響應:最後,回到瀏覽器,看看前端如何接收並處理從後端返回的資料,將其顯示在使用者介面上。

actionmap.xml檔案

在Spring與Struts2結合使用的專案中,actionmap.xml檔案通常用於配置Struts框架中的Action對映。

actionmap.xml的作用

  • Action對映配置actionmap.xml檔案中定義了Struts的Action對映,將特定的URL路徑對映到某個Action類的某個方法上。Action類是Struts框架中的核心元件,它負責處理使用者請求、呼叫業務邏輯並返回相應的檢視。
  • 路徑到Action的對映:當前端發起請求時,Struts根據URL路徑在actionmap.xml中查詢對應的Action對映,然後呼叫配置的Action類中的相應方法。

查詢前端呼叫後端的具體路徑或流程

  • 瀏覽器檢視請求URL:首先,透過瀏覽器的除錯工具(如Network標籤)檢視前端頁面發出的請求URL。這個URL通常會與actionmap.xml中配置的路徑匹配。
  • 定位Action對映:根據瀏覽器中的請求URL,開啟actionmap.xml檔案,找到與該URL匹配的Action對映條目。這個條目會告訴你對應的Action類和方法。
  • 查詢Action類:在專案中找到這個Action類。Action類通常會繼承自ActionSupport或者實現Action介面。在類中查詢對應的方法,這個方法會處理請求並返回結果。
  • 跟蹤業務邏輯:在Action類的方法中,通常會呼叫Service層或業務邏輯類來處理請求。你可以跟蹤這些呼叫,理解業務處理的細節。
  • 返回檢視或資料:Action類處理完業務邏輯後,通常會返回一個檢視名稱或者直接返回資料(例如JSON格式),這部分可以透過Action的返回值或配置的Result型別來確認。

前後端呼叫流程的總結

  1. 前端發起請求:使用者在前端介面上進行操作(如點選按鈕),前端程式碼傳送HTTP請求。
  2. 請求對映到Action:Struts框架根據actionmap.xml中的配置,將請求路徑對映到對應的Action類和方法。
  3. Action類處理請求:Action類中的方法處理前端的請求,通常會呼叫業務邏輯或Service層。
  4. 返回結果:處理完請求後,Action類返回結果,可能是一個檢視名稱,也可能是直接的資料響應(如JSON),前端接收到結果並展示給使用者。

什麼是Action?

Action是一個核心概念,用於處理使用者請求、執行相應的業務邏輯,並返回處理結果。具體來說:

Action的角色和作用

  • 請求處理Action類負責處理來自使用者的請求。每次使用者在前端進行操作(例如提交表單、點選按鈕)時,產生的請求會透過Struts框架路由到相應的Action類。
  • 業務邏輯執行Action類會呼叫業務層或服務層來執行具體的業務邏輯。這可能包括資料驗證、資料庫操作、呼叫外部API等。
  • 結果返回:處理完請求後,Action類會返回一個結果,這個結果通常是一個檢視名稱(例如JSP頁面)或資料(如JSON格式的響應),Struts框架根據這個結果決定接下來要顯示的頁面或要返回的資料。

Action的工作流程

  1. 請求到達Struts框架:使用者在瀏覽器中發起一個請求(如提交表單)。
  2. 對映到Action:Struts根據配置檔案(如actionmap.xml)中的URL對映,將請求路由到相應的Action類。
  3. 執行Action邏輯:Struts呼叫Action類的execute()方法或其他指定方法,執行業務邏輯。
  4. 返回處理結果Action方法返回一個字串,指示框架接下來應該導航到的檢視頁面或響應資料。

配置Action

在Struts中,Action類的對映通常在配置檔案中進行。你可以在actionmap.xmlstruts-config.xml中看到類似如下的配置:

<action path="/login" 
        type="com.example.LoginAction"
        name="loginForm"
        scope="request"
        validate="true"
        input="/login.jsp">
    <forward name="success" path="/home.jsp"/>
    <forward name="failure" path="/login.jsp"/>
</action>
  • path:URL路徑,當請求這個路徑時,呼叫LoginAction類。
  • type:具體的Action類。
  • forward:處理完請求後,決定跳轉到哪個檢視。

Action與路由

Struts中的Action在某種程度上類似於Spring Boot中的路由,但兩者在實現方式和應用場景上有所不同。

  • Struts中的Action 負責處理請求,並透過配置檔案與URL路徑進行對映。
  • Spring Boot中的路由 則更像是透過註解驅動的請求處理方式,簡化了開發過程,並且更靈活。

什麼是Filter?

在Struts 2中,Filter是一個用於攔截和處理HTTP請求的元件。Struts 2透過Filter來處理進入應用程式的所有請求,並將這些請求分發給相應的ActionFilter在Struts 2中起到了一個重要的橋樑作用,它將請求的預處理和後處理與業務邏輯的實現分離開來。

Struts 2中的Filter概述

  • 核心FilterStrutsPrepareAndExecuteFilter
    • 在Struts 2中,StrutsPrepareAndExecuteFilter是最常用的過濾器。它是一個Servlet過濾器,負責攔截所有的HTTP請求,並將這些請求交由Struts 2框架進行處理。
    • StrutsPrepareAndExecuteFilter的主要功能包括:預處理請求、執行對應的Action、處理返回的結果、以及在整個請求處理流程結束後進行清理工作。

Filter工作流程

  1. 請求攔截
    • 當一個HTTP請求到達伺服器時,StrutsPrepareAndExecuteFilter會首先攔截這個請求。它攔截所有與應用程式相關的請求,通常是透過URL模式進行配置的(如/*)。
  2. 請求準備
    • StrutsPrepareAndExecuteFilter會對請求進行預處理,例如設定請求的字元編碼、處理檔案上傳等。此外,它還會確定哪個Action類應該處理這個請求,並將請求引數對映到相應的Action類的屬性中。
  3. 執行Action
    • 預處理完成後,StrutsPrepareAndExecuteFilter會將請求交給框架的核心元件,找到對應的Action類並執行其中的業務邏輯。
  4. 結果處理
    • Action類處理完業務邏輯後,會返回一個結果(通常是檢視名稱)。StrutsPrepareAndExecuteFilter會根據返回的結果,決定接下來要顯示的頁面或資料。
  5. 請求後處理
    • 在整個請求處理流程結束後,StrutsPrepareAndExecuteFilter還負責執行一些清理操作,如釋放資源、清理執行緒本地變數等。

如何配置Filter

在Struts 2中,Filter通常在web.xml中進行配置。配置StrutsPrepareAndExecuteFilter時,可以指定哪些請求需要由Struts 2框架處理。

web.xml中的配置示例

<filter>
    <filter-name>struts2</filter-name>
    <filter-class>org.apache.struts2.dispatcher.filter.StrutsPrepareAndExecuteFilter</filter-class>
</filter>

<filter-mapping>
    <filter-name>struts2</filter-name>
    <url-pattern>/*</url-pattern> <!-- 攔截所有請求 -->
</filter-mapping>

自定義Filter

除了StrutsPrepareAndExecuteFilter,開發者還可以自定義Filter,來實現特定的請求攔截和處理需求。自定義Filter可以用於實現如認證、日誌記錄、資料壓縮等功能。

自定義Filter示例

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

public class CustomFilter implements Filter {

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        // 初始化過濾器
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        HttpServletRequest httpRequest = (HttpServletRequest) request;
        HttpServletResponse httpResponse = (HttpServletResponse) response;

        // 執行過濾邏輯,例如檢查請求頭
        System.out.println("Request URI: " + httpRequest.getRequestURI());

        // 繼續處理請求
        chain.doFilter(request, response);
    }

    @Override
    public void destroy() {
        // 清理資源
    }
}

web.xml中配置自定義Filter

<filter>
    <filter-name>customFilter</filter-name>
    <filter-class>com.example.CustomFilter</filter-class>
</filter>

<filter-mapping>
    <filter-name>customFilter</filter-name>
    <url-pattern>/*</url-pattern> <!-- 攔截所有請求 -->
</filter-mapping>

新增一個action?

想法

新增一個action,讓現有的查詢在特定情況下出發該action

在哪個位置新增?前端去呼叫後端的action是透過URL實現的,那麼現在有兩種方式去“新增”一個action

1、在攔截器攔截到/web/Xx1Action時,直接修改為/web/Xx2Action,然後後續去走Xx2Action的邏輯

2、在前端呼叫Xx1Action後,在後端判斷由前端傳入的特定引數,然後跳轉執行Xx2Action的邏輯

在不新增對應前端按鈕的情況下,第一種方式的靈活性似乎更大,因為無需破壞現有的Xx1Action邏輯,當前端新增好按鈕之後也可以比較方便的遷移過去

計劃

玩家查詢 為測試入口(/web/PlayerInfoLogAction)進行兩種嘗試:

1、若當前的actionName為"PlayerInfoLogAction",那麼將其替換為"TestInfoLogAction"

從ActionFilter改起,當actionName=PlayerInfoLogAction時,將其賦值為"TestInfoLogAction"

此時會去actionPool裡面找這玩意

我的理解是:在player_web_actionMap.xml中新增自定義action事件,並在對應位置新建該action的實現程式碼以及facade方法即可

2、當前端輸入的賬號為“xixi”是,檢測到該引數後"PlayerInfoLogAction"要做對應的處理

嘗試1:新增TestInfoLogAction並跳轉執行

步驟一:配置actionmap檔案以及註冊bean

新增action或者介面時,首先要想的是對其進行約定(或者說“宣告”)【即:約定大於配置】

約定新的action

因為我們新增了一個action,那麼需要有一個檔案對其進行“路由”

前面也提到了,這個檔案就是player_web_actionMap.xml

domains\player_web_actionMap.xml中宣告一個新的action:TestInfoLogAction

<Action actionName="TestInfoLogAction" className="com.xxb.xxxl.web.action.TestInfoLog.TestInfoLogAction" facadeName="TestInfoQueryFacade" concurrencyInitNum="2" concurrencyMaxNum="13"/>

這裡主要規定了下面幾件事:

1、新增action的名字(actionName)

2、action具體的實現程式碼位置(className)

3、action對應的facade方法(facadeName)

約定新的對應介面

新增的action一定有對應的facade方法,這些方法會去進一步呼叫後端的介面與實現程式碼

因此實際上我們還會新增對應的介面,這些介面需要以bean的形式被spring管理

因此這裡也需要進行約定,在evs_service\src\main\resources\player_service_appContext.xml

這裡要將facade方法(及其例項化的物件)和後端介面服務(及其例項化的物件)進行約定

【參考其他介面的約定寫法即可】

步驟二:建立對應檔案

首先要初始化過濾器,並裝載action

-->修改tomcat目錄下的actionmap配置檔案

過濾器首先會去呼叫具體action的實現程式碼中的doSometings()

-->建立TestInfoLogAction.java

該檔案中的doSometings()又會呼叫facade方法

-->建立TestInfoQueryFacade.java

Facade方法需要繼承BaseFacade,其中的某些方法需要呼叫TestInfoQuery的具體實現

-->配置player_service_appContext.xml,將Facade方法加入bean容器中統一管理

-->建立TestInfoQueryService介面類,及其對應的實現類TestInfoQueryServiceImpl.java

步驟三:攔截器跳轉

首先加入判斷,當前端請求的action為PlayerInfoLogAction時,將actionName替換為TestInfoLogAction

步驟四:填充業務邏輯程式碼

再次明確一下想要乾的事情:TestInfoLogAction也是去查詢賬戶資料,但是查詢的玩家名稱為 xixi 時,返回資料均替換為XxxX

呼叫關係:doSometings()-->this.query()【facade方法】-->TestInfoLogActionService【後端介面】

相關文章