本文还有配套的精品资源,点击获取
简介:Struts2是一个用于Java Web开发的MVC框架,通过配置文件如 struts.xml 来定义应用结构。本示例将详细介绍Struts2框架的基础用法,包括多个配置文件的合并、Action配置、拦截器堆栈、结果页面配置、包概念、动态方法调用、类型转换、国际化支持、异常处理以及插件机制。通过实战演练,帮助开发者构建高效可维护的Web应用程序。
1. Struts2框架概述
Struts2是一个用于构建Web应用程序的流行框架,它是作为Apache Struts项目的一个分支而开始的。它用于简化基于MVC(Model-View-Controller)设计模式的应用程序的开发,将业务逻辑、数据和用户界面隔离开来。
1.1 Struts2的核心概念
Struts2基于拦截器的架构,允许开发者在请求处理的各个环节插入自定义逻辑。框架的核心包括Action类,它是业务逻辑的封装,以及Interceptors(拦截器),用于处理通用任务,比如数据验证、输入格式化等。
1.2 Struts2与Struts1的区别
与早期的Struts1相比,Struts2引入了更多的改进和新特性。它提供了更加灵活的配置方式,支持多种视图技术,并且简化了标签库的使用。Struts2还提供了更好的异常处理和更广泛的插件支持,让扩展和定制变得容易。
1.3 Struts2的工作原理
Struts2框架的工作流程从一个HTTP请求开始,由过滤器(FilterDispatcher)捕获并转交给Struts2框架处理。框架根据配置文件 struts.xml 决定哪个Action类将处理请求,并且执行相应的业务逻辑。最后,Action的执行结果会返回一个字符串,这个字符串将决定使用哪个视图组件(例如JSP页面)来展示数据。
在后续的章节中,我们将深入探讨Struts2的配置文件 struts.xml ,理解其结构和使用方法,以及如何利用其高级特性来优化我们的Web应用程序。
2. 配置文件 struts.xml 详解
2.1 Struts2核心配置文件
2.1.1 配置文件的作用与结构
Struts2框架的 struts.xml 文件是整个框架运行的基石,它定义了框架中的核心组件以及它们之间的交互关系。 struts.xml 文件的作用包括:
映射请求的URL到相应的Action类,从而执行业务逻辑。 定义结果页面的重定向逻辑。 设置拦截器和拦截器栈,用于请求处理的预处理和后处理。 管理全局异常处理逻辑。 配置应用程序的包结构,为不同的模块定义命名空间。 支持国际化配置,实现多语言界面。
该文件的结构通常包括以下元素:
以上是 struts.xml 文件的一个基本结构示例。它设置了编码格式为UTF-8,并定义了一个名为 default 的包,该包继承自 struts-default ,并且具有根命名空间。
2.1.2 基本标签的使用方法
在 struts.xml 中,有几个重要的标签需要掌握:
在这个例子中,定义了一个名为 login 的Action,它引用了一个默认的拦截器栈( defaultStack ),这个栈提供了常见的处理流程。如果登录成功,将返回 success.jsp 页面;如果需要重新输入,则跳转到 login.jsp 页面。
2.2 配置文件的高级特性
2.2.1 自定义配置文件的加载机制
Struts2允许开发人员定义多个 struts.xml 文件,可以根据不同模块的需求进行配置。加载机制如下:
当Struts2启动时,它会查找类路径下的 struts.xml 文件。 可以通过配置常量 struts.configuration.files 指定多个配置文件的路径,这些文件将以定义的顺序被加载。 自定义文件中可以覆盖默认的配置文件中的设置,实现更细粒度的控制。
在这个例子中, struts-default.xml 是Struts2框架的默认配置文件, struts-plugin.xml 和 struts-custom.xml 是用户自定义的文件,后者的设置会覆盖前者的配置。
2.2.2 配置文件与资源文件的关联
通过 struts.xml 中的
在上述代码中, messages 是一个资源文件的基本名,该文件必须位于类路径下,如 /resources/messages.properties 。Struts2会根据用户的语言环境,加载相应的国际化资源文件。
通过以上配置,可以实现 struts.xml 文件的高级自定义和国际化支持,为用户提供更丰富和本地化的Web应用体验。
3. 多配置文件的应用与合并
3.1 配置文件的拆分与管理
在大型项目中,单个 struts.xml 配置文件往往会变得冗长且难以维护。为了提高可维护性,Struts2框架允许我们拆分成多个配置文件,同时提供了灵活的管理方式,以实现模块化的配置管理。
3.1.1 逻辑拆分与模块化管理
将配置文件拆分成多个小的文件,每个文件负责一个模块或业务单元的配置,可以提高代码的可读性和可维护性。在Struts2中,我们可以按如下方式组织配置:
3.1.2 文件合并策略与实践
拆分后,就需要一个合并策略来整合所有的配置文件。Struts2提供了两种合并配置文件的策略:
物理合并 :直接在主配置文件中使用
程序合并 :通过程序代码动态加载配置文件,例如:
InputStream is = null;
try {
is = new FileInputStream("path/to/another/struts.xml");
XmlConfigBuilder builder = new XmlConfigBuilder(is);
ConfigurationManager configurationManager = new ConfigurationManager(builder.build());
configurationManager.start();
} catch (FileNotFoundException e) {
e.printStackTrace();
} finally {
if (is != null) {
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
上述代码展示了如何通过 XmlConfigBuilder 和 ConfigurationManager 来动态加载额外的Struts配置。
3.2 配置文件的继承与覆盖
3.2.1 父子配置文件的继承机制
继承机制允许开发者通过定义父子关系来减少配置的冗余。在Struts2中,使用 extends 属性来定义继承关系:
在这里, child 包继承了 parent 包的配置。如果子包中有与父包同名的配置项,将覆盖父包中的配置项。
3.2.2 配置覆盖的应用场景与技巧
覆盖配置通常用于定制化需求,例如,在多环境部署时(开发、测试、生产环境),我们可以创建三个不同的配置文件,仅在需要定制的地方覆盖父配置文件中的设置。
这里是一个覆盖策略的实际应用示例:
在上述配置中, custom 包覆盖了 parent 包中 customAction 的默认结果页面设置,改为指向一个定制的JSP页面。
为了进一步管理和维护覆盖策略,我们可以设计一个配置管理类,用于根据不同的环境选择合适的配置文件进行加载:
public class ConfigManager {
public void loadConfig(String env) {
// 根据环境变量env加载不同的配置文件
InputStream is = null;
try {
if ("dev".equals(env)) {
is = new FileInputStream("dev-struts.xml");
} else if ("test".equals(env)) {
is = new FileInputStream("test-struts.xml");
} else if ("prod".equals(env)) {
is = new FileInputStream("prod-struts.xml");
}
XmlConfigBuilder builder = new XmlConfigBuilder(is);
ConfigurationManager configurationManager = new ConfigurationManager(builder.build());
configurationManager.start();
} catch (FileNotFoundException e) {
e.printStackTrace();
} finally {
if (is != null) {
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
在这个类中,根据环境变量 env 的值来加载相应的配置文件,实现了配置的动态管理和环境隔离。
配置文件的拆分、合并、继承与覆盖是Struts2多配置文件管理的关键,它们可以帮助开发者有效地组织项目,使得每个部分都清晰且易于管理。开发者应根据项目规模和团队习惯选择合适的策略,以达到最佳的配置管理和维护效果。
4. Action类与拦截器堆栈
在Struts2框架的MVC设计模式中,Action类充当控制器的角色,负责业务逻辑的处理。拦截器则提供了强大的机制来扩展和控制Action的执行流程。本章节将深入探讨Action类的配置与使用,以及拦截器堆栈的配置与定制。
4.1 Action类的配置与使用
4.1.1 Action类的基本结构与配置
Action类负责接收用户的请求并返回相应的响应。它必须是公共的、非静态的,并包含一个无参数的方法,通常是 execute() ,用于执行业务逻辑并返回一个字符串结果。例如:
public class ExampleAction extends ActionSupport {
private String input;
public String getInput() {
return input;
}
public void setInput(String input) {
this.input = input;
}
@Override
public String execute() {
// 实现业务逻辑
return SUCCESS;
}
}
在 struts.xml 中配置Action类如下:
4.1.2 ActionContext与OGNL表达式的应用
ActionContext是Struts2框架中用于存储Action类上下文信息的容器,其中包含了请求参数、会话信息等。OGNL(Object-Graph Navigation Language)是Struts2中用于访问ActionContext中数据的语言。
在Action类中,可以通过ActionContext访问请求参数:
ActionContext context = ActionContext.getContext();
Map
String value = (String) parameters.get("input");
OGNL表达式可以在配置文件中直接使用,以简化数据获取的过程,如:
'The value is: ' + #input
4.2 拦截器堆栈的配置与定制
4.2.1 拦截器的工作原理与配置方法
Struts2拦截器在Action执行前后进行拦截,可以执行各种预处理或后处理操作。拦截器工作流程图如下:
graph LR
A[开始请求] --> B[请求到达Action]
B --> C{是否有拦截器堆栈}
C -->|是| D[执行拦截器堆栈]
C -->|否| E[直接执行Action]
D --> F{拦截器判断}
F -->|继续| G[下一个拦截器]
F -->|中断| H[拦截器处理逻辑]
G --> I[返回到拦截器判断]
H --> E
I -->|结束| E
E --> J[返回结果]
拦截器的配置在 struts.xml 中完成:
4.2.2 自定义拦截器的创建与应用
自定义拦截器需要实现 Interceptor 接口或继承 AbstractInterceptor 类。下面是一个简单的自定义拦截器示例:
public class MyInterceptor extends AbstractInterceptor {
@Override
public String intercept(ActionInvocation invocation) throws Exception {
System.out.println("MyInterceptor is working!");
return invocation.invoke();
}
}
在 struts.xml 中配置该拦截器并引用:
通过这种方式,自定义拦截器可以被加入到执行流程中,根据业务需求添加额外的处理逻辑,例如验证用户权限、处理通用逻辑等。
在本章节中,我们详细探讨了Struts2中Action类的配置与使用方法,以及拦截器堆栈的创建和应用。下一章节将深入分析结果页面的配置与跳转,以及包配置的组织与要点。
5. 结果页面与包配置
结果页面是用户操作后看到的页面,它们可以是简单的静态页面,也可以是复杂的动态生成的页面。在Struts2框架中,结果页面的配置与管理是非常重要的一个部分,合理的配置可以使得项目的结构更加清晰,维护更加方便。本章我们将深入探讨如何配置结果页面以及如何组织包(Package)配置。
5.1 结果页面的配置与跳转
5.1.1 结果页面的类型与配置方式
在Struts2中,结果页面通常通过
上面的配置表示,当Action执行完毕且返回"success"这个结果时,Struts2将会查找 /WEB-INF/views/success.jsp 页面来显示给用户。
Struts2提供了多种内置的结果类型:
dispatcher :默认类型,用于请求分发到JSP页面。 chain :用于在不同Action之间传递数据,可以实现Action之间的链式调用。 stream :用于将数据直接以流的形式发送到客户端,可以用来下载文件。 plainText :将结果以纯文本形式发送到客户端,常用于返回JSON或XML格式数据。 ...等等
5.1.2 动态结果页面的生成策略
动态结果页面的生成往往需要根据业务逻辑的需要动态地决定返回哪个页面。例如,一个用户登录操作,如果登录成功,根据用户的角色可能会显示不同的首页。
在Struts2中,动态结果页面的生成可以通过OGNL表达式来实现,如下示例:
/userWelcome-${user.role}.jsp
在这个例子中, ${user.role} 是OGNL表达式,它会根据Action中 user 对象的 role 属性动态生成不同的页面。
动态结果页面还可以结合条件判断语句来实现,如下所示:
<% if (user.getRole().equals("admin")) {
out.println("adminWelcome.jsp");
} else {
out.println("userWelcome.jsp");
} %>
在这段配置中,使用了内嵌的Java代码块,根据 user 对象的角色动态决定页面。需要注意的是,在 type 属性中指定了 chain ,这意味着它会继续链式调用下一个Action。
5.2 包(Package)的组织与配置
在Struts2中,包(Package)是Action类的容器,用于组织和管理Action。一个包可以包含多个Action配置,它们可以定义在同一个 struts.xml 文件中,也可以拆分到不同的配置文件中。
5.2.1 包的作用与配置要点
包的主要作用如下:
提供命名空间 :避免不同模块间的Action名称冲突。 权限控制 :可以对包内的Action进行权限控制。 模块化管理 :提高项目的可维护性和可扩展性。
配置包的基本语法如下:
这里的 name 属性指定包的名称, extends 属性用于继承其他包的配置,而 namespace 属性定义了包的命名空间。
包配置中有一些要点需要注意:
继承struts-default包 :继承 struts-default 包可以使得Action使用Struts2提供的所有默认拦截器。 命名空间的使用 :命名空间的使用可以使得URL更加清晰,比如 /example/user/login ,便于管理和维护。 权限控制 :通过定义访问控制列表(ACL),可以限制哪些用户可以访问特定的Action。
5.2.2 包的命名空间与权限控制
命名空间(namespace)是Struts2中区分不同Action组的重要概念。它不仅有助于URL的组织,还能在一定程度上帮助管理权限。例如,如果一个Action位于 /admin 命名空间,那么可以推断这个Action需要管理员权限。
权限控制通常通过Struts2的权限拦截器来实现。Struts2提供了一系列权限控制相关的拦截器,如 roles 拦截器,可以用来限制访问特定的Action。
admin
这个配置将 roles 拦截器应用在包内,只有当用户角色为admin时,才能访问该包内的Action。
在实际应用中,权限控制往往结合用户的登录状态、角色以及特定的权限标识来实现复杂的权限逻辑,以保证系统的安全性。
包(Package)的合理组织与配置是Struts2项目管理的重要部分。它不仅影响项目的结构,还对项目的后期维护和扩展有深远的影响。通过学习本章的内容,开发者可以掌握如何高效配置结果页面和包,为项目的顺利实施打下坚实的基础。
6. Struts2高级特性应用
6.1 动态方法调用(DMI)
6.1.1 动态方法调用的机制与限制
动态方法调用(DMI)是Struts2框架中的一个重要特性,它允许开发者在运行时动态地指定要执行的Action方法,而不是在配置文件中静态定义。DMI提供了一种灵活的方式来调用Action中的多个方法,尤其在处理表单提交时非常有用。
DMI的工作原理基于一个名为 method 的请求参数。当Struts2接收到一个请求时,会检查请求参数 method 的值,并尝试在对应的Action类中找到具有相同名称的方法来执行。例如,如果请求中包含了 method=submitForm ,Struts2会尝试调用Action类中的 submitForm() 方法。
尽管DMI非常灵活,但它也有一些限制:
方法访问级别 :被DMI调用的方法必须是 public 的。 方法名称长度 :方法名称不能超过20个字符,因为DMI使用了一个特定的后缀 .method 来动态加载方法,这个后缀长度加上方法名最长为24个字符。 方法参数 :DMI支持的方法不能有参数。如果方法需要参数,必须使用静态Action映射,并在 struts.xml 文件中进行配置。
6.1.2 动态方法调用在实际开发中的应用
在实际开发中,DMI可以用来简化代码和提高用户体验。例如,在一个表单提交场景中,可能需要根据用户的选择执行不同的处理逻辑。DMI可以让你在一个Action类中封装这些逻辑,并根据不同的表单提交参数动态地调用不同的方法。
public class MyAction extends ActionSupport {
public String view() {
return SUCCESS;
}
public String submit() {
// 处理提交数据
return SUCCESS;
}
public String delete() {
// 执行删除操作
return SUCCESS;
}
}
在上面的Action类中,有三个方法: view 、 submit 和 delete 。在 struts.xml 中,你可以配置一个Action,它使用DMI调用这些方法:
在JSP页面,你可以创建一个表单,当提交时,根据不同的操作调用不同的方法:
这样,当表单被提交时,用户选择的操作(view, submit, delete)将作为 method 参数传递,并由DMI机制调用对应的Action方法。
6.2 自动类型转换机制
6.2.1 类型转换的基本原理
Struts2的自动类型转换机制是框架中的一个便捷特性,它自动将请求参数从字符串转换为Action方法参数所需的类型。这个过程对于处理表单数据和简化Action类的代码非常有用,因为开发者不需要编写额外的代码来处理类型转换。
类型转换的基本原理涉及以下几个步骤:
查找转换器 :当Struts2准备填充Action的属性时,它会查找一个合适的转换器。如果请求参数的值是字符串,Struts2会尝试将其转换为相应的类型。 执行转换 :转换器是一个实现了 TypeConverter 接口的类,它负责执行实际的转换逻辑。 注册转换器 :Struts2使用默认的转换器注册器( TypeConverterRegistry ),将默认转换器与常见的类型(如 Integer , Double , Date 等)关联起来。 自定义转换器 :开发者可以提供自定义的转换器,并在 struts.xml 中注册,或者使用注解 @Conversion 来标记转换器类。
6.2.2 自定义类型转换器的开发与应用
当默认的类型转换不能满足需求时,开发者可以创建自定义的类型转换器。例如,假设有一个日期格式的需求不符合标准转换器的处理,这时可以创建一个自定义的日期转换器。
以下是自定义日期转换器的一个例子:
public class CustomDateConverter implements TypeConverter {
private static final String DATE_FORMAT = "dd/MM/yyyy";
@Override
public
if (values == null || values.length == 0) {
return null;
}
try {
SimpleDateFormat sdf = new SimpleDateFormat(DATE_FORMAT);
return (T) sdf.parse(values[0]);
} catch (ParseException e) {
throw new TypeConversionException("Could not format the date", e);
}
}
@Override
public String convertToString(Map context, Object o) {
SimpleDateFormat sdf = new SimpleDateFormat(DATE_FORMAT);
return sdf.format((Date) o);
}
}
在上述代码中, CustomDateConverter 实现了 TypeConverter 接口,并定义了转换逻辑。需要注意的是,转换器需要处理数组,因为一个属性可能有多个值。
接下来,需要在 struts.xml 中注册这个转换器:
在转换规则中,指定了转换器类以及要转换的类型(在本例中是 date )。这样,当请求参数是日期字符串且类型为 date 时,Struts2就会使用 CustomDateConverter 来执行转换。
private Date birthDate;
public Date getBirthDate() {
return birthDate;
}
public void setBirthDate(Date birthDate) {
this.birthDate = birthDate;
}
在Action类中定义了一个 Date 类型的属性 birthDate 。当Struts2填充这个属性时,它会使用我们之前定义的 CustomDateConverter 来进行转换。
通过这种方式,开发者可以根据实际需求,提供自定义的类型转换逻辑,从而使得数据绑定更加灵活和准确。
7. Struts2的国际化与异常处理
7.1 国际化(i18n)的支持与实践
Struts2框架提供了强大的国际化支持,允许开发者方便地为应用添加多语言支持。下面将详细介绍国际化配置的基本步骤,以及如何管理多语言资源文件。
7.1.1 国际化配置的基本步骤
在Struts2中,国际化配置主要涉及以下步骤:
资源文件的创建 :通常,你需要为每种语言创建一个属性文件,例如 ApplicationResources_en_US.properties 、 ApplicationResources_es_ES.properties 等。 strutsMessages标签的使用 :在JSP页面中,可以通过
示例代码如下:
在这个例子中, ApplicationResources 是资源文件的前缀。
7.1.2 多语言资源文件的管理与应用
在实际应用中,管理多语言资源文件需要遵循以下最佳实践:
保持文件结构清晰 :按模块划分资源文件,并使用
7.2 全局异常处理策略
Struts2框架同样支持复杂的异常处理策略,允许应用以一致的方式处理各种运行时错误。
7.2.1 异常处理框架的介绍
Struts2提供了 Result 接口的 exception 方法来定义如何处理异常。异常处理可以通过XML配置文件进行配置,也可以通过注解的方式来实现。
7.2.2 全局异常处理器的设计与实现
一个典型的全局异常处理器设计包括以下几个步骤:
创建异常处理类 :实现 ExceptionMapping 接口,并定义 exception 方法来处理异常。 配置全局异常处理 :在 struts.xml 中,使用
示例配置:
在这个例子中,所有被标记为 error 的异常都会被导向 /error.jsp 页面。
一个完整的异常处理类示例:
public class MyExceptionHandler implements ExceptionMapping {
public String exception(ActionInvocation invocation, Exception ex) {
invocation.getStack().push(ex);
return ERROR;
}
}
在这个类中, exception 方法将异常对象推送到值栈上,并返回 ERROR 结果。
通过以上两个部分的介绍,我们已经了解了Struts2如何支持国际化及异常处理。接下来的内容将深入到插件机制与扩展这一领域,探索如何在Struts2框架中利用插件进行功能的扩展。
本文还有配套的精品资源,点击获取
简介:Struts2是一个用于Java Web开发的MVC框架,通过配置文件如 struts.xml 来定义应用结构。本示例将详细介绍Struts2框架的基础用法,包括多个配置文件的合并、Action配置、拦截器堆栈、结果页面配置、包概念、动态方法调用、类型转换、国际化支持、异常处理以及插件机制。通过实战演练,帮助开发者构建高效可维护的Web应用程序。
本文还有配套的精品资源,点击获取