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的区别struts1和struts2的区别struts1和struts2的区别struts1和struts2的区别struts1和struts2的区别struts1和struts2的区别struts1和struts2的区别struts1和struts2的区别struts1和struts2的区别...
2 线程模式方面的对比:Struts 1 Action是单例模式并且必须是线程安全的,因为仅有Action的一个实例来处理所有的请求。单例策略限制了Struts 1 Action能做的事,并且要在开发时特别小心。Action资源必须是线程安全的...
struts2 与 struts1的区别
struts1 struts2 Struts1和Struts2区别
Struts1与Struts2原理 区别详解汇总
struts1与struts2的区别,线程模式,servlet的依赖...
Apache Struts 2即是之前大家所熟知的WebWork 2。在经历了几年的各自发展后,WebWork和Struts社区决定合二为一,也即是Struts 2 Struts 2 英文学习网站:hthttp://struts.apache.org/2.1.6/index.html
Struts2和Struts1的区别,详细点,主要说说Struts2
Struts2和Struts1的什么区别
Struts1和Struts2的区别和对比,从各个方面对 Struts1和Struts2进行了详细的介绍及比较
struts1和struts2的区别(详细).txt
struts与struts2的区别..
struts1.0与struts2.的区别 struts1.0与struts2.的区别 struts1.0与struts2.的区别
Struts1和Struts2的区别和对比.txt
Struts2和Struts1的常见区别 二. Struts2入门 3. 快速配置Struts2环境 4. 开发一个Struts2简单实例 5. struts.xml文件 三. Struts2深入开发 6. 常用标签配置和使用 7. 常用标签配置和使用 8. 标签 ...
struts1.x和struts2.x区别
struts2是WebWork2的基础上进行开发的,struts2.0其实就是WebWork2.3,它和struts1并无关系。