Struts2继承了Struts与WebWork的血脉,吸取了两者的精华而成。
不同点主要包括以下几个方面:
Action类
在Struts中都是使用抽象类编程而不是接口,因此它要求开发的Action类继承一个抽象基类,如DispatchAction等。
Struts2刚基于接口编程,我们的Action类可以实现一个Action接口,也可实现其他接口,使可选和定制的服务成为可能。Struts2提供一个ActionSupport基类去实现常用的接口。更强大的是,在Struts2中Action接口不是必需的,任何有execute()函数的POJO对象都可以用做Strut2的Action类来使用。
线程模式
Struts的Action是单例模式并且必须是线程安全的,因为仅有Action的一个实例来处理所有的请求。单例策略限制了Struts Action所能做的事,并且要在开发时特别小心,Action资源必须是线程安全的或同步的
Struts2的Action对象为每一个请求产生一个实例,因此没有线程安全问题。
Servlet依赖
Struts的Action依赖于Servlet API, 当一个Action被调用时,HttpServletRequest和HttpServletResponse被传递给执行的方法,例如:
Public ActionForward execute(ActionMapping mapping, ActionForm form,HttpServletRequest request,HttpServletResponse response){
}
|
Struts2的Action不依赖容器,允许Action脱离容器单独测试。如果需要,Struts2的Action仍然可以访问初始的request和response。例如下面的这个类MyAction.java,它可以通过ActionContext对象取得Session值,也可以通过ServletActionContext对象取得request值。
Public class MyAction{
Protected Object getSession(String key){
Return ActionContext.getContext().getSession(key);
}
Protected HttpServletRequest getRequest(){
Return (String)ServletActionContext.getRequest();
}
}
|
可测试性
测试Strtus Action的一个主要问题是,execute()方法暴露了Servlet API,这使得测试要依赖于容器。虽然有第三方的软件Struts TestCase能够使用模拟对象来进行测试,但显然会让我们的测试变得更加复杂。
Struts2 Action的类是POJO类,因此可以直接编写测试类来测试Action类,只需要在测试类中为Action注入属性即可。
捕获输入
Struts使用ActionForm对象捕获用户输入,所有的ActionForm必须继承一个基类ActionForm。因为其他的JavaBean不能用做ActionForm,开发者经常创建多余的类捕获输入。动态表单可以作为创建传统ActionForm的选择,但是,开发者可能是在重新创建已经存在的JavaBean,仍然会导致有冗余的JavaBean。
Struts2直接使用Action属性作为输入属性,消除了对第2个输入对象的需求。输入属性可能是有自己子属性的rich对象类型。Action属性能够通过Web页面上的taglibs访问。同时,Struts2也支持ActionForm模式。
表达式语言
Struts整合了JSTL,这种EL有基本对象图遍历,但是对集合和索引属性的支持很弱。
Struts2可以使用JSTL,但是也支持一个形影相随强大和灵活的表达式语言OGNL(Object Graph Notation Language)。
绑定值到页面
Struts使用标准JSP机制把对象绑定到页面中来访问。
Struts2使用ValueStack策略允许通过一系列名称相同,但类型不同的属性重用页面(View)。
类型转换
Struts的ActionForm属性通常都是String类型,并使用Commons-Beanutils进行类型转换。每个类提供一个转换器,对每一个实例来说是不可配置的。
Struts2使用OGNL进行类型转换,提供了基本和常用对象的转换器。
数据校验
Struts的ActionForm属性的validate()方法中手动校验,或者通过Commons Validator的扩展来校验。同一个类可以有不同的校验内容,但不能校验子对象。
Struts2支持通过validate()方法和XWork校验框架来进行校验,XWork校验框架使用为属性类类型定义的校验和内容校验,来支持chain校验子属性。
Action执行的控制
Struts支持每一个模块有单独的Request Processors(生命周期),但是模块中的所有Action必须共享相同的生命周期。
Struts2支持通过拦截器堆栈(Interceptor Stacks)为每一个Action创建不同的生命周期,堆栈能够根据需要和不同的Action一起使用。
以上描述的都是内部实现机制的不同,从开发者的角度来看,其实主要是Action类不同。
在Struts2中共包含两个配置文件:
Struts.properties:定义了Struts2运行的属性配置,通过修改这些属性可以控制Struts2的行为。
Struts.xml:供开发者添加用户请求的映射列表,通过该列表可以将用户的请求与Action类对应起来。(还可以在struts.xml文件中引用别的XML文件,如user.xml,可以在struts.xml文件中使用<include>来引用)
Struts2的请求是由FilterDispatcher来进行拦截的,当接收到用户的请求时,它会在struts.xml中查找对应的请求映射配置,得到使用哪些拦截器Interceptors、 Action类和返回结果Results的信息,然后依次做如下的操作:
1, 请求通过一系列的拦截器:Interceptors是Struts2中的一种过滤机制,它基于AOP的思想进行设计,通常可以用于日志记录、权限限制等;拦截器和拦截器组可以按照不同级别进行组合配置来处理请求。它们为请求提供各种预处理和切面处理的应用功能,这和Struts的使用Jakarta Commons Chain构件的RequestProcessor类很类似。
2, 调用Action:产生一个新的Action对象实例,并提供请求所调用的处理逻辑的方法,并调用Model层执行业务逻辑的操作,然后返回映射配置中指定的Result页面。
3, 业务处理:业务逻辑通常由JavaBean或EJB组件来实现,以实现文件、数据库、通信等的相关操作。
4, 调用相应的Result:通过匹配处理Action方法之后的返回值获取相应Result类,生成并调用它的实例。处理Result可能产生的结果之一就是对UI模板(但并非只有一个)进行渲染,来产生HTML。如果是这种情况的话,模板中的Struts2 tags可以直接从Action中获取要被渲染的值。
5, 响应被返回给用户:最后一步是将控制权交还给Servlet引擎。最常见的结果是把渲染后的HTML返回给用户,但返回的也可能是指定的HTTP头或者进行HTTP重写向。你应该已经注意到Struts2和Struts的差别了,最明显的就是Struts2是一个pull-MVC架构。这是什么意思呢?从开发者的角度看,就是说需要显示给用户的数据可以直接从Action中获取,也就是说JSP页面可能直接访问Action中的数据了,而不像Struts那样必须把相应的Bean存到Page、Request、或者Session中才能获取。
Com.opensymphony.xwork2.Action是个接口,这个类来自于XWork,它的定义如下:
package com.opensymphony.xwork2;
public interface action{
public static final java.lang.String SUCCESS = “success”;
public static final java.lang.String NONE = “none”;
public static final java.lang.String ERROR = “error”;
public static final java.lang.String INPUT = “input”;
public static final java.lang.String LOGIN = “login”;
public abstract java.lang.String execute() throws java.lang.Exception;
}
|
Execute()方法是每个Action的入口方法
Struts.xml文件中,首先是Action的访问地址,它的访问地址由两个部分来决定,一个是package中的namespace定义,一个是action的name.
属性
|
必需
|
说明
|
Name
|
是
|
供其它包引用的包名
|
Extends
|
否
|
继承自其它包并获得其全部行为
|
Namespace
|
否
|
参考正文的命名空间介绍
|
Abstract
|
否
|
声明包为抽象(包内不需要配置action)
|
Package元素只需要一个必须的属性:name。extends属性是可选的,它可以让当前包继承一个或者多个以前包——包括所有的拦截器,拦截器栈,以及action配置。只有namespace属性对我们的action的访问路径有影响的,它的默认值是“”,也就是空字符串,它还可以聚会为根目录,也就 是“/”,被称为Root Namespace,它对应着访问web应用根目录的情况。如果当前例子的配置文件的package 为:
重新发布项目后,访问路径将是:
http://localhost:8080/struts2hello/test/HelloWorld.action
接下来对访问路径有影响的,当然是Action 的 name 属性了,假设这样写
这时候的访问路径将会变成
http://localhost:8080/struts2hello/test/a.HelloWorld.action
不赞成在action的name属性中加符号如:“.”,”-“主要是ajax支持会出问题。
Result:
<package name=”default” extends=”struts-default”namespace=”/test”>
|
<action name=”a.HelloWorld” class=”com.login.action.HelloWorld”>
|
它相当于JSP编程当中的forward,因此,默认的type类型就是dispatcher
可以这样写
<result-types>
<result-type class=”org.apache.struts2.dispatcher.ServletDispatcherResult” default=”true”/>
</result-types>
|
Param元素可以省略掉。
还有一种结果类型,那就是重定向,它的写法是:
<result type=”redirect-action”>Menu</result>
类似于struts1中的GlobalFowards,struts2也支持将某些通用的Result定义成为全局的,即Global Results:
<result name=”success” type=”dispatcher”>
<param name=”location”>/HelloWorld.jsp</param>
</result>
|
强烈建议能用EL表达式和JSTL表达式的时候就用它,而抛弃框架自带的那些非标准和容易变动的自定义标签库。这就是一直提倡的面向标准和尽量独立于框架编程的好处,可维护性和移植性是远远好于绑定某个特定标签库的,开发不能只看眼前,要尽量多考虑以后的扩展和维护。
· Struts2的国际化问题:
比如说在SRC的com.login.action包上右击新建一个文件名为package.properties,接着在打开的编辑器中键入以下内容
HelloWorld.message = Struts 2 is up and running…
Package.properties是默认的,一般情况下得有,如果想在中文浏览器里面显示的话,就需要建立一个package_zh_CN.properties文件了,这个properties文件就像struts1那样差不多,在native2ascii里面先转换然后,再粘贴就OK。
Struts2对开发人员提供了很大的方便,既不用关心Struts2自身的接口和类,也不用关心方法到底应该如何命名,还可以将功能相似的方法合并到一个Action中,例如,将用户管理的功能都写到一个UserAction中, 里面带有login,logout,add,delete等处个模块的方法,而配置的时候只要按需要根据method参数即可配置出对应的5个访问地址,分别对应这些方法的调用。5个页面都对应着结果页面success.jsp。
映射还可以使用通配符的方式如:
<global-results>
<result name=”error”>/Error.jsp</result>
<result name=”invalid.token”>/Error.jsp</result>
</global-results>
|
当访问地址”saveUser”的时候,将会调用com.login.action.ActionMethod Action类的某个实例上的save方法,后面的method=”{1}”这个定义的值{1}等于用户输入的*,即{1}=*
Struts2的验证机制:
和struts1相比,这里的验证工作相当的简单,首先,是表单提交的action后台所对应的类必须继承自ActionSupport类,只有这样才能使用Struts2自带的验证机制。其次,必须使用Struts2里面的form标签来定义表单。再次,action定义中必须有名为input的result来指定表单的来源页面,便于出错后返回表单输入页面显示相关的信息,如:
<result name=”input”>/login.jsp</result>
最后是需要编写一份针对表单域的验证说明文件,并放在和action类相同的包下。配置文件有两种命名约定方式:
1. Action类名-validation.xml,不是Action名字_validation.xml,放在和Acton类相同的包下。例如在这里我们的验证文件名可以为:Login-validation.xml。
2. Action类名-Action别名-validation.xml,如Login-Login-validation.xml。
Interceprors(拦截器)
Struts2 中提供的很多特性都是通过拦截器实现的,例如异常处理,文件上传,生命周期回调与验证。拦截器从概念上来讲和Servlet过滤器或者JDK的Proxy类是一样的。它提供了一种对Action进行预处理和事后处理的功能。
依赖注入可以有多种不同的实现方式:
Spring框架——ActionAutowiringInterceptor拦截器
请求字符串和表单值——ParametersInterceptor拦截器
基于Servlet的对象——ServletConfigInterceptor拦截器
如果要想在Action中激活依赖注入功能,就必须要对Action进行配置。
<action name=”*User” class=”com.login.action.ActionMethod” method=”{1}”
<result>/hello.jsp</result>
</action>
|
在action配置 中就应该这样来写,把它配置上
<interceptors>
…
<interceptor name=”autowiring” class=
”…xwork2.spring.interceptor.ActionAutowiringInterceptor”/>
</interceptors>
|
也可以直接放在package中
<default-interceptor-ref name=”autowiring”/>
由于Struts2的很多功能是基于拦截器完成的,所以一个Action对应有7,8个拦截器也并不稀奇,因此我们一般都用拦截器栈(interceptor stack)来管理拦截器。
OGNL的全称是Object Graph Navigational Language(对象图导航语言),提供了访问值栈中对象的统一方式。
值栈中的对象构成及基排列顺序
1. 临时对象——在执行过程中,临时对象被创建出来并放到了值栈中。
2. 模型对象——如果模型对象正在使用,那么会放在值栈中action的上面
3. Action对象——正在被执行的action
4. 固定名称的对象(Named Objects)——这些对象包括有#application,#session,#request,#attr和#parameters,以及相应的servlet作用域
在OGNL里面,可以用“.”来遍历对象图(比如说,使用”person.address”而不是“
getPerson().getAddress()”),还有类型转换,方法调用,集合的操作与生成,集合间的映射,表达式运算和lambda表达式。
<!--EndFragment-->
分享到:
相关推荐
### Struts1与Struts2的主要区别 #### 概述 Apache Struts 是一个用于构建企业级Java Web应用的开源框架。它分为两个版本:Struts1 和 Struts2。虽然两者都基于模型-视图-控制器(MVC)设计模式,但它们之间存在...
Struts2 和 Struts1 是两个著名的 Java Web 开发框架,它们都出自 Apache Software Foundation,但有着显著的区别。Struts1 是早期的 MVC 框架,而 Struts2 则是在 WebWork 框架的基础上发展起来的,它吸收了 Struts...
### Struts1与Struts2的主要区别 #### 1. Action类的设计差异 - **Struts1**: 在Struts1框架中,Action类必须继承自一个抽象类`org.apache.struts.action.Action`。这种方式可能导致的问题是代码灵活性较低,尤其...
### Struts1与Struts2本质区别 #### 1. 在Action实现类方面的对比 - **Struts 1**:要求Action类必须继承一个抽象基类`Action`,这种设计方式意味着开发者必须按照预设的结构来编写代码,灵活性较低。这种通过抽象...
### Struts1与Struts2原理及区别详解 #### Struts1原理概述 **Struts1** 是一种基于MVC架构的开源Java Web框架,它主要用于构建动态网站和应用程序。Struts1的核心组件包括ActionServlet、ActionForm以及Action...
下面我们将深入探讨Struts1和Struts2的区别。 1. 设计模式: - **Struts1**:基于Front Controller模式,只有一个Servlet(ActionServlet)处理所有请求。它使用Plug-In和Dispatcher机制来实现业务逻辑和视图的...
### Struts2 与 Struts1 的核心区别 #### 一、架构设计及Action实现方式 **Struts1** 在架构上要求Action类必须继承一个特定的抽象基类,这限制了开发者的灵活性,同时也意味着所有的Action都需要遵循相同的生命...
### Struts1与Struts2的主要区别 #### 一、Action执行机制的不同 - **Struts1**: 在Struts1框架中,Action是基于单例模式的,这意味着所有的请求都会共享同一个Action实例。这就导致了如果在Action中保存实例变量...
Struts1和Struts2是两个非常著名的Java Web框架,它们在处理MVC(Model-View-Controller)架构方面有着显著的区别。以下是关于这两个框架在关键特性上的对比: 1. **Action类**: - **Struts1**:要求Action类继承...
### Struts2与Struts1的主要区别 #### Struts2架构设计与实现方式 - **Struts2**在设计上采用了更加灵活的方式,每个请求都对应一个实例化的Action对象,而不是像**Struts1**那样在整个请求周期内共享同一个Action...
而Struts2则是在Struts1的基础上进行了全面改进,采用了拦截器(Interceptor)机制,使得处理请求的方式更加灵活和模块化。 **2. 拦截器:** Struts2的核心就是拦截器,它们是基于责任链模式实现的,可以进行一系列...
视图层的绑定方面,Struts1依赖标准JSP机制,而Struts2引入了ValueStack技术,使得taglib可以直接访问值栈中的对象,无需在视图层与对象进行一对一绑定,提高了代码的复用性。 类型转换上,Struts1使用Apache ...
在探讨Struts2与Struts1的区别时,我们需深入理解这两个框架的设计理念、架构模式以及它们在实际应用中的表现差异。以下将从多个角度详细分析这两种流行Java Web框架的不同之处。 ### 1. **Action类的区别** #### ...
### Struts1与Struts2的区别与对比 #### 概述 Struts1与Struts2是基于Java的两种流行的Web应用框架,它们都遵循MVC(Model-View-Controller)设计模式,用于构建结构化的Web应用程序。Struts1是早期版本,在2000...
### Struts1与Struts2的本质区别 #### 一、Action实现类的对比 - **Struts1**:要求Action类必须继承一个抽象基类,这意味着开发者必须遵守框架提供的特定结构,这在一定程度上限制了灵活性。此外,由于依赖于抽象...
Struts1.x与Struts2.x是两种非常流行的Java Web应用程序框架,它们都由Apache软件基金会开发,旨在简化MVC(Model-View-Controller)架构的实现。然而,两者在设计哲学、功能特性以及实现方式上存在显著差异。以下是...
### Struts1.x与Struts2.x的主要区别 在深入探讨Struts1.x与Struts2.x的区别之前,我们先来了解一下这两个框架的基本背景。Apache Struts是用于构建企业级Web应用程序的开源框架,它提供了MVC(模型-视图-控制器)...
【Struts1与Struts2的区别】 Struts2框架并非完全独立的新框架,而是基于WebWork框架进行发展的。WebWork的稳定性和性能为Struts2提供了坚实的基础,使其成为一个融合了Struts1和WebWork优势的强大力量。在设计上,...