Spring+Struts2專案框架梳理
若基於Spring+Struts2的方式進行開發,前後端的互動邏輯會與boot系以及MCV的組織結構有所不同
這裡是對於學習過程的一些記錄
前置通用知識
Struts2框架資料
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型別來確認。
前後端呼叫流程的總結
- 前端發起請求:使用者在前端介面上進行操作(如點選按鈕),前端程式碼傳送HTTP請求。
- 請求對映到Action:Struts框架根據
actionmap.xml
中的配置,將請求路徑對映到對應的Action類和方法。 - Action類處理請求:Action類中的方法處理前端的請求,通常會呼叫業務邏輯或Service層。
- 返回結果:處理完請求後,Action類返回結果,可能是一個檢視名稱,也可能是直接的資料響應(如JSON),前端接收到結果並展示給使用者。
什麼是Action?
Action
是一個核心概念,用於處理使用者請求、執行相應的業務邏輯,並返回處理結果。具體來說:
Action
的角色和作用
- 請求處理:
Action
類負責處理來自使用者的請求。每次使用者在前端進行操作(例如提交表單、點選按鈕)時,產生的請求會透過Struts框架路由到相應的Action
類。 - 業務邏輯執行:
Action
類會呼叫業務層或服務層來執行具體的業務邏輯。這可能包括資料驗證、資料庫操作、呼叫外部API等。 - 結果返回:處理完請求後,
Action
類會返回一個結果,這個結果通常是一個檢視名稱(例如JSP頁面)或資料(如JSON格式的響應),Struts框架根據這個結果決定接下來要顯示的頁面或要返回的資料。
Action
的工作流程
- 請求到達Struts框架:使用者在瀏覽器中發起一個請求(如提交表單)。
- 對映到
Action
類:Struts根據配置檔案(如actionmap.xml
)中的URL對映,將請求路由到相應的Action
類。 - 執行
Action
邏輯:Struts呼叫Action
類的execute()
方法或其他指定方法,執行業務邏輯。 - 返回處理結果:
Action
方法返回一個字串,指示框架接下來應該導航到的檢視頁面或響應資料。
配置Action
在Struts中,Action
類的對映通常在配置檔案中進行。你可以在actionmap.xml
或struts-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
來處理進入應用程式的所有請求,並將這些請求分發給相應的Action
。Filter
在Struts 2中起到了一個重要的橋樑作用,它將請求的預處理和後處理與業務邏輯的實現分離開來。
Struts 2中的Filter
概述
- 核心
Filter
:StrutsPrepareAndExecuteFilter
- 在Struts 2中,
StrutsPrepareAndExecuteFilter
是最常用的過濾器。它是一個Servlet過濾器,負責攔截所有的HTTP請求,並將這些請求交由Struts 2框架進行處理。 StrutsPrepareAndExecuteFilter
的主要功能包括:預處理請求、執行對應的Action
、處理返回的結果、以及在整個請求處理流程結束後進行清理工作。
- 在Struts 2中,
Filter
工作流程
- 請求攔截:
- 當一個HTTP請求到達伺服器時,
StrutsPrepareAndExecuteFilter
會首先攔截這個請求。它攔截所有與應用程式相關的請求,通常是透過URL模式進行配置的(如/*
)。
- 當一個HTTP請求到達伺服器時,
- 請求準備:
StrutsPrepareAndExecuteFilter
會對請求進行預處理,例如設定請求的字元編碼、處理檔案上傳等。此外,它還會確定哪個Action
類應該處理這個請求,並將請求引數對映到相應的Action
類的屬性中。
- 執行
Action
:- 預處理完成後,
StrutsPrepareAndExecuteFilter
會將請求交給框架的核心元件,找到對應的Action
類並執行其中的業務邏輯。
- 預處理完成後,
- 結果處理:
Action
類處理完業務邏輯後,會返回一個結果(通常是檢視名稱)。StrutsPrepareAndExecuteFilter
會根據返回的結果,決定接下來要顯示的頁面或資料。
- 請求後處理:
- 在整個請求處理流程結束後,
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【後端介面】