Struts1和Struts2的比较

特征 Struts 1 Struts 2
Action类 Struts1的action需要去继承一个抽象基类。一个普遍问题就是Struts1是面向抽象类编程来代替接口编程 Struts2的action可以实现一个Action接口,也可以同时实现一些其他的接口来添置一些附加的,常用的服务。Struts2提供一个基类ActionSupport实现了一些常用的接口。虽然Action接口不是必须的。任何附带execute方法的POJO对象都可以作为Struts2的action对象。
 线程模型 Struts1的action是单例的而且必须是线程安全的,因为该类会只有唯一一个引用来为action处理所有的请求。单例策略会限制Struts1的action的功能以及需要扩展的额外的功能(The singleton strategy places restrictions on what can be done with Struts 1 Actions and requires extra care to develop)。Struts1的action必须是线程安全的并且是同步的。  Struts2的Action对象是针对每一个请求的,所以自然也就不存在线程安全问题了。(实际上,)
Servlet的依赖  Struts1的Action依赖于Servlet API,因为当Action被调用的时候HttpServletRequest和HttpServletResponse对象是通过execute方法进行处理的。 Struts2的Action和容器的连接并不紧密。通常servlet上下文被描绘成简单的Map映射,允许Action被单独测试。当然,如果需要的话Struts2的Action也可以通过访问初始的request和response来完成一些功能。然而,其他的一些架构元素导致降低或者删除了直接访问request和response的需求。
易测试性 测试Struts1的Action有一个大障碍就是execute方法是直接暴露于servlet API的。 Struts2的Action可以很容易的通过设置属性调用方法来进行测试。当然依赖注入的支持也使得测试变得简单。
输入处理 Struts1使用一个ActionForm对象来获取用户的输入。和action一样,所有的ActionForm都必须继承自一个基类。因为其他的javaBean不能被用作ActionForm,开发者通常要写一些多余的类来获取用户输入。DynaBean可以被用做生成ActionForm类的一个选择,但是开发者需要对现有的javaBean进行重写。 Struts2使用Action属性作为输入属性,除掉了对于输入对象的需求。输入属性可以是一个拥有他自己的属性的对象。Action属性是通过标签和web页面交互。Struts2也支持ActionForm模型,就是POJO的Form对象和POJO的Action。多数的对象类型,包括商业逻辑对象和领域对象都可以作为输入/输入对象。模式驱动特征简化了标签和POJO输入对象的关系。
表达式语言 Struts1和JSTL结合,所以他可以使用JSTL的EL。 Struts2也支持JSTL,但是这个框架也支持更加强大的表达式语言OGNL.
表现层和类型值的绑定 Struts1使用标准的JSP机制将对象绑定到page context来进行访问。 Struts2使用”ValueStack”技术,所以标签不用将视图和表现的对象结合就可以得到值.ValueStack策略允许通过一系列可能具有相同属性名字但是不同属性类型的的类型来完成视图的重用,
类型转换 Struts1的ActionForm通常都是String类型。Struts1通过Commons-Beanutils实现类型转换。 Struts2使用OGNL实现类型转换,框架包含了对基础和公共类型的转换器。
验证  Struts1支持通过ActionForm中的validate方法实现手工验证。也可以通过扩展通用的验证框架进行验证。对于同一个类可以有不同的验证,但是不能关联到子对象的验证。 Struts2也支持通过validate方法进行手工验证以及Xwork验证框架进行验证。Xwork验证框架支持将验证链接到子属性,子属性使用了为属性类型和验证上下文定义的验证。
 Action执行的控制 Struts1支持为每一个模块分配请求处理(生命周期),但是一个模块中的所有Action必须分享相同的生命周期。 Struts2支持通过拦截器栈为每个Action创建不同的生命周期。通常对于不同的Action根据需要都要有对应的栈被创建和使用。
     
     

 

Struts2Struts1在使用上的差异:

1、Action的编写无需继承特殊的基类

2、取消了ActionForm,页面参数被直接设置到Action对象的属性上

3、每个请求都会创建一个Action的对象

4、Action的方法可以不依赖于任何Servlet API

Struts2Struts1在设计上的主要差别在于: 

 1、Struts2中的请求处理过程由拦截器模式定义为一个可插拔的、容易扩展的结构,而不是像Struts1

   中,其处理过程是固定不变的

2、Struts2中的参数从页面传递到Action,以及将数据从Action传输到页面,都通过OGNL来进行,

   Struts1中的参数从页面传输到Action是通过Apache-commons-beanutils工具包来解析的,而

   将数据从Action传输到页面则通过request对象来传输

Struts的Token(令牌)机制解决表单重复提交

Struts的Token(令牌)机制能够很好的解决表单重复提交的问题,基本原理是:服务器端在处理到达的请求之前,会将请求中包含的令牌值与保存在当前用户会话中的令牌值进行比较,看是否匹配。在处理完该请求后,且在答复发送给客户端之前,将会产生一个新的令牌,该令牌除传给客户端以外,也会将用户会话中保存的旧的令牌进行替换。这样如果用户回退到刚才的提交页面并再次提交的话,客户端传过来的令牌就和服务器端的令牌不一致,从而有效地防止了重复提交的发生。

这时其实也就是两点,第一:你需要在请求中有这个令牌值,请求中的令牌值如何保存,其实就和我们平时在页面中保存一些信息是一样的,通过隐藏字段来保存,保存的形式如: 〈input type=”hidden” name=”org.apache.struts.taglib.html.TOKEN” value=”6aa35341f25184fd996c4c918255c3ae”〉,这个value是TokenProcessor类中的 generateToken()获得的,是根据当前用户的session id和当前时间的long值来计算的。第二:在客户端提交后,我们要根据判断在请求中包含的值是否和服务器的令牌一致,因为服务器每次提交都会生成新的 Token,所以,如果是重复提交,客户端的Token值和服务器端的Token值就会不一致。下面就以在数据库中插入一条数据来说明如何防止重复提交。

在Action中的add方法中,我们需要将Token值明确的要求保存在页面中,只需增加一条语句:saveToken(request);,如下所示:
public ActionForward add(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response)
//前面的处理省略
saveToken(request);
return mapping.findForward(“add”);
}
在Action的insert方法中,我们根据表单中的Token值与服务器端的Token值比较,如下所示:
public ActionForward insert(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response)
if (isTokenValid(request, true)) {
// 表单不是重复提交
//这里是保存数据的代码
} else {
//表单重复提交
saveToken(request);
//其它的处理代码
}
}

其实使用起来很简单,举个最简单、最需要使用这个的例子:
一般控制重复提交主要是用在对数据库操作的控制上,比如插入、更新、删除等,由于更新、删除一般都是通过id来操作(例如:updateXXXById, removeXXXById),所以这类操作控制的意义不是很大(不排除个别现象),重复提交的控制也就主要是在插入时的控制了。

[ad#468*60-w1]

字体大小: 减小一号 减小一号
▲ Back to top 繁體