下面这3段话个人看了觉得很精辟,基本可以囊括Struts1的精髓,有兴趣的可以慢慢花时间不断体会:

****************************************************************************************************************

1.      struts到底是什么?

其实说的简单一点struts是一个实现了MVC架构的框架。它无余地的规范了MVC开发的整个过程,换句话说只要使用struts框架进行开发那么一定是遵循MVC架构的,不给你“×××”的机会。

2.      struts是怎样规范MVC架构开发模式的,它的内部执行机制是怎样的?

    (1)      客户端的请求以Http的方式传递到服务器上的,首先会执行规范检测,只要是符合struts规范的请求都会提交到ActionServlet上。

    (2)      ActionServlet所充当的角色可以看成是一个中央控制器,它对客户端的请求进行拦截,然后截取URL,根据URL取得struts-config.xml文件中的配置信息,将配置信息封装到ActionMapping对象中,并将该对象传递给所请求的对象RealAction。

    (3)      根据配置信息实例化相应的ActionForm对象,并将传过来的表单参数进行打包然后赋给ActionForm对象的各个属性。

    (4)      根据配置信息实例化用户所请求的对象RealAction,并将上面接受了表单数据的ActionForm对象传递给请求对象RealAction。该RealAction是继承了struts框架中Action类的对象。它持有一个execute()方法,这个方法是所有继承了Action类的核心方法,所有的业务逻辑控制都是在这个方法中完成的。也就是说在这个方法中我们可以与Model层打交道,实现业务逻辑控制和数据的持久化等操作。

    (5)      Execute()方法执行完毕之前会将执行的结果以ActionForward对象的形式返回给ActionServlet,这个返回结果是根据传递过来的ActionMapping中的forward标签决定页面跳转的。ActionServlet接收到新的跳转请求的时候再次重复这个过程直到将目的界面返回给用户。

3.   使用struts和不是用struts的区别是什么?

    (1)      采用struts框架实现servlet的统一控制。传统的servlet开发中每写一个servlet都要在配置文件中,这就导致了当servlet很多的时候我们所看到的配置文件凌乱不堪。难于管理。采用struts框架,所有符合规范的请求将会统一交给ActionServlet进行处理,在struts-config.xml文件中根据配置决定由那个RealAction进行处理。

    (2)      在传统的servlet开发中,当处理完业务逻辑后具体的页面跳转是由每个servlet自己决定的,也就是说几乎每个servlet都有一条页面跳转代码,这样的话如果有N个servlet需要跳转到同一个页面,那相同的跳转语句需要重复写N次,更为重要的是如果后期需求变更,需要跳转到新的页面那么需要改动的代码也就有N次。采用struts框架能够解决这个问题,我们所需要做的仅仅是把跳转页置到<forward>标签中,需求变更的话只需改变配置文件即可。

    (3)      数据采集。Servlet开发中数据的采集是servlet接收到request,采用getParameter()方法取得表单数据,并且不能实现格式的自动转换。如果采用struts框架,定义好ActionForm后,ActionServlet会自动将表单数据加载到相应的ActionForm中并且实现数据类型的自动转换。

说了这么多,那struts到底该怎样用呢?下面我们来介绍struts框架的搭建并通过一个简单的登录实例讲解struts的应用。

***************************************************************************************************************


一个Struts的基本流程,工作机制:

1. 当Tomcat启动的时候根据配置文件中的<loadon-on-startup>标签中的值,ActionServlet伴随着Tomcat的启动而被实例化。

2. ActionServlet被实例化后会加载struts-config.xml文件,将该文件中的配置信息以键值对的形式读到内存中

3. 当login页面被提交的时候由于该页面的action结尾是以.do结束的(也就说它符合在web.xml文件中规定的受struts规范的条件,该条件简单的来说就是只要请求是以.do结尾的就都受struts约束),该请求会被提交到ActionServlet。

4. 请求被提交到ActionServlet后,ActionServlet会首先对该URL进行截取(将.do去掉),然后根据截取后的path在已经加载到内存中的struts-config.xml找到对应的path,同时实例化配置文件中配置好的具体的ActionForm对象和RealAction对象,同时将表单信息赋给ActionForm对象

