本文还有配套的精品资源,点击获取
简介:Struts 2.3.15.1是一个基于MVC模式的开源Java Web框架版本,提供了一套全面的特性来构建高效和可维护的企业级应用。它包含Action类与结果映射、拦截器、OGNL、插件架构、主题和皮肤、异常处理及强大的表单支持等核心特性。源码分析涉及 src 、 lib 、 docs 和 webapps 目录,帮助开发者深入理解框架内部工作原理,提升Java Web开发技能,优化和调试框架。
1. Struts 2.3.15.1框架概述
Struts 2是一个基于MVC设计模式的Web应用框架,用于简化企业级Java EE应用的开发。它自2000年诞生以来,经历了多个版本的迭代,直至2.3.15.1版本,该框架在Java开发者中仍享有广泛的流行度和好评。Struts 2的灵活性和模块化设计,让开发者可以快速搭建起结构清晰、易于维护的Web应用。
在Struts 2框架中,核心组件包括Action、Interceptor(拦截器)、Result和Value Stack等。框架的核心是一个强大的拦截器栈,它负责处理请求,将用户操作映射到相应的业务逻辑处理上,并将结果返回给用户界面。这种基于拦截器的处理机制,为框架提供了高度的可扩展性和灵活性。
Struts 2.3.15.1版本提供了丰富的特性,例如对OGNL(Object-Graph Navigation Language)的全面支持,使得数据绑定和操作更加方便;另外,它也加强了与第三方库的集成能力,使得开发者可以更加轻松地引入额外的功能,如日志记录、安全验证等。本章将概览Struts 2.3.15.1框架的主要组件和工作机制,为后续深入探讨MVC设计模式、Action类、拦截器、OGNL表达式语言、插件架构以及内部机制奠定基础。
2. MVC设计模式在Struts中的应用
2.1 MVC设计模式基础
2.1.1 MVC的概念与组成
MVC(Model-View-Controller)设计模式是一种经典的软件架构模式,它将应用程序分为三个主要的组件,每个组件都负责应用程序的一个特定方面。
Model(模型) :代表应用程序的数据结构,通常包括数据访问逻辑和业务逻辑。Model组件负责数据的存储、检索和更新。在Struts中,Model通常由JavaBean或者EJB来实现。 View(视图) :是用户看到并与之交互的界面。它用于展示Model的数据,但不包含业务逻辑。在Struts中,View层可以通过JSP来实现,其中利用Struts标签库来展示数据和收集用户输入。
Controller(控制器) :作为Model和View之间的中介者,它处理用户的输入,并调用Model和/或View去完成用户的请求。在Struts中,Controller的功能由Action和ActionServlet来实现。
MVC通过这种方式实现了关注点分离,使得每个组件更容易管理和维护。
2.1.2 MVC模式的优势与局限
MVC设计模式的优势主要体现在以下几个方面:
分离关注点 :将数据、业务逻辑、展示逻辑分离,使得代码更容易维护和扩展。 可维护性 :组件的独立性使得系统中的某个部分可以独立变更而不会影响到其他部分。 可测试性 :各个组件可以单独进行单元测试,提高整个系统的质量和可靠性。 灵活性 :允许动态更换视图或模型,使得系统在不同环境下有很好的适应性。
然而,MVC设计模式也存在一些局限性:
复杂性 :对于简单的应用程序来说,MVC可能显得过于复杂。 学习曲线 :开发者需要熟悉MVC的每个组件以及它们是如何协同工作的。 性能开销 :尤其是在Web应用中,为了分离关注点,可能会增加额外的资源消耗。
2.2 Struts中的MVC实现
2.2.1 Model层在Struts中的角色
在Struts框架中,Model层主要由Action类和JavaBean来实现。Action类负责处理业务逻辑,并将结果返回给框架以便决定接下来显示哪个视图。JavaBean通常用于表示Model中的数据。
Struts中Model层的实现与MVC模式中描述的基本一致,但略有不同,主要体现在以下几个方面:
Action类 :在Struts中,Action类通常是业务逻辑的封装,它接收来自客户端的请求,处理数据,并返回一个ActionForward对象给框架,该对象指示下一步跳转的视图或页面。
Model组件 :Struts允许将Model分为两部分:一部分是Action类中的业务逻辑处理部分,另一部分是JavaBean或EJB,后者通常负责数据的持久化。
2.2.2 View层与Struts标签库的结合
Struts提供了丰富的标签库,使得开发者能够方便地在JSP页面中展示数据和创建用户界面。
使用Struts标签库的优点包括:
易于使用 :Struts的标签库预定义了多种标签,简化了JSP页面的开发。 减少代码量 :标签库减少了JSP页面中Java代码的使用,提高了页面的可读性和维护性。 数据绑定 :Struts标签支持数据绑定,可以直接从Action类的属性中获取数据,简化了数据传递的逻辑。
2.2.3 Controller层与核心控制器
在Struts框架中,Controller层的核心是ActionServlet。ActionServlet充当整个应用的请求调度器,负责接收所有的HTTP请求,并根据配置文件(struts-config.xml)将请求转发到相应的Action类。
Struts Controller层的特点有:
请求映射 :ActionServlet通过struts-config.xml文件中的配置来识别特定的Action类,并将请求映射到相应的Action处理程序。 业务流程管理 :ActionServlet不仅转发请求,还负责管理业务流程,比如表单验证、国际化处理等。 分发响应 :处理完业务逻辑后,Action对象会返回一个ActionForward对象,ActionServlet根据该对象决定接下来的动作,可能是返回一个JSP页面或者重定向到其他Action。
通过以上分析,我们可以看到MVC设计模式在Struts框架中的具体实现方式。Model层的定义和作用、View层与标签库的结合,以及Controller层的核心功能和实现机制,共同构成了一套完整的Web应用程序开发体系。接下来,我们将深入探讨Struts的Action类与结果映射机制,进一步了解如何在Struts框架中实现业务逻辑和页面跳转。
3. Action类与结果映射机制
Action类作为Struts 2框架中的核心组件之一,负责接收用户的请求,并根据业务逻辑进行处理后返回相应的视图或者结果。它扮演着控制层的角色,是Model和View之间的桥梁。结果映射则是将Action处理后得到的数据转换为用户能够看见的界面元素的过程。本章节将深入探讨Action类的结构与作用,以及结果映射的具体实现机制。
3.1 Action类的作用与结构
3.1.1 Action接口与实现类
在Struts 2中,Action接口是一个空接口,没有定义任何方法,其目的是为了提供一种标记,以指示某个类是一个Action类。开发人员通常会继承 ActionSupport 类来实现Action。 ActionSupport 是一个非常实用的基类,提供了一些基础方法,例如 execute() 方法用于执行业务逻辑,以及 validation() 方法用于执行数据验证。
// 示例代码:Action类的基本结构
public class MyAction extends ActionSupport {
private String name;
public String execute() {
// 执行业务逻辑
return SUCCESS;
}
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
在上述代码中, MyAction 类继承了 ActionSupport 类,并重写了 execute() 方法来实现具体的业务逻辑。它还定义了一个 name 属性,并提供了相应的getter和setter方法。这种模式是开发Struts 2应用时常见的实践。
3.1.2 ActionContext与上下文管理
ActionContext 是Action的上下文环境,它在Action类中可以通过 getActionContext() 方法获取。ActionContext持有了当前Action的所有上下文信息,包括请求参数、会话信息等。 ActionContext 是Struts 2框架用于管理和传递Action执行过程中所需要的数据的主要工具。
// 示例代码:ActionContext的使用
public class MyAction extends ActionSupport {
public String execute() {
ActionContext context = ActionContext.getContext();
Map
// 可以在session中存储数据
session.put("user", "admin");
// 获取请求参数
Map
String name = parameters.get("name")[0];
// 处理业务逻辑...
return SUCCESS;
}
}
在这段代码中,通过 ActionContext 获取了当前的会话和请求参数,并进行了读写操作。这说明 ActionContext 为Action类提供了访问和操作上下文数据的能力。
3.2 结果映射与视图解析
3.2.1 结果类型与配置
Struts 2框架允许开发者配置Action执行的结果类型,常见的结果类型包括 dispatcher (转发)、 redirect (重定向)和 chain (转发链)。这些结果类型通过 struts.xml 文件配置来指定。例如:
在这个配置中,当 MyAction 的 execute 方法返回”success”时,用户将会被转发到 /success.jsp 页面。如果返回”error”,则会被重定向到 error.jsp 页面。
3.2.2 结果映射的实现原理
Struts 2的结果映射机制依赖于拦截器栈,尤其是 ResultInterceptor 拦截器,它负责将Action的结果映射到具体的视图。 ResultInterceptor 会查找配置文件中与返回值对应的结果配置,并执行相应的转发或重定向操作。
3.2.3 视图解析器的种类和选择
Struts 2提供了多种视图解析器,例如 JspResolver 、 VelocityResolver 和 FreemarkerResolver 等,用于将Action处理后的数据传递给对应的视图技术。选择哪种视图解析器取决于你使用的视图技术。
// 示例代码:视图解析器配置示例
在这个配置中,我们定义了 dispatcher 和 redirect 两种结果类型,并指定了其对应的类,这些类负责将结果转换为响应动作。开发者可以根据实际需要,添加更多视图解析器的配置。
在这一章节中,我们深入探讨了Struts 2的Action类以及结果映射的实现机制。了解了Action类的结构、作用以及如何配置和使用ActionContext进行上下文管理。我们也学习了结果类型、结果映射原理以及视图解析器的配置方法。掌握这些知识对于深入开发和优化基于Struts 2的应用至关重要。
4. 拦截器(Interceptors)的使用
拦截器(Interceptors)是Struts 2框架中用于增强和控制Action处理流程的强大机制。它们可以看作是Struts框架提供的AOP(面向切面编程)工具,允许开发者在Action执行前后插入自定义的处理逻辑。
4.1 拦截器机制简介
4.1.1 拦截器的工作原理
拦截器的执行基于一种叫做责任链(Chain of Responsibility)的设计模式。当一个请求到达Struts框架时,Struts会按照配置文件中定义的拦截器链依次执行拦截器,直到所有的拦截器都执行完毕后,才会调用目标Action类的方法。
每个拦截器在执行完毕自己的职责后,可以选择继续向下传递请求,即调用 Interceptor#intercept 方法中的 invocation.invoke() ,或者直接返回响应结果,终止请求的进一步处理。
4.1.2 拦截器与过滤器的区别
拦截器和过滤器(Filters)都是用于拦截请求并进行处理的组件,但在使用场景和实现机制上存在差异。过滤器是Java Servlet规范的一部分,依赖于Servlet容器。而拦截器是Struts框架特有的,可以访问到ActionContext和Action的状态信息。
过滤器通常用于处理诸如请求编码、权限检查等跨多个应用或框架的通用任务,而拦截器则更专注于Struts应用内部的逻辑,比如输入验证、日志记录等。拦截器的使用更加轻量级且与Action的业务逻辑紧密集成。
4.2 自定义拦截器
4.2.1 拦截器的生命周期与执行流程
自定义拦截器必须实现 com.opensymphony.xwork2.interceptor.Interceptor 接口,或者继承自 com.opensymphony.xwork2.interceptor.AbstractInterceptor 类。拦截器的生命周期包括初始化、拦截和销毁三个阶段。
初始化(init) :在拦截器实例化后,由Struts框架调用,用于执行初始化操作。 拦截(intercept) :这是拦截器的核心方法,请求处理过程中,拦截器通过此方法执行自定义逻辑。 销毁(destroy) :在Web应用卸载或重新加载时,由Struts框架调用,用于清理资源。
拦截器的执行流程在Struts框架中是顺序执行,后一个拦截器的执行依赖于前一个拦截器调用 invocation.invoke() 方法。
4.2.2 创建和注册自定义拦截器
创建自定义拦截器涉及到编写拦截器代码并配置到 struts.xml 文件中。
public class MyInterceptor extends AbstractInterceptor {
@Override
public String intercept(ActionInvocation invocation) throws Exception {
// 自定义前置处理逻辑
String result = invocation.invoke();
// 自定义后置处理逻辑
return result;
}
}
配置拦截器:
上述配置中, myInterceptor 是我们自定义的拦截器,它会在 defaultStack (默认拦截器栈)中的拦截器之前执行。
4.2.3 拦截器链的配置与管理
拦截器链的配置允许开发人员灵活地定义请求的处理流程,其中,
在Struts配置文件中,可以定义多个拦截器栈,并在不同的Action配置中引用它们。这样的配置提高了代码复用性,并且简化了维护过程。
由于拦截器与Action的执行流程密切相关,正确配置和管理拦截器链对于保持应用的健壮性和可维护性至关重要。
在实际应用中,开发者可以根据具体的业务需求,灵活地创建、配置和组合拦截器,以实现更加灵活和强大的业务逻辑控制。
5. OGNL表达式语言
5.1 OGNL基础
5.1.1 OGNL的定义和作用
Object-Graph Navigation Language (OGNL) 是一种强大的表达式语言,用于获取和设置Java对象的属性,以及调用Java对象的方法。OGNL在Struts框架中扮演着极其重要的角色,特别是在ActionContext中,它为Struts的MVC设计模式提供了一种简洁的方式来访问模型(Model)数据。
OGNL 表达式语言在开发Web应用时,可以用来进行数据传递和操作。通过OGNL,可以方便地读写对象的属性,调用对象的方法,以及执行基本的集合操作。OGNL不仅能够访问和操作JavaBean对象,还能够处理集合和数组。
5.1.2 OGNL的表达式语法
OGNL 的表达式语法比较简单,但是非常强大。基本的OGNL表达式包括访问对象属性、调用对象方法、访问静态属性、执行算术运算、访问集合元素等。
属性访问 :通过点操作符 . 或方括号 [] 来访问对象的属性,例如 user.name 或 user['name'] 。 方法调用 :通过在表达式中直接使用方法名并传入参数来调用对象的方法,例如 user.getName() 或 user.get('name') 。 静态属性和方法访问 :使用 @ 符号来访问静态属性或调用静态方法,例如 @Math@PI 或 @Collections@EMPTY_LIST 。 集合操作 :支持对集合进行索引、范围访问以及映射转换等操作。 运算符 :支持逻辑运算符( && 、 || 、 ! )、关系运算符( == 、 != 、 > 、 < )以及算术运算符( + 、 - 、 * 、 / )等。 逻辑运算 :可以进行条件判断等逻辑操作,例如使用三元运算符 (a ? b : c) 。
5.2 OGNL在Struts中的应用
5.2.1 OGNL与ActionContext的集成
在Struts 2框架中,OGNL与ActionContext的集成使其能够访问和操作Action上下文中的数据。ActionContext是存储与当前HTTP请求相关的数据的容器,它包含了Action的实例以及其他与请求处理相关的数据。OGNL 通过 ActionContext 提供的 API,可以访问 ActionContext 中的值栈(Value Stack)。
由于OGNL是作为Struts2核心处理流程的一部分,因此它能够访问到许多默认的和自定义的属性,例如:
表单数据 :当Struts2拦截表单提交时,表单数据会自动填充到值栈中。 请求参数 :OGNL可以获取到HTTP请求中的参数。 会话数据 :OGNL同样能够访问存储在HTTP会话中的数据。
5.2.2 OGNL访问Model属性和方法
在Struts2中,Model层通常由Action类来表示。OGNL使得Action类可以非常方便地暴露其属性和方法给JSP视图或其他组件。当Action类中的属性值发生变化时,这些变化可以立即反映到JSP页面上,反之亦然。
通过OGNL,开发者可以:
读取属性值 :在JSP页面中,可以使用OGNL表达式直接读取Action的属性值,例如 ${user.name} 。 设置属性值 :通过表单提交,OGNL可以将用户输入的值更新到Action的属性中,例如使用表单标签
5.2.3 OGNL的安全问题与防范
虽然OGNL非常强大,但它也可能带来安全风险。OGNL表达式可以访问和执行任意的Java代码,如果不加以控制,这可能会成为应用程序的一个安全漏洞。
为了防范潜在的安全问题,Struts2框架采取了以下措施:
表达式过滤器 :Struts2默认会过滤掉一些可能导致安全问题的OGNL操作符,比如 # 和 $ 。 沙箱模式 :在沙箱模式下,OGNL不能执行任何静态方法或访问任何静态字段。 安全限制 :开发者可以通过配置文件来指定哪些Java类型和方法是允许的,以及限制对某些敏感类的访问。
例如,可以在 struts.xml 文件中设置OGNL为沙箱模式:
开发者应始终注意OGNL的使用,尤其是其访问对象属性和方法的能力,避免不加选择地暴露敏感数据,或者允许执行不受限制的代码。
请注意,以上代码块仅为示例,实际开发中应根据具体需求进行配置。
6. 插件架构与集成第三方库
6.1 插件架构的实现原理
6.1.1 插件的定义和加载机制
在Struts框架中,插件架构提供了一种灵活的扩展机制,允许开发者通过添加插件来扩展框架的功能,而不必修改框架本身。一个插件可以看作是一个独立的模块,它能够监听或修改Struts框架中的核心行为。
插件的定义通常包含一个或多个实现 com.opensymphony.xwork2.plugin.Plugin 接口的Java类。这些类需要被配置在Struts的配置文件( struts.xml )中,通过
加载机制是通过Struts的启动过程自动识别和初始化配置好的插件。插件被加载后,可以通过覆盖 init 和 destroy 方法来执行初始化和销毁时的代码。这些方法会在Struts框架启动和停止时被调用,从而给插件提供了监听框架生命周期的手段。
6.1.2 插件与核心框架的交互
插件与核心框架的交互主要通过拦截器(Interceptors)和结果处理器(Result Handlers)来实现。插件可以提供自己的拦截器来处理请求的前后逻辑,或者修改请求处理流程中的数据。当一个请求到达框架时,它会遍历所有已加载插件的拦截器链,执行它们的 intercept 方法。
交互的另一种方式是通过扩展核心动作类。插件可以定义自己的动作类并将其与特定的URL模式关联,这样在请求到达这些URL时,框架会实例化并调用插件中定义的动作类。
6.2 第三方库的集成方法
6.2.1 通过插件集成第三方库
集成第三方库最直接的方式是通过插件。插件可以包含任何第三方库的JAR文件,并将它们包含在自己的类路径中。通过这种方式,插件可以封装第三方库的功能,并通过拦截器或自定义动作类的形式,将这些功能暴露给Struts框架的其他部分。
开发插件时,你可以使用Apache Maven或Gradle等构建工具来管理第三方库的依赖关系,并在插件的构建过程中将这些依赖打包。当插件被加载时,这些库也随之加载,并可被框架使用。
6.2.2 配置与使用第三方库的示例
以集成日志库log4j为例,你可以创建一个插件并在其依赖中包含log4j。然后在插件的初始化方法中配置log4j的 LogManager 。
public class MyPlugin implements Plugin {
public void init() {
// 使用log4j配置系统
PropertyConfigurator.configure("log4j.properties");
// 记录插件初始化的日志信息
LOG.info("MyPlugin has been initialized.");
}
public void destroy() {
// 插件销毁时的日志记录
LOG.info("MyPlugin is being destroyed.");
}
}
在Struts配置文件中配置插件:
6.2.3 第三方库版本管理与兼容性
在集成第三方库时,版本管理是一个重要的考虑因素。为了保持应用的稳定性,通常推荐使用第三方库的稳定版本,并遵循其官方发布的兼容性列表。
要处理不同版本的第三方库之间的兼容性问题,可以在插件中实现版本检测逻辑,并在不兼容的情况下提供替代的实现方案。例如,可以创建一个统一的API接口,并为不同版本的库实现不同的适配器。这样,即便第三方库更新,只要接口保持不变,应用的其他部分通常无需修改。
public interface ThirdPartyLibraryAPI {
void performAction();
}
public class OldLibraryAdapter implements ThirdPartyLibraryAPI {
public void performAction() {
// 使用旧版本库的方法
}
}
public class NewLibraryAdapter implements ThirdPartyLibraryAPI {
public void performAction() {
// 使用新版本库的方法
}
}
在配置文件中,可以通过一个常量来指定使用的适配器实现类:
通过这种方式,可以有效地管理第三方库的版本和兼容性问题,同时保持应用代码的整洁和可维护性。
7. 深入学习Struts框架内部机制
7.1 源码结构与关键文件分析
7.1.1 Struts源码结构概览
了解Struts的源码结构是深入学习框架内部机制的重要一步。Struts的源码可以被分为几个主要模块,这些模块共同协作实现了MVC架构和Web层的处理。让我们深入到Struts的核心源码结构:
src/core :包含Struts的核心代码,如拦截器、类型转换器、动作类等。 src/convention :包含用于自动扫描动作类的约定插件。 src/others :包含一些旧版的遗留代码,现代开发中使用较少。 src/xwork :是Struts的底层框架,提供了Web层处理的基础。
通过解析这些源代码目录,我们可以对Struts的组件划分有一个清晰的了解,并且知道哪些模块承载了框架的核心功能。
7.1.2 核心组件源码解读
接下来,我们来深入分析几个核心组件的源码,以便更好地理解它们的实现和作用:
ActionSupport :是所有动作类的基类,提供了默认的验证、国际化等功能。 DefaultActionInvocation :负责流程控制,串联起拦截器、动作类等的执行。 ognl.OgnlContext :用于存储和访问OGNL表达式中的数据。
通过阅读源码,我们会发现这些组件是如何相互协作完成一次请求处理的整个流程。
7.2 框架运行机制与核心流程
7.2.1 请求处理的生命周期
Struts框架处理Web请求的生命周期从接收请求开始,一直持续到响应返回给客户端。这一过程大致包含以下几个阶段:
请求接收:容器接收到客户端的HTTP请求。 路由解析:根据配置文件确定请求将被哪个Action处理。 拦截器链执行:按顺序执行配置的拦截器链。 Action执行:执行对应的Action方法,进行业务逻辑处理。 结果返回:根据返回的结果类型,进行视图跳转或数据返回。
下面是一个示例代码块,展示了从接收到处理请求的流程:
public class StrutsRequestProcessor implements RequestProcessor {
public String process(HttpServletRequest request, HttpServletResponse response, boolean b) throws IOException {
// 处理请求的代码...
}
// 其他方法...
}
7.2.2 数据处理与类型转换机制
在Struts框架中,数据处理包括数据的接收、验证和转换。这些功能涉及到几个关键组件:
ParametersInterceptor :用于解析请求参数。 ValidationInterceptor :进行动作类的验证。 conversion.Converter :处理类型转换。
数据处理和类型转换是通过OGNL实现的,OGNL在内部负责解析和执行相关的表达式。
7.3 异常处理机制与表单验证支持
7.3.1 异常处理策略
Struts框架通过定义 exception.ExceptionManager 来处理异常。异常处理策略包括记录异常信息、显示错误信息到用户界面等。开发者可以自定义异常处理,以适应不同的需求和场景。
7.3.2 表单验证流程与实现
Struts提供了一种声明式验证机制,允许开发者在配置文件中定义验证规则,而无需编写验证逻辑代码。验证器继承自 ActionValidator ,通过实现 validate 方法来进行具体的验证逻辑。
7.3.3 自定义验证器的创建与应用
自定义验证器需要实现 ActionValidator 接口,并在 struts.xml 中声明。下面是一个简单的自定义验证器示例:
public class MyCustomValidator implements ActionValidator {
public boolean validate(ActionInvocation invocation, ActionForm form) {
// 自定义验证逻辑...
return true;
}
}
然后,在 struts.xml 中声明和配置自定义验证器:
通过上述内容,我们深入探讨了Struts框架的内部机制,从源码结构到运行机制,再到异常处理和表单验证,这有助于开发者在实际工作中更好地使用和优化Struts框架。
本文还有配套的精品资源,点击获取
简介:Struts 2.3.15.1是一个基于MVC模式的开源Java Web框架版本,提供了一套全面的特性来构建高效和可维护的企业级应用。它包含Action类与结果映射、拦截器、OGNL、插件架构、主题和皮肤、异常处理及强大的表单支持等核心特性。源码分析涉及 src 、 lib 、 docs 和 webapps 目录,帮助开发者深入理解框架内部工作原理,提升Java Web开发技能,优化和调试框架。
本文还有配套的精品资源,点击获取
