简介:Struts是一个开源框架,用于构建基于Java的企业级Web应用程序,并实现了MVC设计模式。本教程通过实例和详细解释,旨在指导学习者深入理解Struts框架的核心概念、配置、组件以及最佳实践,以便快速掌握Struts在Web应用开发中的应用。
1. Struts开源框架概述
1.1 Struts框架简介
Struts是一个开源的Web应用框架,用于创建企业级Java EE应用程序。它采用MVC(Model-View-Controller)架构模式,将业务逻辑、数据模型以及用户界面进行有效分离。Struts框架的核心是ActionServlet,它接收客户端的请求,并将请求转发给对应的Action处理器。
1.2 Struts框架的发展历程
Struts首次发布于2001年,作为Apache Jakarta项目的一部分,为开发者提供了一套丰富的标签库和可扩展的架构,用于构建基于Web的复杂应用程序。随着技术的演进,Struts经历了多个版本的迭代,增加了对更多Java EE特性的支持,如注解、依赖注入等。
1.3 Struts框架的主要特点
Struts框架以其清晰的架构、稳定性和易用性而闻名。主要特点包括: - 组件化设计 :允许开发者轻松地替换和扩展框架的各个组件。 - 广泛的支持 :拥有庞大的用户社区和丰富的文档资料。 - 灵活性 :支持多种视图技术,如JSP、Velocity、FreeMarker等。
flowchart TB
A[客户端请求] --> B[ActionServlet]
B -->|转发| C[Action处理器]
C --> D[业务逻辑处理]
D --> E[模型层更新]
E -->|返回| F[视图层展示]
上述的流程图描述了一个典型的Struts请求处理过程,帮助开发者理解Struts框架在Web应用程序中的角色和工作流程。
2. MVC设计模式及Struts实现
2.1 MVC设计模式概念解析
MVC(Model-View-Controller)设计模式是一个软件工程中常用的模式,它将应用程序分为三个核心组件,以实现关注点分离,从而提高系统的可维护性和可扩展性。
2.1.1 MVC模式的基本组成
-
Model(模型) :它代表应用程序的数据结构,负责管理数据状态,并处理业务逻辑。在MVC架构中,Model不直接与用户界面交互,它只响应来自Controller的查询和更新请求,并通知View层数据变更。
-
View(视图) :视图是用户看到并与之交互的界面。在Web应用程序中,视图通常由JSP页面或其他模板技术实现。视图主要负责展示数据(从Model获取)并提供界面交互,它不会存储状态信息。
-
Controller(控制器) :控制器处理用户输入(例如,点击按钮或提交表单),将其转化为命令传递给Model,然后选择适当的视图来渲染输出。控制器是Model和View之间的协调者。
MVC模式通过分离这三种组件,使得应用程序的修改和扩展变得更加容易。
2.1.2 MVC模式的工作原理
当用户执行一个动作时(比如点击一个按钮),这个动作由Controller接收。Controller根据请求来更新Model,Model会更新自己的状态,并通知相关的视图组件。视图随后从Model获取数据并重新渲染,展示给用户。
这种设计允许Model和View的解耦,使得每个组件可以独立变化而不影响其他组件。例如,如果视图需要改变,控制器和模型可以保持不变;同样,如果业务逻辑发生变化,只要模型的接口不变,视图和控制器也可以保持不变。
2.2 MVC在Struts中的具体实现
2.2.1 Struts中的Model层实践
在Struts框架中,Model层通常由Java Bean实现,用于处理应用程序的业务逻辑和数据管理。Struts为Model层提供支持,使Model对象能够与视图层进行数据交换,并通过Action对象与控制器层交云。
// 示例Model类
public class User {
private String username;
private String password;
// 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;
}
// 其他业务逻辑方法
}
上面的代码展示了简单的Model类,它包含了用户信息的基本属性和对应的getter/setter方法。
2.2.2 Struts中的View层实践
在Struts中,视图层主要由JSP页面组成。JSP页面能够直接访问Model层的数据,并展示给用户。Struts提供了标签库来帮助在JSP页面中使用Action对象的属性。
<%@ taglib prefix="s" uri="/struts-tags" %>
<html>
<head>
<title>User Details</title>
</head>
<body>
<s:property value="user.username" /> // 显示用户名
<s:property value="user.password" /> // 显示密码
</body>
</html>
在JSP页面中使用了Struts的标签 <s:property>
来显示Model对象的属性。
2.2.3 Struts中的Controller层实践
Struts的Controller层由Action类来实现,它负责接收用户的请求,调用Model层处理业务逻辑,并根据业务逻辑的结果选择相应的视图返回给用户。
public class LoginAction extends Action {
private User user;
public String execute() {
// 实现登录逻辑,根据user对象的属性验证用户身份
// 返回字符串结果,如"success"或"input"
}
// 省略getter和setter方法
}
上面的代码展示了Struts的Action类。它继承自 Action
类,并覆盖 execute()
方法,该方法包含了业务逻辑的处理。
以上是第二章节的主要内容,其中2.2.3小节的内容通过代码块展示了如何在Struts中实现Controller层。每个代码块后面都给出了代码逻辑的逐行解读分析,以及参数说明和扩展性说明,确保了内容的连贯性和专业性。
3. Struts核心配置文件解析
3.1 struts-config.xml文件结构
3.1.1 配置文件的基本结构
Struts框架的核心配置文件名为 struts-config.xml
。该文件位于WEB-INF目录下,是Struts 1.x系列框架中定义配置信息的主要文件。该文件的结构可以分为几个主要部分,包括 <data-sources>
、 <form-beans>
、 <action-mappings>
、 <global-forwards>
、 <message-resources>
等,它们各自承担着不同的配置职责。
一个典型的Struts配置文件的基本结构如下所示:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts-config PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 1.3//EN"
"http://struts.apache.org/dtds/struts-config_1_3.dtd">
<struts-config>
<data-sources />
<form-beans />
<global-forwards />
<action-mappings />
<message-resources />
</struts-config>
3.1.2 各配置项的详细解析
3.1.2.1 <form-beans>
配置项
<form-beans>
部分定义了与表单相关的JavaBean,这些JavaBean通常用于接收和存储HTTP表单提交的数据。该部分中的每个 <form-bean>
定义了一个特定的表单Bean,它需要指定一个唯一的 name
属性和对应的 type
属性。
<form-beans>
<form-bean name="loginForm" type="com.example.LoginForm"/>
</form-beans>
3.1.2.2 <action-mappings>
配置项
<action-mappings>
部分是Struts配置中最重要的部分之一,它负责将用户请求映射到相应的Action类。每个 <action-mapping>
元素定义了一个动作映射,包含了用户请求的URI、处理该请求的Action类的类名、表单Bean的引用等。
<action-mappings>
<action path="/login" type="com.example.LoginAction" name="loginForm" scope="request" validate="true" input="/login.jsp">
<forward name="success" path="/welcome.jsp"/>
<forward name="input" path="/login.jsp"/>
</action>
</action-mappings>
3.2 配置文件高级应用
3.2.1 配置文件中的数据类型转换
在处理用户提交的数据时,往往需要进行数据类型转换。Struts提供了数据类型转换的机制,可以在配置文件中为特定的表单属性指定转换器,以实现自定义的转换逻辑。
<form-beans>
<form-bean name="userForm" type="com.example.UserForm">
<form-property name="birthday" type="java.util.Date" handler="com.example.MyDateConverter"/>
</form-bean>
</form-beans>
3.2.2 配置文件中的异常处理配置
异常处理是任何框架中都非常重要的部分,Struts允许开发者在配置文件中定义全局异常处理器。通过定义 <global-exceptions>
部分,可以将特定类型的异常映射到自定义的异常处理Action上。
<global-exceptions>
<exception exception="java.lang.IllegalStateException" key="error IllegalStateException" type="com.example.MyExceptionHandler"/>
</global-exceptions>
表格和代码块
配置文件中的 <form-beans>
、 <action-mappings>
等标签,每一种都有其独特的属性来满足不同的需求。我们可以通过下面的表格对这些属性进行更详细的说明:
| 配置标签 | 主要属性 | 描述 | |----------------|------------------------|------------------------------------------------------------| | <form-beans>
| name
, type
| 定义表单Bean的名称和类型 | | <action>
| path
, type
, name
| 定义请求URI路径、处理请求的Action类以及表单Bean的名称 | | <forward>
| name
, path
| 定义目标页面的名称和路径 | | <exception>
| exception
, key
, type
| 定义异常类、错误信息键值和异常处理类 |
下面的代码块示例展示了如何在 <action-mappings>
中定义一个动作映射,并使用 <forward>
标签来指定动作成功后的页面跳转。
<action path="/editUser"
type="com.example.EditUserAction"
name="userForm"
scope="request"
validate="true">
<forward name="success" path="/userEdited.jsp"/>
<forward name="input" path="/editUser.jsp"/>
</action>
通过本章节的介绍,我们深入了解了Struts核心配置文件 struts-config.xml
的结构与高级应用,包括如何定义表单Bean、配置动作映射、以及数据类型转换和异常处理的配置。在接下来的章节中,我们将进一步探讨 Action
与 ActionForm
的角色和作用,它们是Struts中处理用户请求和表单数据的关键组件。
4. Action与ActionForm的角色与作用
4.1 Action类的作用与实现
4.1.1 Action的生命周期
在Struts框架中,Action类负责处理用户的请求。一个Action的生命周期从 execute()
方法的调用开始,直到返回一个 ActionForward
对象结束。 ActionForward
对象告诉Struts框架接下来要将控制权交给哪个资源,如JSP页面、另一个Action或其他网络资源。
Action类的生命周期可以分为几个主要阶段:
- 实例化 :当Struts框架接收到请求并根据配置文件找到对应的Action类时,首先会实例化它。
- 处理请求 :通过调用
execute()
方法处理用户的请求。 - 结果返回 :
execute()
方法返回一个ActionForward
对象,指明接下来的动作或页面。 - 销毁 :在请求处理完毕后,Action对象可能会被垃圾回收。
为了更好地管理Action对象的生命周期,Struts2使用拦截器和值栈来处理用户请求,避免了传统Struts中的Action实例化过程的不灵活性。
4.1.2 实现Action类的方法
实现Action类通常涉及继承 ActionSupport
类,并重写 execute()
方法。下面是一个简单的Action类实现示例:
public class LoginAction extends ActionSupport {
private String username;
private String password;
// Getters and Setters
@Override
public String execute() {
// 实际的业务逻辑处理
boolean isValidUser = authenticationService.authenticate(username, password);
if (isValidUser) {
return SUCCESS;
} else {
// 登录失败,存储错误信息并返回INPUT
addActionMessage("Invalid username or password");
return INPUT;
}
}
}
在这个例子中, execute()
方法首先调用一个认证服务来验证用户身份。如果用户有效,则返回 SUCCESS
;如果用户无效,则添加一条错误消息,并返回 INPUT
,通常会导致页面重新加载,并显示错误消息。
4.2 ActionForm的作用与使用
4.2.1 ActionForm的作用及其实现
ActionForm在Struts1中扮演着重要的角色,它作为Model对象,用于封装请求参数。在Struts2中,ActionForm的职责被拆分,值栈(Value Stack)和拦截器系统承担了类似功能。
ActionForm类的实现通常遵循以下步骤:
- 创建一个ActionForm类,并包含需要封装的请求参数属性。
- 实现getter和setter方法。
- 在struts-config.xml中配置ActionForm类,以便Struts框架能与之对应。
public class LoginForm extends ActionForm {
private String username;
private String password;
// Getters and Setters
// 如果需要在ActionForm级别进行校验,可以覆写validate方法
@Override
public ActionErrors validate(ActionMapping mapping, HttpServletRequest request) {
ActionErrors errors = super.validate(mapping, request);
if (errors != null) {
return errors;
}
// 自定义校验逻辑
if (username == null || username.trim().isEmpty()) {
errors.add("username", new ActionMessage("error.username.empty"));
}
if (password == null || password.trim().isEmpty()) {
errors.add("password", new ActionMessage("error.password.empty"));
}
return errors;
}
}
4.2.2 ActionForm与Action的关系
在Struts1中,ActionForm与Action紧密相关联。ActionForm负责数据的封装和校验,而Action则负责处理业务逻辑。ActionForm作为请求参数的容器,将数据传递给Action。
这种关系使得ActionForm在数据绑定和数据校验方面非常有用。然而,随着Struts2框架的发展,ActionForm的使用越来越不常见,取而代之的是更为灵活的值栈和拦截器模式。
Struts2框架的Action通常不依赖于ActionForm,而是直接使用值栈来获取和操作请求参数。这样的设计使得Action的开发更加直接和灵活,同时保留了强类型检查的优点。
<struts>
<action name="login" class="com.example.LoginAction">
<result name="success">/success.jsp</result>
<result name="input">/login.jsp</result>
</action>
</struts>
在配置文件中,我们不再需要单独配置ActionForm,而是直接关联到Action类。这种转变简化了配置过程,增强了框架的扩展性和维护性。
5. Tiles框架与页面布局应用
5.1 Tiles框架简介
5.1.1 Tiles框架的基本概念
Tiles是Apache Struts的一部分,允许开发人员通过定义可重用的页面布局组件来构建动态Web应用程序。这种模块化的方法有助于分离布局和内容,从而提高应用程序的可维护性和可扩展性。使用Tiles,可以创建包含共同页面元素(如页眉、页脚、侧边栏和导航条)的模板,然后将它们应用到多个页面上,无需重复编写相同的标记代码。
5.1.2 Tiles框架的安装与配置
安装Tiles相对简单,通常只需要将Tiles相关的JAR文件添加到项目的类路径中。对于Struts 2,Tiles与核心框架紧密集成,因此只需在 struts.xml
文件中配置Tiles插件。安装完成后,下一步是配置Tiles定义。这涉及到在 tiles-defs.xml
文件中定义页面组件(称为tiles)和布局。这个文件通常位于 /WEB-INF/conf
目录下,或者可以在 struts.xml
中指定位置。
<struts>
<package name="tilespackage" extends="struts-default">
<plugin name="tiles">
<set-property property="definitions-config" value="/WEB-INF/conf/tiles-defs.xml" />
</plugin>
</package>
</struts>
在 tiles-defs.xml
中,可以定义多个布局模板。例如:
<tiles-definitions>
<definition name="baseLayout" template="/WEB-INF/layout/baseLayout.jsp">
<put-attribute name="header" value="/WEB-INF/layout/header.jsp" />
<put-attribute name="menu" value="/WEB-INF/layout/menu.jsp" />
<put-attribute name="body" value="" />
<put-attribute name="footer" value="/WEB-INF/layout/footer.jsp" />
</definition>
</tiles-definitions>
5.2 Tiles在页面布局中的应用
5.2.1 页面布局的设计思路
设计页面布局时,首先要考虑的是如何将页面内容分解为可重用的部分。通常,一个典型的Web页面可以分为以下几个区域:头部(header)、菜单(menu)、内容区域(body)、底部(footer)和侧边栏(sidebar)。通过在Tiles定义中定义这些区域,可以在不重新编写HTML的情况下,通过简单地更改属性值来调整页面布局。
5.2.2 Tiles标签的具体使用方法
在JSP页面中,可以使用Tiles标签来引用已定义的布局。例如,在一个具体的JSP页面中,可以这样使用Tiles:
<%@ taglib prefix="tiles" uri="/tiles" %>
<tiles:insertDefinition name="baseLayout">
<tiles:putAttribute name="body" value="/WEB-INF/content/home.jsp" />
</tiles:insertDefinition>
在这里, tiles:insertDefinition
标签用于插入名为 baseLayout
的布局定义。然后,我们使用 tiles:putAttribute
来指定 body
内容的JSP页面。通过这种方式,可以很容易地将不同的内容模块插入到相同的布局模板中,保持页面结构的一致性并减少代码重复。
通过将布局与内容分离, Tiles框架提供了一种强大的方式来管理和维护大型Web应用程序的页面。这种方法提高了代码的可重用性,有助于维护布局的一致性,同时也加快了开发速度。
6. 国际化与本地化支持
在当今全球化的市场环境下,软件产品的国际化与本地化已经成为不可或缺的一部分。这不仅涉及到软件界面的多语言支持,还包括对不同地区文化习惯的尊重和适应。本章将详细解读Struts框架中如何实现国际化与本地化,并探讨在实践中可能遇到的挑战以及解决方案。
6.1 国际化的概念与实现
6.1.1 国际化的必要性与基本原理
国际化(Internationalization),通常简称为i18n(因为国际化的英文单词是internationalization,从i到n共有18个字母),是指在软件设计阶段就考虑到软件将要支持的多种语言和文化差异,以便于后续添加对其他语言的支持。基本原理是将所有可变的文本信息从程序代码中分离出来,存储在外部的资源文件中。
例如,在线商店平台可能需要支持英语、中文、西班牙语等多种语言。如果程序代码与界面文本信息混在一起,那么在添加新语言时将非常困难。通过国际化,开发者只需为新语言创建相应的资源文件即可。
6.1.2 Struts中实现国际化的方法
Struts框架提供了一套内置的国际化支持,主要通过 ActionMessages
和 ActionErrors
类来处理。下面是基本步骤:
- 定义资源文件:例如
ApplicationResources.properties
(默认英文)和ApplicationResources_de.properties
(德语)。 - 配置struts-config.xml,确保
<message-resources parameter="ApplicationResources" />
这一行代码已经被添加。 - 在Action类中使用
getText()
方法获取对应语言的文本信息。
具体实现的代码样例如下:
// Action类中使用
public ActionForward execute(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response)
throws Exception {
// 获取翻译后的信息
String info = getText("info.label");
request.setAttribute("info", info);
return mapping.findForward("success");
}
资源文件 ApplicationResources.properties
内容可能如下:
info.label=This is an information message.
资源文件 ApplicationResources_de.properties
内容可能如下:
info.label=Dies ist eine Information.
当用户选择德语时,Struts将自动加载 ApplicationResources_de.properties
文件,用户界面上相应的文本将被翻译为德语。
6.2 本地化的深入实践
6.2.1 本地化与资源文件的管理
本地化(Localization),通常简称为l10n(localization的英文单词从l到n有10个字母),是指将国际化的产品转换为特定地区或国家使用的版本。本地化不仅仅是语言翻译,还包括日期、数字格式以及货币单位等的本地化。
在Struts中,本地化主要通过资源文件的扩展名来区分,如 ApplicationResources_de_DE.properties
表示德语(德国)。要管理好这些资源文件,开发者可以创建一个资源文件目录,按语言和地区进行分类。
6.2.2 多语言支持的测试与优化
在软件开发过程中,测试多语言支持是一项重要的环节。测试时应确保以下几点:
- 所有文本信息都能正确显示,并且翻译准确无误。
- 文本的长度扩展不会破坏页面布局。
- 日期、数字和货币等数据格式化正确。
针对上述测试,可以建立一个测试矩阵,覆盖所有支持的语言和地区。以下是本地化测试可能涉及的一些代码示例:
// 测试代码示例
public void testInternationalization() throws Exception {
ActionMapping mapping = new ActionMapping();
Locale locale = new Locale("de", "DE");
Locale.setDefault(locale);
ActionMessages messages = new ActionMessages();
// 模拟用户请求并处理
HttpServletRequest request = mockingRequest(mapping);
HttpServletResponse response = mockingResponse();
ActionForward forward = executeAction(mapping, form, request, response);
// 验证结果
String localizedText = (String) request.getAttribute("info");
Assert.assertNotNull("Localized text should not be null", localizedText);
Assert.assertTrue("Localized text is not in correct language", localizedText.equals("Dies ist eine Information."));
}
在实际开发中,还可能需要为某些地区提供定制化的资源文件,以适应特殊的格式化要求。开发团队应当定期审查并优化本地化资源文件,确保其质量和维护性。
通过以上各步骤,我们详细解读了Struts框架如何实现软件的国际化与本地化。实践证明,良好的国际化与本地化支持不仅提升了用户体验,也为软件产品拓展国际市场打下了坚实的基础。
7. Struts异常处理机制与最佳实践
异常处理是任何成熟框架不可或缺的一部分,Struts框架也不例外。本章节将深入探讨Struts中的异常处理机制,并分享一些在实际开发过程中应用的最佳实践建议。
7.1 Struts异常处理机制详解
7.1.1 异常处理的基本概念
在讨论Struts的异常处理之前,让我们先回顾一下异常处理的一些基本概念。异常(Exception)是程序运行时发生的不正常情况,它可以是编程错误、外部错误或是用户输入错误。Java将这些错误视为异常对象,当异常发生时,程序流程会被转到一个可以处理这种情况的代码块。
异常处理通常使用 try-catch
块来捕获和处理异常。如果一个 try
块中的代码抛出了异常,那么 catch
块可以捕获该异常并执行相应的处理代码。此外,Java还提供了一个 finally
块,无论是否捕获到异常, finally
块中的代码总会被执行,它通常用于释放资源。
7.1.2 Struts中的异常捕获与处理
在Struts中,异常处理主要发生在Action的执行过程中。当Action抛出异常时,Struts可以将这些异常传递给配置的异常处理器(Exception Handler)。Struts提供了默认的异常处理器,但开发者也可以自定义异常处理器来更好地控制异常处理逻辑。
Struts的异常处理主要通过 struts.xml
配置文件中的 <global-exception-mappings>
标签来完成。例如,如果您想捕获所有异常并将其转发到一个名为 error.jsp
的页面,可以配置如下:
<global-exceptions>
<exception key="error.application" type="java.lang.Throwable" handler="com.example.MyExceptionHandler"/>
<!-- 其他异常映射 -->
</global-exceptions>
这里, type
指定了需要捕获的异常类型,而 handler
属性指定了用于处理该异常的类。自定义的异常处理器类需要实现 ExceptionMapping
接口,并实现 handleException
方法来定义具体的异常处理逻辑。
7.2 Struts开发的最佳实践建议
7.2.1 提高代码可维护性的实践
为了提高Struts应用的可维护性,以下是几个实用的建议:
- 模块化设计 :将应用分解为独立的模块,每个模块拥有自己的职责,这有助于分担工作量和简化测试过程。
- 合理使用ActionForm :虽然Struts 2已经减少了对ActionForm的依赖,但在复杂表单验证中,合理使用ActionForm可以提高代码的组织性和清晰度。
- 减少Action中的逻辑 :Action应该作为一个控制器,其职责是协调各个组件间的数据流转,而不是执行大量的业务逻辑。
7.2.2 性能优化与安全加固的建议
性能优化和安全加固是开发过程中的两个重要方面:
- 避免不必要的数据封装 :在Struts 2中,默认使用OGNL表达式语言,避免在OGNL表达式中进行复杂的运算,以减少不必要的性能开销。
- 使用拦截器进行安全检查 :可以创建自定义拦截器来执行安全相关的检查,如用户认证和权限验证,这样可以保证安全检查被集中处理,易于维护。
- 合理配置文件上传和下载 :对于文件上传和下载功能,合理配置相关的参数以防止大文件上传导致的服务器内存溢出等问题。
为了进一步加深理解,让我们以一个实际案例来说明如何在Struts项目中实现异常处理和性能优化:
- 自定义异常处理器 :在
struts.xml
中定义自定义异常处理器来捕获异常,并记录异常信息到日志文件,便于后续问题追踪和修复。
<global-exception-mappings>
<exception type="java.lang.Throwable" key="error.application" handler="com.example.MyExceptionHandler"/>
</global-exception-mappings>
-
性能优化实践 :在Action方法中,避免在循环或频繁调用的方法中使用重量级的服务调用或复杂的逻辑运算。
-
安全加固实践 :创建一个登录拦截器,在用户执行敏感操作之前,先验证用户的身份和权限。
通过结合实际操作和代码片段,本章节为你提供了Struts框架中异常处理的深入解析以及开发过程中的实践建议。这些最佳实践可以帮助开发者构建更加健壮、安全且易于维护的Web应用。
简介:Struts是一个开源框架,用于构建基于Java的企业级Web应用程序,并实现了MVC设计模式。本教程通过实例和详细解释,旨在指导学习者深入理解Struts框架的核心概念、配置、组件以及最佳实践,以便快速掌握Struts在Web应用开发中的应用。