简介:Struts 2是Apache软件基金会的Java Web应用框架,基于MVC设计模式,为开发者提供强大的功能和灵活的架构。Struts 2的改进版本继承了Struts 1的许多优点,并加入了新特性。通过分析Struts 2.2.1版本中的关键组件,如javassist和commons-io,可以理解其内部工作原理和核心特性,包括Action与Result的处理、Tiles插件的布局管理、插件架构的扩展性、OGNL表达式语言、国际化支持、数据验证框架以及核心控制器FilterDispatcher。尽管Struts 2.2.1版本已较为陈旧,但对其的研究有助于更好地把握现代Web开发框架。
1. Struts 2开源项目概述
1.1 Struts 2的起源与背景
Struts 2是目前流行的Java EE Web应用框架之一,其源起于经典的Struts 1,并在2007年进行了全面的重构,引入了WebWork的核心机制,由此诞生了Struts 2框架。它的目标是提供一个简洁、高效且易于使用的Web层解决方案,以便开发人员可以快速创建交互式、动态网站。
1.2 Struts 2的主要特性
Struts 2框架具有多项特点,其中包括支持MVC设计模式、强大的插件系统、丰富的标签库、灵活的配置以及强大的数据验证框架。这些特性使得Struts 2成为构建企业级Web应用的有力工具。它以拦截器为其实现AOP(面向切面编程)的基础,这为各种横切关注点提供了优秀的解决方案。
1.3 Struts 2在现代Web开发中的地位
随着技术的发展,虽然有许多新的Web框架如Spring Boot和Java EE的原生解决方案兴起,Struts 2依然在一些遗留系统和新项目中占有重要地位。对于追求稳定性和功能全面性的企业,Struts 2提供的完善功能和成熟的生态系统,仍然是其选择使用的主要因素。随着本文的深入,我们将探索Struts 2如何通过其核心组件、插件系统和表达式语言等来满足开发需求。
2. 深入Struts 2核心组件
2.1 Struts 2 Action组件解析
2.1.1 Action的生命周期与作用
Action组件是Struts 2框架中的核心,它负责处理用户的请求并返回相应的响应。理解Action的生命周期对于开发者来说至关重要,因为这直接关系到应用的性能和稳定性。
Action的生命周期通常包括以下几个阶段:
- 初始化:Struts 2框架加载Action类并创建其对象实例。
- 拦截器链:Action实例被传递给配置的拦截器链进行预处理。
- 处理请求:调用Action的方法以处理请求。
- 结果展示:根据方法执行结果选择对应的Result视图返回给用户。
- 销毁:请求处理完成后,Action实例可以被销毁,释放资源。
Action组件的作用主要体现在以下几个方面:
- 分离业务逻辑和视图,使得应用的结构更清晰。
- 通过拦截器链实现预处理和后处理,增强处理请求的灵活性。
- 允许开发者通过实现Action接口或继承ActionSupport类来添加自定义逻辑。
Struts 2通过OGNL(Object-Graph Navigation Language)来访问和操作数据,使得Action组件能够轻松访问请求参数和处理业务逻辑。
代码块展示及解析:
下面是一个简单的Struts 2 Action组件示例代码:
import com.opensymphony.xwork2.ActionSupport;
public class LoginAction extends ActionSupport {
private String username;
private String password;
public String execute() {
// 这里将实现登录逻辑,并返回success或error
return SUCCESS;
}
// 省略getter和setter方法
}
在上述代码中, LoginAction
继承了 ActionSupport
类,这是一个提供了通用方法和属性的便利类。开发者可以重写 execute()
方法,这是默认的方法名,当用户提交表单时,Struts 2框架会调用这个方法来处理请求。返回值 SUCCESS
是一个常量,由Struts 2框架识别,用以表示该请求已成功处理,并且将跳转到对应的result配置中指定的视图。
2.1.2 如何定义与配置Action
在Struts 2中定义和配置Action主要涉及以下几个步骤:
- 创建Action类,实现
Action
接口或继承ActionSupport
类。 - 在
struts.xml
配置文件中定义Action的名称和属性。 - 为Action配置结果类型(Result)和拦截器(Interceptor)。
下面是一个 struts.xml
配置文件的示例:
<struts>
<package name="default" extends="struts-default">
<action name="login" class="com.example.LoginAction">
<result name="success">/welcome.jsp</result>
<result name="error">/login.jsp</result>
</action>
</package>
</struts>
在上述配置中,定义了一个名为 login
的Action。当Action成功执行时,用户将被重定向到 /welcome.jsp
页面;如果执行失败,则重定向到 /login.jsp
页面。 class
属性指定了要实例化的Action类的完全限定名。
2.1.3 Action的线程模型与并发问题
由于Java的特性,Struts 2 Action默认是线程安全的。每个请求都会创建一个新的Action实例,这意味着单个Action实例不会被多个线程共享。
然而,需要注意的是,Action的非局部属性(如静态变量或全局变量)可能会引起并发问题。此外,开发者在实现Action时,可能会使用到这些共享资源,因此需要格外小心以避免潜在的并发问题。
开发者在设计Action时应该遵循良好的编程实践,如避免使用静态变量存储数据,使用线程安全的数据结构,或者在Action中实现适当的数据同步机制。
2.2 Struts 2 Result组件解析
2.2.1 Result类型与结果集的使用
在Struts 2框架中,Result负责将Action处理的结果反馈给客户端。当Action执行完毕并返回一个结果字符串(如"success")时,Struts 2框架将根据配置文件中的 <result>
标签来决定如何处理这个结果。
Result类型主要包括以下几种:
-
dispatcher
:默认结果类型,通常用于JSP页面的转发。 -
redirect
:用于页面重定向。 -
chain
:用于调用另一个Action。 -
stream
:将内容作为流直接发送到客户端。
以下是 dispatcher
类型的一个示例配置:
<result name="success" type="dispatcher">
/success.jsp
</result>
在这个例子中,当Action返回 success
时,结果会通过 dispatcher
类型转发到 /success.jsp
页面。
2.2.2 自定义Result类型实现细节
开发者可以创建自己的Result类型以满足特定需求。自定义Result类型需要实现 Result
接口,并提供相应的逻辑来处理Action的结果。
下面是一个简单的自定义Result类型示例:
public class CustomResult implements Result {
private String someParameter;
public void execute(ActionInvocation invocation) throws Exception {
// 获取ActionContext和相关配置
ActionContext context = invocation.getInvocationContext();
Map<String, Object> parameters = context.getParameters();
someParameter = (String) parameters.get("someParameter");
// 实现具体的处理逻辑,例如设置响应头信息
HttpServletResponse response = (HttpServletResponse) context.get(ServletActionContext.HTTP_RESPONSE);
response.setHeader("CustomHeader", someParameter);
}
}
在上面的示例中, CustomResult
类实现了 Result
接口的 execute
方法。当Action执行完成后,这个方法被调用,可以在其中添加自定义逻辑,比如修改HTTP响应头。
2.2.3 Result与Action的关系及应用案例
Result与Action之间是通过配置关联的。在 struts.xml
文件中,每个 <action>
标签可以配置多个 <result>
标签来定义不同的执行结果。每个结果都有一个名称,对应于Action中 execute()
方法返回的字符串。
应用案例:
假设有一个用户登录的Action,登录成功后应该展示主页,登录失败则重新显示登录页面。配置可能如下:
<action name="login" class="com.example.LoginAction">
<result name="success" type="dispatcher">/主页.jsp</result>
<result name="input" type="dispatcher">/登录.jsp</result>
<result name="error">/登录.jsp</result>
</action>
在这个例子中:
- 当
LoginAction
的execute()
方法返回"success"
时,用户会被转发到主页。 - 如果返回
"input"
,用户将被重定向回登录页面,通常是因为表单验证失败。 - 如果出现其他错误,则返回
"error"
,展示登录页面并提供错误信息。
2.2 Struts 2 Tiles插件概述
3.1.1 Tiles插件的功能与优势
Tiles插件是Struts 2框架的一部分,用于页面布局管理。它的主要功能是将整个网页分解为可重用的布局部分(称为Tiles),从而提高开发效率,增强页面的模块化和可维护性。
Tiles插件的优势主要包括:
- 重用性 :可以创建通用的页面布局部分,供整个应用或多个应用重用。
- 模块化 :页面可以分解为独立的小部件,每个小部件可以单独开发和维护。
- 灵活性 :通过配置而非编程实现布局的定义和修改。
- 易于扩展 :开发者可以轻松地添加新的Tiles定义,以便在多个页面间共享。
使用Tiles插件,可以有效地解决以下问题:
- 减少重复代码:避免在多个JSP页面中复制和粘贴相同的HTML代码。
- 保持一致性:确保整个应用或网站的布局和样式一致。
- 易于维护:当需要修改布局时,只需在一个地方进行更改。
3.1.2 配置与使用Tiles布局
为了使用Tiles插件,首先需要在 struts.xml
文件中配置 <constant>
标签来启用Tiles插件:
<struts>
<constant name="struts_tiles_enabled" value="true" />
<!-- 其他配置 -->
</struts>
接着,需要在 struts.xml
中定义一个特殊的Action,该Action用于加载Tiles的配置文件:
<action name="loadTiles" class="org.apache.struts2.views.ActionSupport">
<result name="success" type="tiles">/tiles.xml</result>
</action>
一旦配置完成,就可以在JSP页面中使用Tiles标签来构建布局了。例如,使用 <s:insert>
标签来引入一个Tile定义:
<s:insert template="/templates/mainLayout.jsp">
<s:param name="title">主页</s:param>
<s:param name="body">/home.jsp</s:param>
</s:insert>
上述代码片段将会把 mainLayout.jsp
作为基础布局,并传入名为 title
和 body
的参数。
3.2 Tiles插件的高级应用
3.2.1 动态页面布局技术
动态页面布局技术允许开发者在运行时根据用户的需要或系统规则动态地改变页面布局。Tiles插件支持动态布局,主要通过以下方法实现:
- Tile预设 :在Tiles配置文件中定义多个Tile预设,然后在页面中根据需要选择相应的预设。
- 条件渲染 :使用JSP标签(如
<s:if>
)来控制某些Tile部分是否渲染。
一个动态布局的Tiles配置示例:
<definition name="dynamicLayout" template="/templates/layout.jsp">
<put name="header" value="/fragments/header.jsp"/>
<put name="footer" value="/fragments/footer.jsp"/>
<put name="body" value="/fragments/body.jsp"/>
</definition>
开发者可以在JSP页面中使用 <s:if>
标签来动态地包含或排除某些Tile部分:
<s:if test="showHeader == true">
<s:insert template="/templates/header.jsp"/>
</s:if>
3.2.2 与Action集成实现动态页面
与Action集成是实现动态页面的重要步骤。开发者可以在Action中准备必要的数据和视图状态,然后将这些信息传递给Tiles布局。
下面是一个Action与Tiles布局集成的简单例子:
Action代码:
public class HomeAction extends ActionSupport {
private String title;
private String body;
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getBody() {
return body;
}
public void setBody(String body) {
this.body = body;
}
public String execute() {
setTitle("我的主页");
setBody("/homeContent.jsp");
return SUCCESS;
}
}
Tiles配置文件:
<tiles-definitions>
<definition name="home" template="/templates/homeLayout.jsp">
<put name="title" value="" />
<put name="body" value="" />
</definition>
</tiles-definitions>
JSP页面使用Tiles标签来组合这些元素:
<s:insert template="/templates/homeLayout.jsp">
<s:param name="title" value="%{title}"/>
<s:param name="body" value="%{body}"/>
</s:insert>
在这个集成方案中,Action准备了页面标题和内容,然后这些信息被传递到Tiles布局中,最终在用户的浏览器中渲染。
3.2 Tiles插件的高级应用案例
通过上述技术的综合运用,开发者可以实现复杂且高度动态的页面布局。下面是一个高级应用的案例,展示了如何使用Tiles插件来构建一个复杂的动态网站布局。
高级应用案例描述
在这个案例中,我们将创建一个电子商务网站,网站有一个公共的头部和尾部,而内容区域则根据用户的浏览和购物行为动态变化。
步骤一:定义基础布局
首先定义基础的页面布局,为头部、尾部和可替换的主体内容预留空间。
layout.jsp
:
<html>
<head>
<title>电子商务网站</title>
</head>
<body>
<div id="header">
<!-- 插入头部内容 -->
</div>
<div id="content">
<!-- 主体内容 -->
</div>
<div id="footer">
<!-- 插入尾部内容 -->
</div>
</body>
</html>
步骤二:创建Tiles定义
在 tiles.xml
文件中定义多个Tiles,每个Tile代表一个功能模块,例如产品列表、购物车、用户登录等。
tiles.xml
:
<tiles-definitions>
<definition name="productList" template="/fragments/productList.jsp">
<put-list name="products" value="/products" />
</definition>
<definition name="shoppingCart" template="/fragments/shoppingCart.jsp">
<put-list name="cartItems" value="/cartItems" />
</definition>
<!-- 更多Tiles定义 -->
</tiles-definitions>
步骤三:在JSP页面中组合Tiles
最后,在JSP页面中使用 <s:insert>
标签来组合不同的Tiles,根据用户的动态需要展示不同的内容。
index.jsp
:
<s:insert template="/layout.jsp">
<s:param name="header" value="/fragments/header.jsp"/>
<s:param name="content" value="/tiles/productList"/>
<s:param name="footer" value="/fragments/footer.jsp"/>
</s:insert>
在这个高级应用案例中,我们通过Tiles插件将页面分解成独立的部分,并且通过配置来动态组合这些部分,从而实现了高度动态化和灵活的页面布局。这不仅提升了代码的复用性,也使得页面的维护变得更加简单。
总结
Struts 2框架通过Action组件和Result组件提供了强大的Web应用开发能力。通过 Tiles 插件,开发者能够更容易地管理页面布局,实现页面的模块化和复用。Tiles 插件支持动态布局技术,允许在运行时根据需要选择不同的布局,这使得Web页面更加灵活和动态。通过将Tiles与Action集成,开发者可以在服务器端控制页面布局,从而实现复杂且动态的内容展示。以上详细介绍了 Tiles 插件的功能、配置和高级应用案例,展示了如何通过 Tiles 插件来构建可维护、灵活的Web页面。
3. 掌握Struts 2 Tiles插件
3.1 Struts 2 Tiles插件概述
3.1.1 Tiles插件的功能与优势
Struts 2 Tiles插件是一个灵活的模板系统,它允许开发人员重用和组织JSP页面的布局。通过使用Tiles,可以创建可配置的页面模板,从而实现页面布局的模块化。这种模块化有助于减少代码的重复并简化页面的维护工作。
Tiles的主要功能包括: - 布局模板 : 可以定义页面布局模板,并在多个页面上重用这些模板。 - 组件化 : 可以将页面分割成可重用的组件,例如页眉、页脚、导航栏等。 - 动态布局 : 可以根据不同的需求动态地改变页面的布局。
使用Tiles插件的优势显而易见: - 提高开发效率 : 通过减少重复代码,开发人员可以更快速地开发出一致的页面布局。 - 易于维护 : 页面布局和内容分离,使得后期维护更加方便,同时也便于进行设计更改。 - 支持模块化开发 : 可以更容易地遵循MVC架构,将视图层的代码进行模块化管理。
3.1.2 配置与使用Tiles布局
配置和使用Tiles插件可以分为以下几个步骤:
-
添加依赖 : 确保项目中已经包含了Tiles插件的库文件。
-
定义模板 : 创建JSP文件作为页面布局模板,使用Tiles标签来定义各个区域。
-
配置Tiles : 在Struts 2的配置文件(通常是
struts.xml
)中配置Tiles的定义。 -
使用模板 : 在需要使用模板的页面上,引用配置好的模板,将具体的内容填充到模板中定义的区域。
下面是一个简单的Tiles布局示例配置:
<tiles-defs>
<definition name="baseLayout" template="/WEB-INF/layouts/base.jsp">
<put-attribute name="header" value="/WEB-INF/layouts/header.jsp" />
<put-attribute name="body" value="/WEB-INF/layouts/body.jsp" />
<put-attribute name="footer" value="/WEB-INF/layouts/footer.jsp" />
</definition>
</tiles-defs>
通过上述配置,定义了一个名为 baseLayout
的模板,包含了三个区域:头部(header)、主体(body)和底部(footer)。在具体的页面上,可以通过引用 baseLayout
来使用这个布局。
3.1.3 Tiles插件的高级应用
动态页面布局技术
动态页面布局技术是指在运行时根据用户需求或系统状态改变页面布局。在Tiles中实现动态布局通常涉及条件判断或动作执行,根据这些条件来决定渲染哪个模板或哪个部分的内容。
举例来说,可以使用Tiles的 <insert>
标签嵌入动态内容:
<insert page="usermenu.jsp" flush="true" if="requestScope.user != null"/>
上面的代码片段表示如果 requestScope.user
不为空,则将 usermenu.jsp
页面内容插入到当前位置。
与Action集成实现动态页面
在Struts 2中,可以通过Action的结果来控制Tiles布局。Action可以返回不同的结果字符串,这些字符串与 struts.xml
中的 <result>
标签相匹配,进而控制页面的渲染。
一个集成示例如下:
public class MyAction extends ActionSupport {
// ...
public String execute() {
// ...
if (someCondition) {
return SUCCESS; // 使用默认布局
} else {
return SUCCESS_WITH_DYNAMIC_LAYOUT; // 使用动态布局
}
}
}
在 struts.xml
中配置结果字符串:
<action name="myAction" class="com.example.MyAction">
<result name="success">/WEB-INF/layouts/base.jsp</result>
<result name="success_with_dynamic_layout" type="tiles">baseLayout</result>
</action>
在上述配置中,根据 MyAction
返回的字符串,可能会渲染不同的布局模板。
3.2 Tiles插件的高级应用
3.2.1 动态页面布局技术
动态页面布局技术使得页面布局可以根据用户的权限、设备类型或会话状态等条件动态变化。Tiles插件通过其XML配置文件允许开发者设计灵活的模板系统。
在实际应用中,可以利用Tiles提供的 <insert>
标签和 <set>
标签来实现动态布局。通过这些标签,可以在页面的执行时动态插入内容或设置属性值。例如,可以设计一个基础布局模板,并使用 <set>
标签动态地修改特定内容块:
<tiles:insert template="baseLayout.jsp">
<tiles:put name="header" value="/WEB-INF/layouts/loginHeader.jsp" />
</tiles:insert>
在上述示例中, baseLayout.jsp
是一个基础模板,我们重写了 header
区域,以适应登录页面的特定需求。
3.2.2 与Action集成实现动态页面
在Struts 2框架中,结合Tiles插件,可以设计出高度动态化的页面。Action作为MVC架构中的C(Controller),可以影响视图层的显示。通过Action传递参数给Tiles模板,可以根据业务逻辑动态改变页面布局。
例如,在用户登录后,我们可能需要根据用户的角色来显示不同的菜单。在Action中,可以设置相应的属性值:
public class LoginAction extends ActionSupport {
private String userRole;
public String execute() {
// ...
if ("admin".equals(userRole)) {
setUserRole("ADMIN_ROLE");
} else {
setUserRole("USER_ROLE");
}
return SUCCESS;
}
// getters and setters
}
在 struts.xml
文件中,可以利用Struts 2的逻辑表达式来控制视图的选择:
<action name="login" class="com.example.LoginAction">
<result name="success" type="tiles">
<param name="definition">userRole=${userRole}</param>
</result>
</action>
这里, definition
属性的值会根据 ${userRole}
的值动态改变,从而渲染不同的模板。
通过这种集成方式,可以实现以下高级应用: - 条件性视图渲染 :根据不同条件显示不同的页面内容或布局。 - 个性化用户界面 :根据用户特征显示个性化界面。 - 多语言支持 :根据用户的语言偏好显示相应语言的界面。
最终,结合Tiles插件的高级特性,可以创建出既灵活又强大的动态Web应用程序。
4. Struts 2 Plug-in架构剖析
4.1 Plug-in的基本概念与架构
4.1.1 Plug-in的定义与生命周期
Struts 2 Plug-in是一种特殊的组件,可以增强或扩展Struts 2框架的功能。Plug-in本质上是一个实现了特定接口的Java类,并且它的生命周期由Struts 2框架管理。它的核心职责是在Struts 2应用启动和停止时进行一些初始化和清理工作。
Plug-in在Struts 2应用生命周期的不同阶段扮演着关键角色。当Struts 2初始化时,它会扫描所有的Plug-in并按顺序进行初始化。同样,当应用关闭时,Plug-in会被清理和销毁。
4.1.2 预定义的Plug-in功能解析
Struts 2框架提供了一些预定义的Plug-in,它们负责处理一些框架的核心任务。例如, i18n
Plug-in负责国际化支持, params
Plug-in负责处理HTTP请求参数。
通过分析这些预定义Plug-in的源代码,开发者可以了解如何实现自己的Plug-in。通常,开发者需要关注Plug-in接口的 init
方法和 destroy
方法。 init
方法在Plug-in实例被创建并且框架配置文件(struts.xml)被加载后调用;而 destroy
方法在应用关闭时调用。
4.2 创建与管理自定义Plug-in
4.2.1 设计自己的Plug-in步骤
要设计自己的Plug-in,你需要遵循以下步骤:
- 创建一个新的Java类,并实现
org.apache.struts2.StrutsPlugin
接口。这个类将包含Plug-in的所有核心逻辑。 - 实现
init
方法,用于初始化Plug-in。在这个方法中,可以进行资源加载、创建服务等。 - 实现
destroy
方法,用于清理Plug-in。在这个方法中,应该释放init
方法中获取的所有资源。 - 在
struts.xml
文件中注册你的Plug-in,通过<constant>
标签配置Plug-in的属性。 - (可选)实现
start
和stop
方法,这些方法可以在应用启动和停止时进行更多的自定义处理。
4.2.2 Plug-in配置与扩展点实践
在自定义Plug-in中,可以利用Struts 2提供的扩展点来增强功能。一个扩展点是Struts 2框架的一个钩子(hook),它允许开发者在框架处理流程中的某些特定时刻介入。
例如,如果你想在每个请求处理之前执行一些操作,可以实现 RequestEventListener
接口。然后在你的Plug-in的 init
方法中注册这个监听器。以下是一个代码示例:
public class MyPlugin implements StrutsPlugin {
@Override
public void init(final Plugin plugin) {
// 注册请求监听器
plugin.getRequestListeners().add(new RequestListener() {
@Override
public void beforeRequest(final ActionContext context, final String行动计划) {
// 在请求处理前执行的逻辑
}
});
}
// 其他方法...
}
在上面的代码中,我们创建了一个 RequestListener
并将其添加到Plug-in中,该监听器将在每个请求到达之前被调用。你可以在这个监听器中加入任何你希望在请求处理前执行的逻辑。
通过Plug-in架构,开发者可以有效地对Struts 2框架进行模块化扩展,实现特定业务需求或集成第三方库。这种架构上的灵活性是Struts 2框架的一大优势,让开发者可以更加专注于业务逻辑的开发,而框架层面的通用问题则可以通过Plug-in来解决。
5. Struts 2表达式语言与国际化
5.1 Struts 2的表达式语言OGNL
OGNL的语法与功能
Object-Graph Navigation Language(OGNL)是Struts 2框架中使用的表达式语言,它提供了一种在Java应用程序中访问和操作对象的方法。OGNL的语法类似于其他表达式语言如XPath和XQuery。它支持运算符、方法调用、属性访问以及集合操作等,使得在页面标签或拦截器中通过简单的表达式访问复杂的对象图成为可能。
OGNL表达式的根对象是ValueStack,从这个栈上可以访问到所有的请求参数、ActionContext中的数据以及Action本身。OGNL表达式在Struts 2中的应用广泛,包括在JSP页面标签中显示数据、在拦截器中操作对象以及在配置文件中引用动态值等。
OGNL在Struts 2中的应用
在Struts 2中,OGNL作为默认的表达式语言,被广泛应用于数据传递和视图与控制器之间的通信。例如,OGNL可用于在JSP页面中显示用户信息:
<s:text name="user.name" />
这段代码中, <s:text>
标签使用OGNL表达式访问名为 user.name
的值。OGNL不仅限于简单数据的获取,还可以处理复杂的逻辑。例如,在JSP页面中,可以利用OGNL进行数据格式化:
<s:text name="user.dob" format="%date{yyyy-MM-dd}"/>
这段代码使用OGNL表达式调用 format
方法将日期对象格式化为字符串。OGNL还支持集合过滤和映射:
<s:iterator value="user.books" status="status">
<s:property value="title"/>
<s:if test="status.index % 2 == 0">Even</s:if>
</s:iterator>
在这个例子中, <s:iterator>
标签用于迭代 user.books
集合,并显示每个书的标题。 <s:if>
标签通过OGNL表达式判断当前的迭代索引是否为偶数,并输出相应的文本。
5.2 Struts 2的国际化支持
国际化的原理与实现
国际化(i18n)是软件开发中一个重要的功能,它允许应用程序根据用户的语言和区域设置显示相应语言的资源。在Struts 2中,国际化主要通过资源文件实现,这些资源文件包含了不同语言的键值对。当请求到达服务器时,Struts 2会根据用户的语言偏好从相应的资源文件中加载字符串,然后将它们插入到视图中。
要实现国际化,开发者需要创建多个资源文件,例如 ApplicationResources_en_US.properties
用于美国英语, ApplicationResources_cn.properties
用于简体中文等。这些文件应该包含键值对,其中键是相同的,而值是对应语言的翻译。
# ApplicationResources_en_US.properties
welcome.message = Welcome to our application!
# ApplicationResources_cn.properties
welcome.message = 欢迎来到我们的应用程序!
Struts 2会根据浏览器的语言设置自动选择合适的资源文件。如果匹配的资源文件不存在,它会回退到默认的资源文件。开发者可以使用 <s:text>
标签来引用这些资源文件中的字符串。
实战多语言支持配置与示例
要启用Struts 2的国际化支持,首先需要在 struts.xml
配置文件中指定资源包,然后在JSP页面中使用资源键来引用翻译后的字符串。
<struts>
<constant name="struts.custom.i18n.resources" value="ApplicationResources" />
<!-- 其他配置 -->
</struts>
在这个配置中, struts.custom.i18n.resources
常量告诉Struts 2框架在哪里查找资源文件。开发者可以为每种语言创建一个资源文件,并遵循相同的命名规则,如 ApplicationResources_de.properties
用于德语。
在JSP页面中,开发者可以使用 <s:text>
标签来显示翻译后的字符串,如之前提到的示例。此外,还可以使用 <s:i18n>
标签动态更改当前线程的语言设置:
<s:i18n name="ApplicationResources">
<s:text name="welcome.message" />
</s:i18n>
这段代码会根据当前用户的语言设置显示相应的欢迎信息。如果需要在代码中更改语言设置,可以使用 ActionContext
:
ActionContext.getContext().put("request.locale", new Locale("zh", "CN"));
这段代码会将当前用户的语言设置更改为简体中文。当页面重新渲染时,Struts 2将使用 ApplicationResources_cn.properties
中的翻译内容。
开发者还可以通过配置HTTP拦截器 i18n
来实现更复杂的国际化支持,例如,根据URL参数动态更改语言设置。这样,开发者可以根据用户的偏好和需求灵活地提供多语言支持,提升用户体验。
通过上述章节的介绍,我们可以看到OGNL和国际化在Struts 2中的强大应用和灵活性。OGNL作为一种功能强大的表达式语言,在视图层和控制器层之间搭起了一座桥梁,使得数据处理和传递变得更为简洁和高效。同时,Struts 2的国际化支持则确保了应用程序能够满足全球化市场的需求,提供多语言界面,增强用户体验和应用程序的可访问性。
6. 深入Struts 2验证框架与核心控制器
6.1 Struts 2验证框架详解
6.1.1 验证框架的原理与配置
Struts 2 验证框架的原理基于拦截器(Interceptors)机制,它允许开发者在Action执行之前或之后进行预处理或后处理。验证拦截器是在处理用户请求前检查表单输入数据的有效性的重要环节。
为了启用验证框架,你需要在Struts 2的配置文件(struts.xml)中添加对 validation
和 workflow
拦截器的引用:
<package name="default" extends="struts-default" namespace="/">
<action name="exampleAction" class="com.example.ExampleAction">
<interceptor-ref name="defaultStack"/>
<interceptor-ref name="validation">
<param name="excludeMethods">input,back,cancel</param>
</interceptor-ref>
<result name="success">/success.jsp</result>
<result name="input">/input.jsp</result>
</action>
</package>
在这个配置中, defaultStack
拦截器包含了 validation
拦截器, excludeMethods
允许你指定不进行验证的方法。
6.1.2 实现自定义验证器的方法
Struts 2 自带了许多常用的验证器,但有时你需要实现自定义验证器来处理特定的验证逻辑。自定义验证器实现起来很简单,按照以下步骤进行:
- 创建一个类并实现
ValidationMethod
接口。 - 实现
validate
方法,其中包含你的验证逻辑。 - 在验证方法中,使用
ValidationContext
来获取和设置错误消息。
例如,创建一个验证电子邮件格式的自定义验证器:
public class EmailValidator implements ValidationMethod {
public void validate(Object object, ValidationContext context) {
String email = (String) context.get("email");
if (email == null || !email.matches(".+@.+\\..+")) {
context.addMessage("email", "Invalid email address.");
}
}
}
在Struts 2的配置文件中指定使用自定义验证器:
<validators>
<validator type="com.example.EmailValidator">
<param name="email">email</param>
</validator>
</validators>
6.1.3 常见验证场景与解决方案
- 必填字段验证 :使用
required
验证器检查字段是否为空。 - 字符串长度验证 :
string-length
验证器检查输入字符串的长度是否符合指定范围。 - 数字范围验证 :
int
、double
等验证器可以检查数字值是否在指定的范围内。 - 正则表达式验证 :
expression
验证器利用正则表达式进行复杂的格式验证。
<validators>
<validator type="required">
<param name="field">username</param>
</validator>
<validator type="string-length">
<param name="field">password</param>
<param name="min">6</param>
<param name="max">10</param>
</validator>
</validators>
这些验证场景涵盖了大多数常见的需求,并且Struts 2的验证框架提供了足够的灵活性来满足更复杂的情况。
6.2 Struts 2核心控制器FilterDispatcher
6.2.1 FilterDispatcher的工作机制
Struts 2框架中的 FilterDispatcher
是核心控制器,负责接收所有来自客户端的请求,并将它们转发到相应的Action。
- 请求分发过程 :当一个HTTP请求到达时,
FilterDispatcher
会根据请求中的信息确定哪个Action应该处理该请求。 - 处理流程 :然后
FilterDispatcher
会创建一个Action实例,调用它的execute
方法,并将请求和响应对象作为参数传递给该方法。 - 生命周期 :请求处理完毕后,Action的生命周期结束,结果返回给客户端。
6.2.2 FilterDispatcher与请求处理流程
在Struts 2中,FilterDispatcher与请求处理流程紧密集成,其流程包括:
- 拦截HTTP请求。
- 解析URL,识别目标Action。
- 创建Action实例。
- 创建值栈(Value Stack),并将请求参数放入值栈。
- 调用Action的
execute
方法。 - 根据返回的结果,选择相应的结果页面。
- 渲染结果页面并响应客户端。
FilterDispatcher确保了请求的正确解析与分发,并且在整个请求处理周期中起到了重要的作用。
6.3 Struts 2关键库分析
6.3.1 javassist-3.7.ga.jar库的作用
javassist
是一个处理Java字节码的类库,它可以用来动态编辑类文件。在Struts 2中,它被用于动态创建字节码,从而支持一些特性,如动态类型转换和拦截器的动态生成。
6.3.2 commons-io-1.3.2.jar库的使用技巧
commons-io
库提供了许多用于处理文件和数据流的工具类。在Struts 2应用中,你可以用它来处理文件上传和下载的I/O操作,以及实现更复杂的文件处理逻辑。
6.3.3 关键库在Struts 2中的实际应用案例
让我们以一个文件上传功能为例,说明 commons-io
库的使用:
public class FileUploadAction extends ActionSupport {
private File file;
private String fileName;
public String execute() {
// 使用commons-io库的FileUtils.copyFile方法保存文件
try {
FileUtils.copyFile(file, new File(uploadLocation, fileName));
return SUCCESS;
} catch (IOException e) {
e.printStackTrace();
return INPUT;
}
}
}
在配置文件中,你需要定义一个拦截器来处理文件上传:
<action name="upload" class="com.example.FileUploadAction">
<interceptor-ref name="fileUpload">
<param name="maximumSize">10240</param>
<param name="allowedTypes">image/jpeg,image/png</param>
</interceptor-ref>
<result name="success">/upload_success.jsp</result>
</action>
javassist
和 commons-io
是Struts 2背后的关键库,它们提供了框架扩展性和应用功能的重要支持。通过上述案例,你可以看到关键库在实际开发中是如何发挥作用的。
简介:Struts 2是Apache软件基金会的Java Web应用框架,基于MVC设计模式,为开发者提供强大的功能和灵活的架构。Struts 2的改进版本继承了Struts 1的许多优点,并加入了新特性。通过分析Struts 2.2.1版本中的关键组件,如javassist和commons-io,可以理解其内部工作原理和核心特性,包括Action与Result的处理、Tiles插件的布局管理、插件架构的扩展性、OGNL表达式语言、国际化支持、数据验证框架以及核心控制器FilterDispatcher。尽管Struts 2.2.1版本已较为陈旧,但对其的研究有助于更好地把握现代Web开发框架。