速来报名!AICon北京站鸿蒙专场~ 了解详情
写点什么

将 Struts 应用迁移到 Struts 2(一)

  • 2007-04-05
  • 本文字数:5296 字

    阅读完需:约 17 分钟

大多数人都会熟悉 Struts, 无论是从项目实战中获得的经验还是从书中了解到的知识。在这一系列文章里,我们将通过一个由 Struts 迁移到 Struts 2 的简单应用例子向大家展现 Struts 2 的所有特征。

在我们开始介绍这个例子之前,你需要去了解一点 Struts 2 的背景知识。文章的第一部分将介绍 Struts 2 与 Struts 的核心架构的不同点,以助于更好地把所有概念联系起来。第二部分将深入探讨两者在 actions 上的差别、action 相关的框架特征和 action 的配置。在文章最后一部分将会讲述用户界面。我们会讲到其架构、UI 构件、主题和标签,还有如何为我们的应用加上新的外观。

我们并不打算谈及迁移过程的所有细节方面,我们只是从普通的出发点开始介绍 Struts 2 的概念和现在可用的所有新特征。但拥有这些知识后,无论以后迁移到何等规模的应用到 Struts 2 中你都可以易如反掌。

导言 / 历史

Struts 的第一个版本是在 2001 年 5 月份发布的。它的最初设想是通过结合 JSP 和 Servlet,使 Web 应用的视图和业务 / 应用逻辑得以清晰地分离开来。在 Struts 之前,最常见的做法是在 JSP 中加入业务和应用逻辑,或者在 Servlet 中通过println()来生成视图。

自从第一版发布以来,Struts 实际上已成为业界公认的 Web 应用标准。它的炙手可热也为自己带来了改进和变更,所以不但要跟上对 Web 应用框架不断变化的需求,而且要与日渐增多竞争激烈的众多框架的特性相融合。

到最后,产生了几个下一代 Struts 的解决方案。其中两个最受瞩目的方案是 Shale 和 Struts Ti。Shale 是一个基于构件的框架,并在最近成为 Apache 的顶级项目。而 Struts Ti 则是在 Struts 的成功经验基础上继续坚持对前端控制器(Front Controller)和 MVC(model-view-controller)模式进行改进。

WebWork 项目是在 2002 年 3 月发布的,它对 Struts 式框架进行了革命性改进,引进了不少新的思想,概念和功能,但和原 Struts 代码并不兼容。WebWork 是一个成熟的框架,经过了好几次重大的改进与发布。

在 2005 年 12 月,WebWork 与 Struts Ti 宣布合并。与此同时,Struts Ti 改名为 Struts Action Framework 2.0,成为 Struts 真正的继承者。

最后要注意的是,并不是说 Struts 或 WebWork 项目已经停止开发了。由于人们对这两个项目的兴趣仍然很高,而且也有很多开发者仍然愿意使用它们,因此这两个项目还在继续开发中,继续修复 Bug,改进功能和继续添加新功能。

请求运作过程

在我们开始详细探讨如何把应用由 Struts 迁移到 Struts 2 之前,让我们通过体验整个请求流程,看看新架构是如何运作的。

在我们体验了整个请求的生命周期后,你应当注意到很重要的一点——Struts 2 仍是以前端控制器框架为主体的。所有的概念还都是你以前所熟悉的。

这意味着:

  • Actions 仍然是通过 URL 触发的
  • 数据仍然是通过 URL 请求参数和 Form 参数传送到服务端的
  • 所有 Servlet 对象(如 request、response 和 session 等)仍在 Action 可用

以下是请求处理过程的高层概览:

整个请求的处理过程可以分为 6 步:

  1. 由框架产生一个请求并进行处理 - 框架根据请求匹配相应的配置,得到使用哪些拦截器,Action 类和返回结果的信息。
  2. 请求通过一系列的拦截器 - 拦截器和拦截器组可以按照不同级别进行组合配置来处理请求。它们为请求提供各种预处理和切面处理的应用功能。这和 Struts 的使用 Jakarta Commons Chain 构件的 RequestProcessor 类很相似。
  3. 调用 Action - 产生一个新的 Action 对象实例,并提供请求所调用的处理逻辑的方法。我们在第二部文章中将对这步骤进行进一步讨论。Struts 2 可以在配置 Action 时为请求分配其指定的方法。
  4. 调用相应的 Result - 通过匹配处理 Action 方法之后的返回值,获取相应 Result 类,生成并调用它的实例。处理 Result 可能产生的结果之一就是对 UI 模板(但并非只有一个)进行渲染,来产生 HTML。如果是这种情况的话,模板中的 Struts 2 tags 可以直接从 Action 中获取要被要被渲染的值。
  5. 请求再次经过一系列拦截器处理后返回 - Request 以和进入时相反的方向通过拦截器组,当然,你可以在这个过程中进行回收整理或者额外的处理工作。
  6. 响应被返回给用户 - 最后一步是将控制权交还给 Servlet 引擎。最常见的结果是把渲染后的 HTML 返回给用户,但返回的也可能是指定的 HTTP 头或者进行 HTTP 重定向。

