Spring+Struts2项目框架梳理
若基于Spring+Struts2的方式进行开发,前后端的交互逻辑会与boot系以及MCV的组织结构有所不同
这里是对于学习过程的一些记录
前置通用知识
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
中看到类似如下的配置:
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
中的配置示例:
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
示例:
java
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
:
xml
<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
xml
<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【后端接口】