5.根据配置文件中的type属性找到真正的请求类LoginAction后,由该类完成业务逻辑的各种操作,最后返回ActionForward对象给ActionServlet,最后ActionServlet根据返回情况从struts-config.xml文件中找到对应的跳转页面实现页面导航的统一控制。


************************************************************************************************************

Struts关于单例多线程的问题:

在使用Struts1.XStruts2.X的时候我们会发现一个很明显的问题:

Action的单实例问题:Struts1.X中的Action都是Singleton的,但是Struts2.X中,Action却全是Prototype的;尤其是我们配置SSH三层架构的时候,让Spring来管理Struts的Action,如果使用Struts2,默认都要为每个Action的Bean添加prototype="true"这个属性,不然,当操作一个对象时候,无论你是删除还是修改一个对象,始终会出现最后一次访问的记录;

为什么Struts2会采用Prototype模式而不是单实例的模式呢?

       首先,单实例的模式最主要的一个问题就是线程同步问题,如果处理不好程序会有严重的bug,Servlet就是一个例子,它同样是采用单实例多线程的模式,如果多线程中同时访问一个共享的数据,没有加同步锁(synchronized),可能会出现数据错误。

这就找到了单实例引线程安全问题的原因:单实例是否能够被状态化,通俗一点说,就是单实例类中是否可以有成员变量,有成员变量的就是状态,无成员变量就是无状态;

       状态化的单实例适用的场合是作为一个状态窗户对外提供服务;比如,论坛帖子的计数器,用户浏览一次,就synchronized的加1;

       无状态的单实例适用的场合就是工具性质的功能,常用的Servlet就属于此类,每次来个请求,都始终是一个Servlet实例在工作;(所有Servlet是不建议在它里面定义成员变量的,就是有也必须synchronized处理);


我们知道:

Struts1.X中Action从页面获得数据是从FormBean获得的,它不需要定义成员变量获取页面数据,所有它是无状态的,采用的是单实例模式,而且线程安全的;


Struts2.X采用值绑定模式,在Action页面定义了成员变量与页面的标签name绑定,一次获取页面数据,它是有状态的,很容易出现线程安全问题,如果单纯用synchronized处理,并发访问肯定出问题,所有它采用了prototype模式,就是非单实例的模式,线程不安全;

有人担心Struts2每次都创建Action会有性能问题。


对上述内容进行补充说明:

struts2本身就是多实例单线程的,所以可以说 本身就是线程安全的。
struts1则是单实例多线程的,所以必须要注意线程的安全性。

所以相对来说,struts1 要多使用局部变量,而struts2使用 实例变量则不会产生不安全的结果

总的来说,Struts1 的 Action 是单例模式,因此开发者必须保证它是线程安全的或是同步的,因为Struts 1中每个Action仅有一个实例来处理所有的请求。


   但是在用Struts 1开发时并没有考虑到线程安全问题,这是因为我们在Action中使用的基本都是局部变量,而“局部变量是线程安全的。因为每执行一个方法,都会在独立的空间创建局部变量,它不是共享的资源。局部变量包括方法的参数变量”(忘了引自哪了)。在Struts 1中,所有的变量都是定义在Action中我们要执行的方法里的(Action中的execute方法或DispatchAction中指定要执行的方法),我们用于封装客户端请求参数的ActionForm,也是作为一个参数传入,也属于局部变量,因此,不存在线程安全问题。

 Struts 2 的 Action 对象为每一个请求产生一个实例,因此,虽然在Action中定义了很多全局变量,也不存在线程安全问题。

Struts 2框架在处理每一个用户请求的时候,都建立一个单独的线程进行处理,值栈ValueStack也是伴随着局部线程而存在的。在该线程存在过程中,可以随意访问值栈,这就保证了值栈的安全性。


在Struts 2中,ActionContext是一个局部线程,这就意味着每个线程中的ActionContext内容都是唯一的。所以开发者不用担心Action的线程安全。

********************************************************************************************************************************