你应该已经注意到 Struts 2 和 Struts 的差别了。最明显的就是 Struts 2 是一个 pull-MVC 架构。这是什么意思呢?从开发者角度看,就是说需要显示给用户的数据可以直接从 Action 中获取,而不像 Struts 那样必须把相应的 Bean 存到 Page、Request 或者 Session 中才能获取。

配置框架

首先最重要的是,通过配置 web.xml 文件让框架能在 Servlet 容器里运行。

下面这个就是大家都熟悉的 Struts 在 web.xml 里的配置方法:

<servlet></servlet><br></br><servlet-name></servlet-name>action<br></br><servlet-class></servlet-class>org.apache.struts.action.ActionServlet<br></br><init-param></init-param><br></br><param-name></param-name>config<br></br><param-value></param-value>/WEB-INF/struts-config.xml<p><load-on-startup></load-on-startup>2</p><br></br><servlet-name></servlet-name>action<br></br><url-pattern></url-pattern>*.do<br></br><servlet-mapping></servlet-mapping>在 Struts 2 中,配置有少许改变,最明显的是分发器(dispatcher)已由 Servlet 转为 Servlet Filter, 其配置和 Servlet 一样简单,如下:

<filter></filter><br></br><filter-name></filter-name>webwork<br></br><filter-class></filter-class><br></br> org.apache.struts.action2.dispatcher.FilterDispatcher<br></br><filter-name></filter-name>webwork<br></br><url-pattern></url-pattern>/*<br></br>和 Servlet 配置一样,Filter 配置中定义了 Filter 的名称(作为引用)和类名。Filter Mapping 通过 URI 和名称匹配来调用相应的 Filter。默认情况下,扩展名为“.action”,这是在 default.properties 文件(在 Struts 2 JAR 文件里)的“struts.action.extension”属性定义的。

工具箱:“default.properties”是默认配置选项定义文件。你可以通过在 classpath 中包含一个叫“struts.properties”的文件,设置不同的属性值,来覆盖默认配置的值,实现自己的配置。

对于 Struts 来说, Servlet 配置提供了一个用于定义文件名的 init-param tag 来配置 Struts,而 Struts 2 没有这样的配置参数,取而代之的是在 classpath 下的默认配置文件“struts.xml”。

工具箱 / 提示:因为 Struts Actions(扩展名“.do”)和 Struts 2 Actions(扩展名“.action”)两者的扩展名命名空间不一样,所以 Struts 和 Struts 2 可以在同一个 Web 应用系统中无碍地共存。所以这就为迁移提供了很好的条件,加入适当的配置,新功能的开发都用 Struts 2。保持原有的遗留功能,如果时间和资源允许的情况下再逐步迁移。另一种方法是,只把 Struts 2 的扩展名改为“.do”,这样就可使得以前的 JSP 页面可重用。

解剖 Actions

在上面介绍的请求运作流程中,我们从高层次上谈及了一些 Struts 和 Struts 2 的不同点。现在我们将较深入地探讨这两个框架中 Action 结构的具体差别。

让我们来回顾一下 Struts 的 Action 的主要结构。Struts Action 的主要形式如下:

public class MyAction extends Action {<br></br> public ActionForward execute(ActionMapping mapping,<br></br> ActionForm form,<br></br> HttpServletRequest request,<br></br> HttpServletResponse response)<br></br> throws Exception {<br></br> // do the work<br></br> return (mapping.findForward("success"));<br></br> }<br></br>}当你实现一个 Struts Action 时, 需要注意以下问题:

  1. 所有的 Action 都继承于 Action 基类。
  2. 所有的 Action 都必须是线程安全的,因为只产生一个 Action 实例。
  3. 因为所有的 Action 都必须是线程安全的,所有在 Action 处理过程中所需要的对象都必须以方法参数的形式传入。
  4. 处理 Action 所调用的方法必须命名为“execute”(在 Struts 中的 DispatchAction 类可以调用同一个 Action 的其它方法,但实际上在框架中的入口点仍然是“execute”方法)。
  5. ActionForward 结果是通过 ActionMapping 类中的方法来产生的,通常的做法是通过调用“findForward”方法。

相比较之下,Struts 2 的 Action 提供了更简单的实现方式。下面就是个例子:

public class MyAction {<br></br> public String execute() throws Exception {<br></br> // do the work<br></br> return "success";<br></br> }<br></br>}首先你会注意到的是,Struts 2 中的 Action 不再继承于任何类或需要实现任何接口。实际上,它还远不只这些。按照惯例,只有“execute”方法能调用 Action, 但在 Struts 2 中并非必要,任何声明为 public String methodName() 方法都能通过配置来调用 Action。

另外,你会注意到返回的对象不是 ActionForward,而是 String。如果你不喜欢以字符串的形式出现在你的代码中,有个 Helper 接口 Action 可以以常量方式提供常见结果,如“success”、“none”、“error”、“input”和“login”。

最后,和 Struts 最大的革命性的不同是,处理 Action 过程中调用的方法(“execute”方法)是不带参数的。那你如何获取你所需要的对象呢?答案是使用“反转控制(Inversion of Control)”,也叫“依赖注入(Dependency Injection)”的模式(想更多地了解这方面信息请看 Martin Fowler 的文章 http://www.martinfowler.com/articles/injection.html )。Spring 框架使得这个模式流行起来,然而 Struts 2 的前身(WebWork)也在同时应用上了这个模式。

为了更好地了解反转控制,让我们来看看一个例子,如何在 Action 处理过程中可以访问到当前请求 HttpServerRequest 对象。

在我们的例子中,我们使用的依赖注入机制是接口注入。就如其名称一样,接口注入需要的是已经被实现了的接口。这个接口包含了相应属性的 setter,为 Action 提供值。例子中我们使用了 ServletRequestAware 接口,如下:

public interface ServletRequestAware {<br></br> public void setServletRequest(HttpServletRequest request);<br></br>}当我们继承这个接口后,我们原本简单的 Action 看起来有点复杂了,但是这时我们可以获取 HttpServerRequest 对象来使用了。

public class MyAction implements ServletRequestAware {<br></br> private HttpServletRequest request;<br></br> public void setServletRequest(HttpServletRequest request) {<br></br> this.request = request;<br></br> }<br></br> public String execute() throws Exception {<br></br> // do the work using the request<br></br> return Action.SUCCESS;<br></br> }<br></br>}看起来现在这些属性是类级别的,并不是线程安全的,会出现问题。其实在 Struts 2 里并没有问题,因为每个请求过来的时候都会产生一个新的 Action 对象实例,它并没有和其他请求共享一个对象,所以不需要考虑线程安全问题。

现在我们还有最后一步,就是为这个 Action 关联上ServletConfigInterceptor拦截器。这个拦截器提供了一系列功能去获取 HttpServletRequest,并可以把它注入到实现了ServletRequestAware接口 Action 中。这时你并不需要担心如何配置这些,我们将在下一篇文章中有具体讲述。最重要的是让我们明白到是拦截器和接口共同合作下为 Action 提供了反转控制功能的。

这个设计的好处是能让 Action 和框架完全解耦。Action 仅仅是一个与框架无关的简单 POJO。这给单元测试带来极大的好处,Struts 2 Action 的单元测试远比 Struts Action 使用 StrutsTestCase 或 MockStrutsTestCase 的单元测试简单。

总结 / 综述

到现在为止,你应该对 Struts2 的基础有所了解了——包括高层的框架概念和基础的请求流程。你也应该能自己动手在 Servlet 容器里配置 Struts 2,并理解 Struts 和 Struts 2 两者之间在 Action 方面的差别了。

在下篇文章中,我们将会介绍一个详细的迁移的例子,同时我们也在这章学到的知识基础上,演示如何由 Struts 向 Struts 2 的 Action 迁移。在最后讲述如何在应用中使用 JSTL、JSP 和 Struts2。我们会进一步探讨 Struts 和 Struts 2 在 Action 上的区别,Struts 2 的配置和其他框架元素,和谈到更多的 Action 相关的框架特征。

关于作者

Ian Roughley 是一位技术演讲人、作家及独立咨询顾问,住在马萨诸塞州的波士顿。他具有十多年提供架构设计、开发、过程改进以及指导等方面服务的经验,客户范围小至创业公司,大到财富 500 强前 10 名的公司。他专注于具有实效性且以结果为目标的方法,是开源及以敏捷开发为基础的过程和质量改进的支持者。

关于译者

陈俊 SpringSide 开源项目的主力成员,中科院软件工程硕士,就职于 Accenture。长期从事 J2EE 企业级应用开发, 略有小成。热衷于软件体系结构,设计模式,软件过程改进及敏捷开发研究,以成为出色的架构师为目标。爱尝试不同的开源技术,一直投身 SpringSide 开发,为国内开源出一分绵力。

2007-04-05 20:002328
用户头像

发布了 27 篇内容, 共 10.1 次阅读, 收获喜欢 15 次。

关注

评论

发布
暂无评论
发现更多内容

Navicat Charts Viewer for Mac(Navicat图表查看器) v1.2.16激活版

iMac小白

Navicat for MySQL Mac版(数据库管理开发工具)v16.3.6中文特别版

iMac小白

Mac电脑图像编辑软件:Pixelmator Pro中文直装激活

iMac小白

AI加速引擎PAI-TorchAcc:整体介绍与性能概述

阿里云大数据AI技术

模型训练 大模型 #人工智能 机器学习PAI

Navicat for SQLite 16 for Mac(强大数据库管理及开发工具)v16.3.6中文版

iMac小白

风险评估是什么意思?与等保测评有什么区别?

行云管家

等保 等保测评 风险评估

企业需要知道的数据安全管理产品-堡垒机

行云管家

数据安全 堡垒机 运维审计

Web3.0区块链技术开发方案:区块链数字钱包软件开发

区块链软件开发推广运营

dapp开发 区块链开发 链游开发 NFT开发 公链开发

鸿蒙Harmony 时代的跨端方案

FN0

小程序 鸿蒙 鸿蒙开发

一端开发、多端部署,如何利用移动开发利器

Geek_2305a8

30分钟开发Vue 3插入客制化脚本插件

星辰编程理财

Vue 前端 vite AST 前端客制化

电商卖家如何利用API提升客户满意度

技术冰糖葫芦

API 接口

Bridge 2024 for Mac(BR)v14.0.2激活版

iMac小白

用云手机进行舆情监测有什么作用?

Ogcloud

云手机 海外云手机 云手机海外版 国外云手机

使用OpenTelemetry进行监控

快乐非自愿限量之名

.net 优化 开发语言 项目开发

QLab Pro for Mac(音频剪辑软件)v5.3.6激活版

iMac小白

洞悉市场趋势,把握增长先机:商品企划系统助力品牌飞跃式增长

第七在线

通义千问1.5(Qwen1.5)大语言模型在PAI-QuickStart的微调与部署实践

阿里云大数据AI技术

阿里云 人工智能’ 通义千问 机器学习PAI 大语言模型

云手机的境外舆情监控应用——助力品牌公关

Ogcloud

云手机 海外云手机 云手机海外版 国外云手机 舆情监控

MySQL学习笔记

秃头小帅oi

Adobe Photoshop 2024 v25.5最新中文破解版 附安装教程

iMac小白

什么是HTTP状态码,常见状态码有哪些

德迅云安全杨德俊

使用C++界面框架ImGUI开发一个简单程序

EquatorCoco

c++ UI API 开发语言

开发者手机开源代码编译指导

Laval小助手

友盟+Hologres:千亿级多维分析平台建设实践

阿里云大数据AI技术

友盟 数据分析、 数据查询 hologres

阿里巴巴1688商品详情API:如何高效地获取商品信息?

技术冰糖葫芦

API 接口

Navicat Charts Creator for Mac(Navicat图表创建器)v1.2.16激活版

iMac小白

这波操作看麻了!十亿行数据,从71s到1.7s的优化之路。

不在线第一只蜗牛

数据结构 数据 数据优化 比赛

AI加速引擎PAI-TorchAcc:OLMo训练加速最佳实践

阿里云大数据AI技术

模型训练 大模型 机器学习PAI

云手机海外社交媒体监测:洞悉舆论,把握商机

Ogcloud

云手机 海外云手机 云手机海外版 国外云手机

将Struts应用迁移到Struts 2(一)_Java_Ian Roughley_InfoQ精选文章