简介:Struts2是一个开源的JavaEE Web应用程序框架,基于MVC设计模式。本笔记深入讲解了Struts2的核心概念,包括Action类的工作原理、struts.xml配置文件的使用、结果类型和OGNL表达式语言的应用、表单提交的自动数据校验、以及与Spring框架的集成。此外,还讨论了Tiles模板技术和Struts2工具组件的使用,以及ActionContext、FilterDispatcher和拦截器链等内部机制。通过阅读此笔记,开发者可以全面掌握Struts2框架,提高Web应用开发的效率和质量。
1. MVC设计模式在Struts2中的应用
在现代Web开发中,MVC设计模式是一种流行的架构模式,它通过将应用分为三个主要部分——模型(Model)、视图(View)和控制器(Controller),来降低代码的复杂性,并提高系统的可维护性和扩展性。Struts2作为一个基于MVC设计模式的Java Web框架,提供了一套完善的机制,使得开发者可以有效地组织代码,管理Web应用的业务逻辑和表现层。
在Struts2框架中,Action类扮演着控制器的角色,负责接收用户请求并根据不同的业务逻辑转发给相应的模型处理。模型部分通常由JavaBean或EJB等组件构成,它们是应用业务逻辑的载体。视图则由JSP或其他模板技术实现,用于展示数据和用户界面。Struts2通过配置文件struts.xml将这些组件相互关联起来,实现了MVC设计模式的分离与协同工作。
通过本章的学习,我们将深入理解MVC模式在Struts2中的具体应用,并掌握如何高效地利用这一模式构建可维护、可扩展的Web应用。
2. Action类与业务逻辑处理
2.1 Action类的基础概念
2.1.1 Action类的职责与生命周期
Action类在Struts2框架中扮演着至关重要的角色,它是业务逻辑处理的中心。一个Action类通常负责接收用户请求,并调用服务层(Service Layer)来处理业务逻辑,最后返回一个结果视图(Result View)给用户。Action类的生命周期包括以下几个阶段:
- 实例化 :当请求到达Struts2框架时,框架会根据配置文件
struts.xml
中的配置信息,创建Action类的实例。 - 执行 :执行过程中,Action类的方法会被调用。在这个过程中,Action类可以访问请求参数,与服务层交互,并设置返回值。
- 结果返回 :Action类方法执行完毕后,会返回一个字符串(Action类的返回值),该字符串将被Struts2框架用来决定执行哪个结果(Result)。
- 销毁 :在请求处理完毕后,Action类的实例将被销毁。
Action类的生命周期是由Struts2框架控制的,开发者通常不需要手动干预。了解这个生命周期对于设计可重用、高效的Action类是非常重要的。
2.1.2 Action接口与Result接口的作用
在Struts2框架中,Action接口和Result接口是定义Action类和结果视图的核心接口。
Action接口 定义了几个重要的方法:
-
execute()
: 这是执行业务逻辑的主要方法。开发者需要重写该方法,以实现具体的业务逻辑。 -
input()
: 通常用于表单验证失败时,返回输入视图的名称。 -
success()
: 表示业务逻辑执行成功时,返回的结果视图名称。 -
error()
: 表示业务逻辑执行中出现异常时,返回的结果视图名称。
开发者根据业务需求,可以实现这些方法来处理不同的场景。
Result接口 则是定义结果视图如何被返回到客户端:
- 一个Result可以配置为返回一个JSP页面、一个JSON或XML响应、一个重定向URL等。
- 结果视图的配置是在
struts.xml
文件中完成的,开发者需要在Action类返回的字符串和结果视图之间建立映射关系。
这些接口的实现和配置,使得Action类可以专注于业务逻辑的处理,而结果的呈现交给框架去完成。
2.2 Action类的编写与实现
2.2.1 实现业务逻辑的Action类示例
一个典型的Action类实现可以如下所示:
public class LoginAction implements Action {
private String username;
private String password;
private boolean success = false;
@Override
public String execute() {
// 业务逻辑代码,根据用户名和密码判断登录是否成功
if ("admin".equals(username) && "123456".equals(password)) {
success = true;
return SUCCESS; // 返回成功结果
} else {
return INPUT; // 验证失败,返回输入表单
}
}
// getter和setter方法
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public boolean isSuccess() {
return success;
}
public void setSuccess(boolean success) {
this.success = success;
}
}
在这个示例中, LoginAction
实现了 Action
接口,其中 execute()
方法用于处理登录逻辑,并根据验证结果返回相应的值。
2.2.2 Action类中的数据传递与结果返回
在Action类中,数据通常从表单传递到Action类的属性,然后在Action类的方法中处理这些数据,并返回相应的结果。数据传递可以通过Struts2提供的标签 <s:property>
来实现。以下是一个简单的JSP页面,用于提交表单并传递数据:
<s:form action="login">
<s:textfield name="username" label="Username"/>
<s:password name="password" label="Password"/>
<s:submit value="Login"/>
</s:form>
在这个表单中,当用户提交后,Struts2会自动填充Action类中的 username
和 password
属性。之后, LoginAction
的 execute()
方法会被调用,并根据逻辑返回 success
或 input
。
以下是 struts.xml
中对应的配置:
<action name="login" class="com.example.LoginAction">
<result name="success">/success.jsp</result>
<result name="input">/login.jsp</result>
</action>
在上述配置中, name="login"
表示请求的URL映射, class="com.example.LoginAction"
表示对应的Action类。 <result>
标签定义了不同返回值对应的结果视图。
通过上述步骤,Action类成功地处理了用户请求,并实现了数据的传递与结果的返回。
接下来,我们将深入探讨 struts.xml
配置文件的详细内容,了解如何通过这个文件将请求映射到不同的Action类,并配置结果视图。
3. struts.xml配置文件详解
3.1 struts.xml的基础知识
3.1.1 配置文件的作用与结构
Struts2框架通过 struts.xml
配置文件来控制框架行为,定义了框架中Action组件的映射、拦截器栈、结果类型和国际化资源等。这种配置方式的好处在于,它为Struts2提供了高度的可配置性和灵活性,开发者可以按照需求定制框架行为而无需修改Java代码。
配置文件的基本结构由 <struts>
根元素开始,内部可以定义多个包,每个包下面可以配置 <action>
元素,用于定义特定的Action映射。下面是 struts.xml
的基础结构示例:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.5//EN"
"***">
<struts>
<package name="default" extends="struts-default">
<action name="exampleAction" class="com.example.actions.ExampleAction">
<result name="success">/success.jsp</result>
</action>
</package>
</struts>
在上述结构中, <package>
元素是配置文件中的核心单位,它定义了一个独立的命名空间,这个命名空间可以包含多个Action映射。 <action>
元素用于指定一个请求对应的Action类和处理该请求的结果页面。 <result>
元素定义了当Action执行成功时返回的视图路径。
3.1.2 常见的配置元素解析
-
extends
: 指定继承自哪个包,一般继承struts-default
包以使用Struts2提供的拦截器栈和其他默认行为。 -
namespace
: 定义包的命名空间,用于区分不同的Action组。 -
action
: 用于映射一个请求到对应的Action类,并指定一系列的结果类型。 -
result
: 指定一个Action执行完毕后返回的视图,支持不同的视图技术,如JSP、FreeMarker模板等。 -
interceptor-ref
: 引用自定义拦截器或Struts2提供的拦截器,用于在Action执行前或执行后添加自定义行为。 -
constant
: 可以定义或修改Struts2的配置常量,影响整个框架的行为。
3.2 struts.xml的高级配置技巧
3.2.1 命名空间与包的配置
命名空间和包的配置是大型项目中非常重要的概念,它有助于管理Action,并且可以避免不同模块之间的命名冲突。通过配置命名空间,可以为一组Action提供一个统一的路径前缀。例如:
<package name="account" namespace="/account" extends="struts-default">
<!-- ... -->
</package>
在这个例子中,所有的Action都会带上 /account
前缀。如果一个Action是 userLogin
,那么访问URL将会是 /account/userLogin
。这样的结构有助于组织和维护大型应用中的代码。
3.2.2 常用拦截器的使用与配置
拦截器是Struts2中用于封装请求处理逻辑的一个强大机制。通过 <interceptor-ref>
元素,可以在包级别引用拦截器,也可以在具体的Action级别覆盖这些拦截器。下面是如何配置自定义拦截器的示例:
<interceptors>
<interceptor name="myInterceptor" class="com.example.interceptors.MyInterceptor"/>
<interceptor-stack name="myStack">
<interceptor-ref name="myInterceptor"/>
<interceptor-ref name="defaultStack"/>
</interceptor-stack>
</interceptors>
<package name="default" extends="struts-default" interceptor-ref="myStack">
<!-- ... -->
</package>
这里定义了一个名为 myInterceptor
的拦截器和一个名为 myStack
的拦截器栈。然后,我们使用 myStack
拦截器栈代替默认的拦截器栈。现在,每个Action在执行之前都会先经过 myInterceptor
拦截器处理。
在下一章节中,我们将探讨更多关于拦截器的高级用法,包括如何为特定的Action或一组Action定制拦截器栈。
4. 多种结果类型的使用和OGNL表达式语言
4.1 结果类型的分类与应用场景
4.1.1 常见结果类型的介绍与使用
Struts2框架提供了多种结果类型(Result Types),使得开发者能够根据不同的需求选择合适的返回方式,以实现灵活的视图控制和数据处理。常见的结果类型包括 dispatcher
、 chain
、 redirect
和 redirect-action
等。
-
dispatcher
结果类型用于分发请求到一个JSP页面,它是最常用的类型,适用于展示数据和视图渲染的场景。 -
chain
结果类型允许你将请求传递到另一个action,而无需重新通过filter栈,这个方法可以用来实现业务逻辑的串行化处理。 -
redirect
结果类型会创建一个HTTP重定向响应,通常用于在action执行成功后,将用户重定向到另一个页面,而不会返回给前一个页面。 -
redirect-action
结果类型结合了chain
和redirect
的功能,实现了重定向同时传递参数到另一个action。
下面是一个简单的 dispatcher
类型的结果配置示例:
<result name="success" type="dispatcher">/WEB-INF/success.jsp</result>
4.1.2 结果类型的参数配置与注意事项
在配置结果类型时,我们可能会添加一些参数,这些参数将改变结果类型的默认行为,以适应更具体的场景需求。例如,我们可以在 dispatcher
结果类型中加入参数 location
,来指定跳转的页面。
<result name="success" type="dispatcher">
<param name="location">/WEB-INF/success.jsp</param>
</result>
需要注意的是,有些结果类型的参数可能与其他类型冲突或不兼容。比如使用 redirect
类型时,就不可能再使用 location
参数,因为重定向是基于URL的,与内部路径无关。
在配置文件 struts.xml
中使用结果类型时,必须确保已正确定义了结果类型的类路径。Struts2提供默认的结果类型,但是也可以自定义结果类型,通过继承已有的结果类型,并重写 execute
方法来实现。
4.2 OGNL表达式语言详解
4.2.1 OGNL的基本语法与特性
OGNL(Object-Graph Navigation Language)是一种强大的表达式语言,用于获取和设置Java对象的属性。在Struts2框架中,OGNL被广泛应用于值栈操作、动态方法调用和数据传递等。
- 访问属性:使用点(
.
)或者方括号([]
)语法访问对象属性。 - 字面量:OGNL支持字符串、整数、浮点数、布尔值、null等基本数据类型的字面量。
- 调用方法:可以使用OGNL表达式调用Java对象的方法。
- 集合操作:OGNL支持对集合的访问、过滤和转换操作。
- 赋值操作:OGNL允许直接对值栈中的对象属性进行赋值。
4.2.2 OGNL在Struts2中的应用实例
在Struts2中,OGNL被用于很多场景,最常见的是在 <s:property>
标签中显示数据,以及在 <s:set>
标签中修改数据。
<s:property value="user.name" />
在上述代码中, user.name
是一个OGNL表达式,用于显示用户对象的 name
属性。
<s:set name="user.name" value="'John Doe'" />
这个例子中, <s:set>
标签用于修改值栈中 user
对象的 name
属性,将 name
属性设置为 John Doe
。
如果要使用OGNL表达式传递参数到另一个页面或者Action,可以结合 param
标签使用:
<s:form action="login">
<s:textfield name="username" />
<s:submit value="Submit" />
</s:form>
提交表单后, username
字段的值会作为参数传递到 login
Action,通过OGNL表达式可以在 login
Action中获取这个参数:
String username = (String) ActionContext.getContext().getValueStack().findValue("username");
这个例子展示了如何通过OGNL表达式在Struts2中访问和操作数据。由于OGNL的强大功能,使得数据的传递和处理在Struts2中变得非常灵活和方便。
5. 自动数据校验机制
5.1 数据校验的重要性与方法
5.1.1 前端校验与后端校验的区别
在Web开发中,数据校验是确保数据完整性和安全性的关键步骤。它主要分为前端校验和后端校验两种形式,两者虽然目的相同,但在实现方式和作用时间点上有着显著的不同。
前端校验是在客户端执行的,一般由JavaScript脚本或HTML5提供的表单验证功能来完成。它的优点是能够即时反馈给用户,提高用户体验,并减少服务器的无效处理,减轻服务器的负担。然而,前端校验也有明显的缺点,比如用户可能会关闭浏览器中的JavaScript功能,或者绕过前端验证直接构造请求发送到服务器,这就使得前端校验不能单独作为数据完整性的保证。
后端校验发生在服务器端,是在数据到达服务器后进行的。后端校验不依赖于用户浏览器环境,更加可靠和安全。后端校验主要由应用程序逻辑来实现,如在Java Web应用中,Struts2框架提供了强大的后端校验机制。后端校验的重要性在于,无论客户端如何尝试绕过验证,服务器端的数据校验能够确保数据的最终一致性。
5.1.2 Struts2中的校验框架与机制
Struts2框架内置了强大的校验框架,通过实现其提供的校验接口(如 ValidationAware
、 TextProvider
),开发者可以轻松地为应用增加数据校验机制。Struts2校验框架支持两种类型的校验:拦截器校验和自定义校验。
拦截器校验通过配置文件定义校验规则,当Action被调用时,拦截器会自动执行校验逻辑,并根据校验结果决定是否继续执行Action。常见的拦截器如 fieldexpression
、 double
、 int
等,它们分别用于校验字段是否匹配特定的正则表达式或数据类型。
自定义校验则允许开发者通过编写自定义的校验器来扩展校验功能。自定义校验器需要实现 Validator
接口,并在 validate
方法中编写具体的校验逻辑。与拦截器校验不同的是,自定义校验器可以访问到Action的上下文信息,进行更为复杂的校验。
5.2 校验规则的实现与配置
5.2.1 内建校验器与自定义校验器的使用
Struts2框架中提供了多种内建的校验器,例如 required
校验器用于确保字段不为空, int
校验器用于验证整数,还有 double
、 date
、 expression
等多种校验器,几乎涵盖了常见的数据验证需求。
使用内建校验器非常简单,只需在 struts.xml
中配置相应的校验规则即可。下面是一个使用 required
和 int
校验器的配置示例:
<field name="name">
<field-validator type="required">
<message>姓名字段不能为空!</message>
</field-validator>
</field>
<field name="age">
<field-validator type="int">
<param name="min">18</param>
<param name="max">60</param>
<message>年龄必须是一个介于18到60之间的整数!</message>
</field-validator>
</field>
在上述配置中, name
字段必须非空, age
字段必须是介于18到60之间的整数。
自定义校验器则需要开发者编写Java代码,并且在 struts.xml
中通过 validator
元素注册。以下是一个简单的自定义校验器实现:
public class CustomValidator implements Validator {
public boolean validate(Object obj, ValidationContext context) {
// 获取Action中的字段值
MyAction action = (MyAction) obj;
boolean valid = true;
String message = "";
// 校验逻辑
if(action.getField1() == null || action.getField1().trim().isEmpty()) {
valid = false;
message = "Field1 must not be blank";
}
// 将校验结果和信息保存到ValidationContext中
if(!valid) {
ValueStack vs = context.getValidationProvider().createValueStack();
vs.getContext().put("myField", message);
context.addMessage("myField", message);
}
return valid;
}
}
在 struts.xml
配置文件中,注册并使用自定义校验器:
<action name="myAction" class="com.example.MyAction">
<validator type="com.example.CustomValidator" />
...
</action>
5.2.2 校验文件的编写与校验流程
校验文件通常是XML格式,它包含了校验规则的定义,放置在 src/main/resources
目录下,并且与相应的Action类同名。校验文件的命名约定是 Action类名-validation.xml
。例如,对于 MyAction
类,相应的校验文件名应为 MyAction-validation.xml
。
校验文件由一系列的 field
元素组成,每个 field
元素对应Action类中的一个属性,并包含一个或多个 field-validator
元素,定义了具体的校验规则。下面是一个简单的校验文件示例:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE validators PUBLIC "-//Apache Struts//XWork Validator 1.0//EN" "***">
<validators>
<field name="username">
<field-validator type="requiredstring">
<message>用户名是必需的</message>
</field-validator>
<field-validator type="stringlength">
<param name="minLength">3</param>
<param name="maxLength">32</param>
<message>用户名长度必须在3到32个字符之间</message>
</field-validator>
</field>
<field name="password">
<field-validator type="requiredstring">
<message>密码是必需的</message>
</field-validator>
<field-validator type="stringlength">
<param name="minLength">6</param>
<param name="maxLength">16</param>
<message>密码长度必须在6到16个字符之间</message>
</field-validator>
</field>
</validators>
校验流程大致如下:
- 当Action被Struts2框架调用时,会首先查找是否存在对应的校验文件。
- 如果找到校验文件,则根据配置的校验规则依次进行校验。
- 校验过程中,如果某个规则未通过,则会收集错误信息,并将Action标记为无效。
- 如果存在多个校验错误,则会将所有收集到的错误信息一并返回给客户端。
通过配置和使用Struts2的校验机制,开发者可以确保用户提交的数据在到达业务逻辑处理之前,已经符合预定的格式和条件,从而增强应用的健壮性和安全性。
6. Struts2与Spring框架的集成
6.1 集成的必要性与优势
6.1.1 解决方案的对比分析
在企业级应用开发中,整合不同框架以实现最佳实践是常见的做法。例如,Struts2作为一个成熟的MVC框架,拥有强大的Web层处理能力,而Spring框架则以其依赖注入和面向切面编程(AOP)等特性在企业应用中广泛应用,尤其在业务逻辑层及持久层表现卓越。
对比纯Struts2和Struts2+Spring的集成方案,我们可以看到集成Struts2和Spring能够带来以下优势:
- 事务管理 :Spring提供的声明式事务管理能够有效管理业务逻辑层和持久层的事务,相比Struts2自带的事务管理更为强大和灵活。
- 依赖注入 :通过Spring的IoC容器,可以实现对象的依赖注入,降低对象之间的耦合度,使得单元测试和代码维护更为便捷。
- 业务逻辑处理 :Spring框架的service层可以有效处理业务逻辑,而Struts2主要处理视图层和控制层,两者结合可以发挥各自优势,提高开发效率。
- 集成第三方服务 :Spring提供了丰富的支持,包括但不限于JPA、Hibernate、JMS等,与Struts2集成后,能够更方便地集成这些服务。
6.1.2 Struts2与Spring集成的价值
将Struts2与Spring框架进行集成,不仅能够为开发者提供一个强大而灵活的应用架构,还有助于应用的扩展性和维护性。具体来说,这种集成的价值体现在以下方面:
- 统一的开发模式 :通过整合两大框架,开发者可以按照Spring的开发模式,使用Struts2作为前端控制器,进行统一的开发和维护。
- 模块化部署 :集成后的应用更容易实现模块化部署,从而提高了应用的可维护性与可扩展性。
- 代码优化和重构 :在集成Spring之后,可以通过Spring的切面编程(AOP)来优化代码,或者重构一些难以维护的代码块,如日志、事务处理等。
- 简化测试工作 :通过依赖注入和Spring的IoC容器,使得单元测试变得更加容易,测试覆盖率也相应提高。
6.2 集成的步骤与实践
6.2.1 配置文件的整合与调整
集成Struts2和Spring框架的第一步是配置文件的整合。这包括修改 struts.xml
和Spring的配置文件,如 applicationContext.xml
等。这里我们详细讲解如何进行这些配置:
- 整合
struts.xml
配置文件 :将原有的struts.xml
配置文件,按照Spring的配置方式调整,例如,将原有的Action类的实例化方式由Struts2自带的转换为Spring的方式。这通常需要在struts.xml
中添加constant
标签指定Spring的配置文件路径。
xml <constant name="struts.objectFactory" value="org.apache.struts2.spring.StrutsSpringObjectFactory" />
- 修改
applicationContext.xml
:在Spring的配置文件中,添加对应的Struts2 bean的配置。例如,将Struts2的Action类声明为Spring的bean。
xml <bean class="com.example.MyAction" name="myAction"> <property name="service" ref="myService" /> </bean>
在此配置中, MyAction
是Struts2中的一个Action类,而 myService
是定义在Spring中的业务逻辑层的bean。通过Spring的依赖注入, MyAction
可以使用 myService
中的方法。
6.2.2 实体类、Action类与服务层的交互
在集成过程中,实体类(Model)、Action类(Controller)和服务层(Service)之间的交互需要特别关注。正确配置这些组件之间的关系,是集成成功的关键。具体步骤如下:
- 创建服务层组件 :在Spring配置文件中定义业务逻辑处理的bean。这些bean通常对应于应用中的service层。
xml <bean id="myService" class="com.example.MyService"> <!-- service bean properties --> </bean>
- 在Action类中注入服务层bean :通过Spring的依赖注入机制,将服务层bean注入到Action类中,使得Action类可以调用业务逻辑。
java public class MyAction extends ActionSupport { @Autowired private MyService myService; public String execute() { // Use myService to call business logic here } }
- 与实体类的交互 :Action类通常会操作实体类来传递数据到视图层或者接收用户输入的数据。实体类也应作为服务层方法的参数或返回类型。
java public class MyService { public void processUser(User user) { // Process the user entity } }
在这个过程中,我们通常需要为实体类、Action类和服务层之间的依赖关系进行详细配置,以保证整个应用程序的正常运转。通过整合配置文件与调整代码间的交互,我们能够有效地将Struts2与Spring框架集成在一起,发挥各自的长处,构建一个高效且易于维护的企业级应用。
7. Tiles模板技术与页面布局复用
7.1 Tiles模板技术概述
7.1.1 Tiles在MVC中的角色与优势
Tiles是Apache Struts 2框架的一部分,旨在实现Web应用中页面布局的复用和模块化。在MVC模式中,Tiles扮演着视图层的角色,它允许开发者将页面分解为可复用的组件,通过组合这些组件来构建最终的页面布局。使用Tiles的优势在于:
- 代码复用 :重复使用的页面布局可以集中管理和维护,减少了代码冗余。
- 分离布局与内容 :内容的变动无需改动布局,布局的调整也无需影响内容。
- 提高开发效率 :通过预先定义好的布局模板,开发者可以快速搭建页面结构。
7.1.2 Tiles的基本配置与应用实例
配置Tiles通常涉及以下三个文件: tiles-defs.xml
、 struts.xml
以及JSP页面。下面是 Tiles 的基本配置过程和一个应用实例:
配置 Tiles
首先,在 struts.xml
文件中引入 Tiles 配置文件:
<struts>
<include file="tiles-defs.xml"/>
<!-- 其他配置 -->
</struts>
然后,在 tiles-defs.xml
中定义模板:
<tiles-definitions>
<definition name="baseLayout" template="/WEB-INF/layouts/base.jsp">
<put-attribute name="header" value="/WEB-INF/jsp/header.jsp"/>
<put-attribute name="body" value="/WEB-INF/jsp/body.jsp"/>
<put-attribute name="footer" value="/WEB-INF/jsp/footer.jsp"/>
</definition>
</tiles-definitions>
上述配置定义了一个名为 baseLayout
的模板,它使用了三个JSP组件: header
、 body
和 footer
。
应用实例
在Action中使用Tiles定义的布局:
public class ExampleAction extends ActionSupport {
public String execute() {
return SUCCESS;
}
}
在 struts.xml
中配置Action以应用Tiles布局:
<action name="example" class="com.example.ExampleAction">
<result name="success" type="tiles">examplePage</result>
</action>
这里指定了返回结果 success
使用 tiles
类型,并通过名为 examplePage
的Tiles定义来渲染页面。
7.2 页面布局的复用与管理
7.2.1 复用布局的创建与配置
为了创建可复用的布局,开发者需要定义各种通用的布局模板,并在这些模板中预留出可插入内容的区域。这些区域在Tiles配置文件中通过 <put-attribute>
标签定义。例如,一个带有导航栏和侧边栏的布局模板可能如下配置:
<definition name="layoutWithNavSidebar" extends="baseLayout">
<put-attribute name="sidebar" value="/WEB-INF/jsp/sidebar.jsp"/>
<put-attribute name="nav" value="/WEB-INF/jsp/nav.jsp"/>
</definition>
通过 extends
属性, layoutWithNavSidebar
继承了 baseLayout
,并在其基础上添加了 sidebar
和 nav
区域。
7.2.2 动态布局变化的实现方法
为了支持动态布局变化,开发者可以采用以下几种方法:
- 使用动态属性 :在Tiles配置文件中,使用
<put-attribute>
的dynamic
属性,允许在运行时动态设置组件的值。
<definition name="dynamicLayout" template="/WEB-INF/layouts/base.jsp">
<put-attribute name="body" value="/WEB-INF/jsp/body.jsp" dynamic="true"/>
</definition>
在 struts.xml
中,可以通过传递参数来动态改变 body
的值:
<action name="dynamicExample" class="com.example.DynamicAction">
<result name="success" type="tiles">dynamicLayout</result>
</action>
在 DynamicAction
的 execute
方法中,可以设置动态属性:
public class DynamicAction extends ActionSupport {
private String body;
public String getBody() {
return body;
}
public void setBody(String body) {
this.body = body;
}
public String execute() {
// 动态设置body内容
setBody("/WEB-INF/jsp/dynamicBody.jsp");
return SUCCESS;
}
}
- 自定义拦截器 :创建自定义拦截器,在拦截器中设置Tiles组件的属性,这使得布局变化可以在拦截器链中进行控制。
通过这些方法,开发者可以灵活地控制页面布局,满足复杂的页面构建需求,同时保证代码的整洁和维护的方便性。
简介:Struts2是一个开源的JavaEE Web应用程序框架,基于MVC设计模式。本笔记深入讲解了Struts2的核心概念,包括Action类的工作原理、struts.xml配置文件的使用、结果类型和OGNL表达式语言的应用、表单提交的自动数据校验、以及与Spring框架的集成。此外,还讨论了Tiles模板技术和Struts2工具组件的使用,以及ActionContext、FilterDispatcher和拦截器链等内部机制。通过阅读此笔记,开发者可以全面掌握Struts2框架,提高Web应用开发的效率和质量。