有很多人都很熟悉 Struts, 无论是从项目中直接获得的实战经验还是从书中了解到的。我们这一系列文章,将通过一个由 Stuts 转移到 Struts2 简单的例子向大家展现Struts2的所有特征。
在我们开始这个例子之前,你需要去知道一点 Struts2的背景知识。 在第一部分的文章中,我们将介绍Struts2与Struts的核心框架的不同点,以助于更好地了解其他方面的整合。第二部分中,我们将深入探讨 actions 的差别, action相关的框架特征,和action配置。在最后一部分中,我们将会讲述 user interface,我们也会讲到其架构,UI构件,themes 和标签。 还有如何为你的应用加上新的外观。
我们并不打算谈及迁移过程的所有细节方面,我们只是从出发点开始介绍Struts2 的概念和现在可用的所有特征。但拥有这些知识,你将在以后Struts2的应用中无往而不利。
Struts的历史
Struts的第一个版本 是在 2001年5月份发布。它提供了一个Web应用的解决方案,如何让 JSPs 和 servlets 共存去提供清晰的分离视图和业务和应用逻辑的架构。在Struts之前,最通常的做法是在JSP中加入业务和应用逻辑,或者在servlets中生成视图。
自从第一个版本的发布, Struts 实际上已成为业界公认的Web应用标准。但随着时间的推移,Web应用框架经常变化的需求,产生了几个下一代 Struts的解决方案。其中两个可选方案是Shale 和 Struts Ti。 Shale 是一个基于构建的框架,并在最近成为 Apache 中的重要项目。而 Struts Ti 则是继续坚持 MVC模式的基础上改进,继续Struts的成功经验。
WebWork项目是在2002年3月发布的,它对Struts式框架进行了革命性改进,引进了不少新的思想,概念和功能,但和原Struts代码并不兼容。WebWork是一个成熟的框架,经过了好几次重大的改进与发布。在2005年12月,WebWork与Struts Ti决定合拼, 再此同时, Struts Ti 改名为 Struts Action Framework 2.0,成为Struts真正的下一代。
请求如何运作
在我们开始详细探讨如何转移Struts到Struts2之前,让我们来看看整个请求流程在新架构中是如何运作的。你会注意到在整个请求的生命周期,仍是以controller作主体,而且所有的概念还都是你以前所熟悉的, 就如:
通过URL请求的参数来调用Actions来把数据传给server.
所有的Servlet objects (request, response, session,之类.) 仍然可以在Action中获取
下图展示了整个请求的概要过程:
整个请求过程可以分为六步骤:
一个请求产生并经由框架处理 - 框架根据请求匹配相应的配置,如使用哪些拦截器,action 类和结果。
请求通过一系列的拦截器 - 拦截器,和拦截器组经配置后,能处理不同等级的请求,它们为请求提供了各种预处理,切面处理。这和Struts的使用 Jakarta Commons Chain 构件的 RequestProcessor类很相似。
调用 Action - 产生一个新的action对象实例,并提供请求所调用的处理逻辑的方法。Struts2 可以在配置action时为请求分配其指定的方法。我们在第二部文章中将对这步骤进行进一步讨论;
调用产生的结果 - 获取通过action的方法处理后返回来的结果,匹配其result class并调用产生的实例。有种情况是在UI模板去生成HTML时才去处理这些结果。如果在这种情况下,在Struts2 模板中的tags能直接返回到 action 中,取结果来呈现界面。
请求再次经过一系列的拦截器处理后返回 - 请求反顺序通过与原来进入时的拦截器链, 当然,你也可以配置在这个过程中减少或增加拦截器处理.
请求返回到用户 - 最后一步是由 control 返回到servlet。通常是生成HTML返回到user, 但你也可以指定返回的HTTP头或HTTP重定向。
你应该已注意到,Struts2与Struts的差别。最明显的就是Struts2是pull-MVC 架构,就是可以直接从Action中获取所需要的数据,而不是像Struts那样必须把 beans 存到page, request,或者session中才能获取。这个我们将在下一章中详细提及。
配置框架
首先最重要的是,让框架能通过web.xml在servlet containers里运行。
下面这个就是大家都熟悉的 Struts在 web.xml里的配置方法
<servlet>
<servlet-name>action</servlet-name>
<servlet-class>org.apache.struts.action.ActionServlet</servlet-class>
<init-param>
<param-name>config</param-name>
<param-value>/WEB-INF/struts-config.xml</param-value>
</init-param>
<load-on-startup>2</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>action</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
在 Struts2 中,这个有少许改变,最明显的是dispatcher 由servlet转为servlet filter, 其配置和servlet一样简单,如下:
<filter>
<filter-name>webwork</filter-name>
<filter-class>
org.apache.struts.action2.dispatcher.FilterDispatcher
</filter-class>
</filter>
<filter-mapping>
<filter-name>webwork</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
和servlet配置一样,filter配置定义了名称(供关联)和filter的类。filter mapping让URI匹配成功的的请求调用该filter。默认情况下,扩展名为".action"。
这个是在default.properties文件里的"struts.action.extension" 属性定义的。
工具箱: "default.properties"是配置选项定义文件。通过在classpath中包含一个叫"struts.properties"的文件,并设置不同的属性值,你可以覆盖这个默认的配置,实现自己的配置。
对于Struts, servlet配置提供了初始化tag的参数和使用的文件,而Struts2没有这样的配置参数,取而代之的是在classpath下的默认配置文件"struts.xml"。
工具箱/提示: Struts actions(扩展名".do"),Struts2 actions(扩展名".action"),所以Struts和Struts2可以在一个系统中共存。所以最好是保持原先的系统,在新功能的开发上用Struts2, 如果时间和资源允许的情况下再逐步迁移。另一种方法是只是把Struts2的扩展名改为".do",可重用JSPs.
分析Actions
在上面介绍的请求运作流程中,我们谈及了一些Struts和Struts2的不同点。现在我们将较深入地探讨这两个框架中action结构的具体差别。
让我们来回顾一下 Struts 的 action 结构, 主要的形式如下:
public class MyAction extends Action {
public ActionForward execute(ActionMapping mapping,
ActionForm form,
HttpServletRequest request,
HttpServletResponse response)
throws Exception {
// do the work
return (mapping.findForward("success"));
}
}
当实现一个Struts action时, 你需要注意一下问题:
所有的action 都必须继承于base Action 类.
所有的action都必须是线程安全的,因为action是单例的,singleton的.
因为所有的action都必须是线程安全的,所以所有的对象都不能是类属性, 都必须以方法参数的形式传值。
调用action的方法必须命名为 "execute" ( 在Struts中的 DispatchAction 类好像可以用其它方法去执行同一个action ,但实际上在框架中调用的仍然是 "execute" 方法。).
ActionForward 的结果是通过ActionMapping 类中的方法来产生的,通常是"findForward"方法.
相比较之下, Struts2的action 提供了很多简单的实现。下面就是个例子
public class MyAction {
public String execute() throws Exception {
// do the work
return "success";
}
}
首先你会注意到的是,Struts2中的action不再继承于任何类或需要实现任何接口。实际上,它还远不只这些。按照惯例,只有"execute"方法能调用action, 但在Struts2中并非必要,任何声明为public String methodName() 方法都能通过配置来调用action.
另外,你会注意到返回值不再是"ActionForward ",而是String, 如果你需喜欢String的形式,那在Action接口里有个帮助方法可以提供简单的结果常量,如"success", "none", "error", "input" 和 "login"。
最后,和Struts最大的革命性的不同是, 调用action不再是带参数的。那你如何在获得你所需要的值呢?答案是"inversion of control" 或 "dependency injection", 反转控制(想了解更多可以看Martin Fowler的文章
http://www.martinfowler.com/articles/injection.html)。
为了更好地了解反转控制,让我们来看看一个例子,如何在action处理过程中可以访问到HttpServerRequest 。在我们的例子中,我们用ServletRequestAware 接口,这个接口包含了相应属性的setter,如下
public interface ServletRequestAware {
public void setServletRequest(HttpServletRequest request);
}
当我们继承这个接口时,我们需要通过setter为我们的HttpServerRequest 属性变量赋值:
public class MyAction implements ServletRequestAware {
private HttpServletRequest request;
public void setServletRequest(HttpServletRequest request) {
this.request = request;
}
public String execute() throws Exception {
// do the work using the request
return Action.SUCCESS;
}
}
看起来现在这些属性是类级别的,并不是线程安全的,但是在Struts2里并没有问题,因为每个请求过来的时候都会产生一个新的action对象实例,它并没有和其他请求共享一个对象,所以不需要考虑线程安全问题。
现在我们还有最后一步,就是把action关联上ServletConfigInterceptor 拦截器。这个拦截器继承了ServletRequestAware 接口,并提供了把HttpServletRequest 注入到action中的功能。但是你现在不用担心如何配置这些,我们将在下一篇文章中具体讲述。最重要的是我们明白了拦截器和接口共同为action提供了反转控制的功能。
这个设计的好处是能让action完全和框架解耦。action仅仅是一个被框架使用的简单的POJO。这对于单元测试但来极大的好处, 你能方便的为Struts action实现 StrutsTestCase 或 MockStrutsTestCase 单元测试。
总结
By到现在为止,你应该已经了解了Struts2的整个请求流程,还有高层的框架概念, 你也应该能自己动手配置Struts2的action,和讲出Struts和Struts2的差别了。
在下篇文章中,我们将会介绍一个详细的Struts应用向Struts2迁移的例子,同时我们也会介绍迁移中相关的知识,会讲述如何综合使用JSTL, JSP 和 Struts2,进一步讲述Struts和Struts2的action的差别,Struts2的配置和其他框架元素,和谈到更多的其他相关框架的特征。
在这篇文章中,我们将会更详细地讲述如何由Struts 的action转为Struts 2的action。
一个应用的例子
这个例子选择了大家都熟悉的 - weblog. 简单地介绍下这例子的功能需求:
增加一个新的日志
察看一个日志
修改一个日志
删除一个日志
列出所有日至
增删修改(CRUD),是项目中最为普遍的应用。
业务逻辑类在Struts 和 Struts2 应用都是可共用的。如:
public class BlogService {
private static List<Blog> blogs = new ArrayList<Blog>();
public List<Blog> list() { ... }
public Blog create(Blog blog) { ... }
public void update(Blog blog) { ... }
public void delete(int id){ ... }
public Blog findById(int id) { ... }
}
BlogService 只是个简单的业务逻辑类,并不是接口,Struts 和 Struts2 的action皆可调用其实例。虽然这样设计在实际项目中会带来不必要的耦合,但我们的例子只是集中在讨论web层上,所以无关重要。
工具箱: 在第一篇文章中,我们谈论了在Struts2 actions中的依赖注入的接口注入方式。这个是servlet 相关类(HttpServletRequest, HttpServletResponse, PrincipalProxy, 等.)的主要注入方式,但这并不是唯一的方式。
Struts2 可以使用Spring框架作为默认的容器时,依赖注入的setter方法就可用了。通过在action中加入setter方法(如下演示), Struts2 框架将能从Spring框架中获得正确的信息,并通过setter加载在action中。
public void setBlogService(BlogService service) {
this.blogService = service;
}
和接口注入方式类似,我们需要一个拦截器来帮助我们完成任务,这就是 ActionAutowiringInterceptor 拦截器。这样我们的业务逻辑类就通过Spring框架管理自动在action被调用之前注入到Struts2得action中。有多种的配置参数(如by name, by type 或 automatically)可供选择,可以让对象和setter匹配的注入的方式根据你的需要而定。
Struts 应用中的代码
我们首先从Struts讲起。在Struts中,最普遍的做法是,对于每个需求用例(如save,update,remove,list)来说都会有对应的action类,同时也会有相应的action form类。在我们的应用中的这个方式或许不是最佳的实现方式(其他的解决方案包括使用dynamic form或者使用request来分发action),但我们例子中的做法是所有Struts开发者最熟悉的一种形式。了解了这种简单的实现方法,你有能力在迁移到Struts2时,使用更为优秀的方法。
在第一篇文章中我们谈过Struts 和 Struts2 中action的区别。现在我们从UML中再次看看他们的差别。一般来说form在Struts action中的表现形式是:
这action form将会在多个action中使用,让我们来看看它:
public class BlogForm extends ActionForm {
private String id;
private String title;
private String entry;
private String created;
// public setters and getters for all properties
}
如UML中展示的那样,其中一个限制就是必须继承ActionForm类,另外一个限制就是form中所有属性都必须是String类型,所以所有的getter和setter都必须只能接受String参数和返回String结果。
然后我们来看看action。我们这个例子中的action有view, create 和 update action。
The View Action:
The Create Action:
public class ViewBlogAction extends Action {
public ActionForward execute(ActionMapping mapping,
ActionForm form,
HttpServletRequest request,
HttpServletResponse response)
throws Exception {
BlogService service = new BlogService();
String id = request.getParameter("id");
request.setAttribute("blog",service.findById(Integer.parseInt(id)));
return (mapping.findForward("success"));
}
}
public class SaveBlogEntryAction extends Action {
public ActionForward execute(ActionMapping mapping,
ActionForm form,
HttpServletRequest request,
HttpServletResponse response)
throws Exception {
BlogService service = new BlogService();
BlogForm blogForm = (BlogForm) form;
Blog blog = new Blog();
BeanUtils.copyProperties( blog, blogForm );
service.create( blog );
return (mapping.findForward("success"));
}
}
The Update Action:
public class UpdateBlogEntryAction extends Action {
public ActionForward execute(ActionMapping mapping,
ActionForm form,
HttpServletRequest request,
HttpServletResponse response)
throws Exception {
BlogService service = new BlogService();
BlogForm blogForm = (BlogForm) form;
Blog blog = service.findById( Integer.parseInt(blogForm.getId()));
BeanUtils.copyProperties( blog, blogForm );
service.update( blog );
request.setAttribute("blog",blog);
return (mapping.findForward("success"));
}
}
这三个action都跟随着同一个模式:
产生一个新的业务逻辑对象实例 - 如前面所提到的,我们使用最直接的方式在action中使用业务逻辑对象,这表示在每个action中都会产生新的业务逻辑对象实例。
从请求中获得数据 - 这是两种形式之一。在view action中,"id"是从HttpServletRequest 对象中直接获取的。而在create 和 update action 中,则从ActionForm 中取值。ActionForm 与 HttpServletRequest 的调用方式其实很相似,唯一不同的ActionForm 是bean的从field中取值。
调用业务逻辑- 现在开始生成调用业务逻辑所需的参数并调用逻辑。如果参数(在view action中)是一个简单对象类型,则转换值时会自动转为正确的类型(如从String转到Integer)。如果参数是复杂的对象类型,,则ActionForm 需要通过BeanUtil 来帮忙转成相应的对象。
设定返回的数据 - 如果需要把数据返回显示给用户,那则要把这个数据设在HttpServletRequest 的attribute 中返回。
返回一个 ActionForward - 所有 Struts action的最后都需要找到并返回其相应的 ActionForward 对象.
最后的两个action,remove和list action, 只有很少的差别。remove action如下所示,没有用BlogForm类. 通过从request的attribute中获取"id"(和view action相似),就能调用业务逻辑完成其需要的工作。在下面我们介绍配置时,你可以看到它并没有返回任何数据,因为它的"success"返回结果其实是执行remove后再执行了list action来返回信息的。
public class RemoveBlogEntryAction extends Action {
public ActionForward execute(ActionMapping mapping,
ActionForm form,
HttpServletRequest request,
HttpServletResponse response)
throws Exception {
BlogService service = new BlogService();
String id = request.getParameter("id");
service.delete(Integer.parseInt(id));
return (mapping.findForward("success"));
}
}
list action并不需要任何的用户输入,它只是简单地调用了业务逻辑的无参方法,同时返回所有的Blog对象。
public class ListBlogsAction extends Action {
public ActionForward execute(ActionMapping mapping,
ActionForm form,
HttpServletRequest request,
HttpServletResponse response)
throws Exception {
BlogService service = new BlogService();
request.setAttribute("bloglist",service.list());
return (mapping.findForward("success"));
}
}
相关推荐
Struts 2是一个基于Model-View-Controller (MVC)设计模式的Web应用程序框架,它在Struts 1的基础上进行了重大改进,引入了许多新的特性和功能。本教程旨在帮助已经熟悉Struts 1的开发者理解和迁移至Struts 2。 首先...
Struts2是一个基于MVC(Model-View-Controller)架构模式的Java框架,它极大地简化了Java Servlet的开发,提供了丰富的功能来构建可维护、可扩展的Web应用程序。REST(Representational State Transfer)是一种网络...
Struts2是一个强大的Java web应用程序框架,用于构建和部署企业级的MVC(Model-View-Controller)架构应用。它是Apache软件基金会旗下 Jakarta项目的一部分,是Struts1的升级版本,提供了更丰富的功能和更好的性能。...
Struts2是一个强大的Java web应用程序框架,用于构建和部署可维护、高性能的MVC(Model-View-Controller)架构的应用程序。它是在经典的Struts 1框架基础上发展起来的,旨在提供更优雅、灵活和可扩展的解决方案。...
Struts2是一个强大的Java web应用程序开发框架,由Apache软件基金会维护。它基于MVC(Model-View-Controller)设计模式,旨在简化企业级应用的开发流程。张冰的PPT可能详细介绍了Struts2框架的核心概念和技术,让...
Struts2是一个强大的Java web应用程序开发框架,它基于Model-View-Controller(MVC)设计模式,为开发者提供了构建高效、可扩展且易于维护的Web应用的工具和组件。这个开源代码库对于Java程序员,尤其是那些正在深入...
在"从Struts应用开发框架转移到Struts 2 WEB框架 教程.doc"中,可能详细讲解了以下几个方面: 1. **Struts 2的基础概念**:包括Struts 2的核心组件、配置文件、生命周期等基本知识。 2. **Action类和结果类型**:...
第1章 Struts 2:现代Web框架 2 1.1 Web应用程序:快速学习 2 1.1.1 构建Web应用程序 2 1.1.2 基础技术简介 3 1.1.3 深入研究 6 1.2 Web应用程序框架 7 1.2.1 什么是框架 7 1.2.2 为什么使用框架 8 1.3 Struts 2框架...
Struts2是一个强大的Java web应用程序框架,用于构建和维护可扩展、高效且易于维护的Web应用。这个"struts-2.5.14.1-apps"是Struts2官方提供的示例程序集合,旨在帮助开发者更好地理解和掌握Struts2框架的核心特性...
Struts2是一个基于MVC(Model-View-Controller)设计模式的Java Web应用程序框架,它在Web开发领域具有广泛的应用。Struts2是Struts1的升级版,它弥补了Struts1的一些不足,提供了更强大的功能和更好的性能。本篇...
总结起来,"Struts2 Spring3 JPA RESTful"是一个强大的Java Web开发组合,它利用各框架的优势,构建出高性能、易于维护且具有良好扩展性的Web应用。开发者可以借此快速搭建功能丰富的RESTful服务,满足各种业务需求...
Struts2是一个流行的Java web开发框架,用于构建MVC(模型-视图-控制器)架构的应用程序。在本文中,我们将深入理解Struts2的运行流程,并通过单元测试来验证其完整的工作机制,特别是涉及拦截器、验证框架和Result...
Struts2是一个强大的Java web应用程序框架,它提供了一种组织和构建MVC(模型-视图-控制器)架构的方式。核心拦截器是Struts2框架的重要组成部分,它们允许开发者在动作执行前后插入自定义逻辑,以实现如日志、权限...
Struts2是一个强大的MVC(模型-视图-控制器)框架,它被广泛应用于Java Web开发中,用于构建高效、可扩展的企业级应用程序。在这个项目中,“Struts2结合JSP完成一个ATM系统”,我们将深入探讨如何使用这两个技术来...
Struts2 是一款流行的 Java Web 开发框架,它提供了一系列强大的功能来帮助开发者构建健壮的 Web 应用程序。其中,Struts2 的标签库是其核心特性之一,为开发者提供了丰富的 HTML 和表单元素,以及更高级的动态数据...
在Struts2中,结果类型(Result Type)是动作执行后处理结果的关键部分,它决定了如何将控制权转移给下一个资源,如JSP、FreeMarker模板或者重定向到其他URL。自定义结果类型允许开发者根据项目需求定制化结果处理...
Struts2是一个基于MVC(Model-View-Controller)设计模式的Java Web应用程序框架,它在Web开发领域具有广泛的应用。这个"struts2 jar包"包含了一系列的JAR文件,这些文件是Struts2框架运行所必需的库。下面我们将...
Struts2是一个强大的Java web应用程序框架,用于构建和管理MVC(模型-视图-控制器)架构的应用程序。它是Apache软件基金会的Jakarta项目的一部分,是Struts1的升级版,提供了更高级的功能和更好的性能。 一、Struts...
Struts2是一个强大的MVC框架,它为Java开发者提供了丰富的功能来构建Web应用程序。在Struts2中,UI标签库是其一大特色,它简化了视图层的开发,使得开发者能够更专注于业务逻辑,而不是繁琐的HTML代码。本篇文章将...
Struts2标签库是开发Java Web应用程序时常用的一种工具,它极大地简化了JSP页面的编写,提高了开发效率。在JSP中,我们通常使用`<%@ taglib prefix="s" uri="/struts-tags" %>`来引入Struts2的标签库。下面将详细...