Action类(org.apache.struts.action.Action)是Struts架构中控制器组件的重要组成部分,它是用户请求和业务逻辑之间沟通的媒介。每个Action类型的对象实际上都在充当客户的业务代理。它就像政府部门接待群众来访的接待室工作人员,负责倾听群众的要求,然后按照要求的不同,调用不同的业务逻辑处理方法进行处理,即转达给对应的部门进行处理。
在Struts设计架构中,人们通常在处理器Action类的excute()方法中添加下属处理逻辑:
(1)用户进行身份验证
对用户的身份验证一般分两种情形:用户登录时的验证和中间验证。
中间验证的目的是为了防止未注册的用户绕开登录页面(通过直接访问中间页面的方式)进入应用程序,或者session超时失效后用户有继续操作。这种情况一般可以通过检验session状态来实现。有关这部分控制逻辑将在后续中具体实现。
(2)调用其它的业务逻辑Bean
虽然从语法上讲,可以将所有的业务逻辑都直接封装在处理器Action类中,但这并不是推荐的做法。通常应该将商务逻辑封装到独立的业务逻辑Bean中,再通过调用Action的excute()方法进行调用。
(3)
新服务器端对象状态
这里的服务器端对象通常指那些request范围或session 范围的Bean,在Servlet中对应的则是Request或Session对象的属性,它们一般会在后续页面中被用来创建用户界面。如:
request.setAttribute("username",userform.getUsername()); 或
session.setAttribute("username",userform.getUsername());
(4)返回ActionForward对象,用于标识要转向到的下一个目标页面。
如何设计好的Action?
在设计处理器Action类时要注意以下几点:
(1)首先,RequestProcessor对象对于每种Action类型只创建一个实例,该实例将被用于所有匹配的请求,这就需要定义Action类考虑如何使之能够在一个多线程环境中正常运行。(也正是由于使用多线程Servlet容器可以同时接受多个客户请求,而不是传统的多进程,另外,这样有利于代码重用。)和过去定义Servlet类的doPost()/doGet()方法类似,为实现这种线程安全,一个重要的原则是在Action类中尽量只使用局部变量而不是实例变量。局部变量的作用域被限定在所在的方法,其生存期只限于所在方法的一次运行期间,不存在被多个请求处理线程共享的问题。
(2)虽然org.apache.struts.action.Action类的excute()方法原型中允许抛出Exception,但应尽量在Action类中加入处理逻辑,在方法内部捕获和处理可能抛出的违例,而不是简单将之抛出。
(3)应该在控制其将请求重定向到其它页面前,释放action组件所占用的资源(如数据库联接),包括在调用其它业务逻辑Bean的功能方法出错、抛出违例时。
(4)要避免出现非常大的Action类,虽然表面看来将商业逻辑功能也嵌入到Action类本身实现起来最简单,但这会导致使Action类的可读性和可维护性变差。由于这些商业逻辑代码被嵌入于只能运行在Web应用程序环境的组件中,因此很难有重用的可能。
综上所述,Action通常负责将客户端请求映射到处理这些请求的业务逻辑Bean,再转向生成响应回送给客户端的页面,实际上起到的是 Controller和Model之间的“适配器”的作用,属于一种低层面的控制器。