Struts1.1应用初步
来源:互联网 发布:手机屏幕画笔软件 编辑:程序博客网 时间:2024/06/08 13:44
转至:http://cping1982.blog.51cto.com/601635/129813/
Struts 是基于Model 2之上的,而Model 2是经典的MVC(模型-视图-控制器)模型的Web应用变体,这个改变主要是由于网络应用的特性--HTTP协议的无状态性引起的。Model 2的目的和MVC一样,也是利用控制器来分离模型和视图,达到一种层间松散耦合的效果,提高系统灵活性、复用性和可维护性。在多数情况下,你可以将 Model 2与MVC等同起来。下图表示一个基于Java技术的典型网络应用,从中可以看出Model 2中的各个部分是如何对应于Java中各种现有技术的。 在利用Model 2之前,我们是把所有的表示逻辑和业务逻辑都集中在一起(比如大杂烩似的JSP),有时也称这种应用模式为Model 1,Model 1的主要缺点就是紧耦合,复用性差以及维护成本高。Struts 1.1 和Model 2既然Struts 1.1是基于Model 2之上,那它的底层机制也就是MVC,下面是Struts 1.1中的MVC实现示意图: 图解说明:其中不同颜色代表MVC的不同部分:红色(控制器)、紫色(模型)和绿色(视图) 首先,控制器(ActionServlet)进行初始化工作,读取配置文件(struts- config.xml),为不同的Struts模块初始化相应的ModuleConfig对象。比如配置文件中的Action映射定义都保存在 ActionConfig集合中。相应地有ControlConfig集合、FormBeanConfig集合、ForwardConfig集合和 MessageResourcesConfig集合等。提示:模 块是在Struts 1.1中新提出的概念,在稍后的内容中我们将详细介绍,你现在可以简单地把模块看作是一个子系统,它们共同组成整个应用,同时又各自独立。Struts 1.1中所有的处理都是在特定模块环境中进行的。模块的提出主要是为了解决Struts 1.0中单配置文件的问题。 控制器接收HTTP请求,并从ActionConfig中找出对应于该请求的Action子类,如果没有对应的Action,控制器直接将请求转发给JSP或者静态页面。否则控制器将请求分发至具体Action类进行处理。在 控制器调用具体Action的execute方法之前,ActionForm对象将利用HTTP请求中的参数来填充自己(可选步骤,需要在配置文件中指 定)。具体的ActionForm对象应该是ActionForm的子类对象,它其实就是一个JavaBean。此外,还可以在ActionForm类中 调用validate方法来检查请求参数的合法性,并且可以返回一个包含所有错误信息的ActionErrors对象。如果执行成功, ActionForm自动将这些参数信息以JavaBean(一般称之为form bean)的方式保存在Servlet Context中,这样它们就可以被其它Action对象或者JSP调用。Struts将这些ActionForm的配置信息都放在FormBeanConfig集合中,通过它们Struts能够知道针对某个客户请求是否需要创建相应的ActionForm实例。Action 很简单,一般只包含一个execute方法,它负责执行相应的业务逻辑,如果需要,它也进行相应的数据检查。执行完成之后,返回一个 ActionForward对象,控制器通过该ActionForward对象来进行转发工作。我们主张将获取数据和执行业务逻辑的功能放到具体的 JavaBean当中,而Action只负责完成与控制有关的功能。遵循该原则,所以在上图中我将Action对象归为控制器部分。提示:其 实在Struts 1.1中,ActionMapping的作用完全可以由ActionConfig来替代,只不过由于它是公共API的一部分以及兼容性的问题得以保留。 ActionMapping通过继承ActionConfig来获得与其一致的功能,你可以等同地看待它们。同理,其它例如ActionForward与 ForwardConfig的关系也是如此。 下图给出了客户端从发出请求到获得响应整个过程的图解说明。 下面我们就来详细地讨论一下其中的每个部分,在这之前,先来了解一下模块的概念。模块我 们知道,在Struts 1.0中,我们只能在web.xml中为ActionServlet指定一个配置文件,这对于我们这些网上的教学例子来说当然没什么问题,但是在实际的应 用开发过程中,可能会有些麻烦。因为许多开发人员都可能同时需要修改配置文件,但是配置文件只能同时被一个人修改,这样肯定会造成一定程度上的资源争夺, 势必会影响开发效率和引起开发人员的抱怨。在Struts 1.1中,为了解决这个并行开发的问题,提出了两种解决方案: 1.多个配置文件的支持 2.模块的支持 支持多个配置文件,是指你能够为ActionServlet同时指定多个xml配置文件,文件之间以逗号分隔,比如Struts提供的MailReader演示例子中就采用该种方法。 action org.apache.struts.action.ActionServlet config /WEB-INF/struts-config.xml, /WEB-INF/struts-config-registration.xml 1 这种方法可以很好地解决修改冲突的问题,不 同的开发人员可以在不同的配置文件中设置自己的Action、ActionForm等等(当然不是说每个开发人员都需要自己的配置文件,可以按照系统的功 能模块进行划分)。但是,这里还是存在一个潜在的问题,就是可能不同的配置文件之间会产生冲突,因为在ActionServlet初始化的时候这几个文件 最终还是需要合并到一起的。比如,在struts-config.xml中配置了一个名为success的,而在 struts-config-registration.xml中也配置了一个同样的,那么执行起来就会产生冲突。为 了彻底解决这种冲突,Struts 1.1中引进了模块(Module)的概念。一个模块就是一个独立的子系统,你可以在其中进行任意所需的配置,同时又不必担心和其它的配置文件产生冲突。 因为前面我们讲过,ActionServlet是将不同的模块信息保存在不同的ModuleConfig对象中的。要使用模块的功能,需要进行以下的准备 工作:1、为每个模块准备一个配置文件2、配置web.xml文件,通知控制器决定采用多个模块以后,你需要将这些信息告诉控制器,这需要在web.xml文件进行配置。下面是一个典型的多模块配置: config /WEB-INF/struts-config.xml config/customer /WEB-INF/struts-config-customer.xml config/order /WEB-INF/struts-config-order.xml 要配置多个模块,你需要在原有的一个 (在Struts 1.1中将其对应的模块称为缺省模块)的基础之上,增加模块对应的。其中表示 为config/XXX的形式,其中XXX为对应的模块名,中还是指定模块对应的配置文件。上面这个例子说明该应 用有三个模块,分别是缺省模块、customer和order,它们分别对应不同的配置文件。3、准备各个模块所需的ActionForm、Action和JSP等资源但 是要注意的是,模块的出现也同时带来了一个问题,即如何在不同模块间进行转发?有两种方法可以实现模块间的转发,一种就是在< forward>(全局或者本地)中定义,另外一种就是利用org.apache.struts.actions.SwitchAction。下面就是一个全局的例子: ... ... ... ... 可以看出,只需要在原有的path属性前加上模块名,同时将contextRelative属性置为true即可。此外,你也可以在中定义一个类似的本地。 如果你已经处在其他模块,需要转回到缺省模块,那应该类似下面这样定义,即模块名为空。 此外,你也可以使用org.apache.struts.actions.SwitchAction,例如: ... ... ... ActionServlet我们首先来了解MVC中的控制器。在Struts 1.1中缺省采用ActionServlet类来充当控制器。当然如果ActionServlet不能满足你的需求,你也可以通过继承它来实现自己的类。这可以在/WEB-INF/web.xml中来具体指定。要 掌握ActionServlet,就必须了解它所扮演的角色。首先,ActionServlet表示MVC结构中的控制器部分,它需要完成控制器所需的前 端控制及转发请求等职责。其次,ActionServlet被实现为一个专门处理HTTP请求的Servlet,它同时具有servlet的特点。在 Struts 1.1中它主要完成以下功能: •接收客户端请求 •根据客户端的URI将请求映射到一个相应的Action类 •从请求中获取数据填充Form Bean(如果需要) •调用Action类的execute()方法获取数据或者执行业务逻辑 •选择正确的视图响应客户 此 外,ActionServlet还负责初始化和清除应用配置信息的任务。ActionServlet的初始化工作在init方法中完成,它可以分为两个部 分:初始化ActionServlet自身的一些信息以及每个模块的配置信息。前者主要通过initInternal、initOther和 initServlet三个方法来完成。我们可以在/WEB-INF/web.xml中指定具体的控制器以及初 始参数,由于版本的变化以及Struts 1.1中模块概念的引进,一些初始参数被废弃或者移入到/WEB-INF/struts-config.xml中定义。下面列出所有被废弃的参数,相应地 在web.xml文件中也不鼓励再使用。•application •bufferSize •content •debug •factory •formBean •forward •locale •mapping •maxFileSize •multipartClass •nocache •null •tempDir ActionServlet根据不同的模块来初始化ModuleConfig类,并在其中以XXXconfig集合的方式保存该模块的各种配置信息,比如ActionConfig,FormBeanConfig等。初 始化工作完成之后,ActionServlet准备接收客户请求。针对每个请求,方法process(HttpServletRequest request, HttpServletResponse response)将被调用。该方法指定具体的模块,然后调用该模块的RequestProcessor的process方法。protected void process(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { RequestUtils.selectModule(request, getServletContext()); getRequestProcessor(getModuleConfig(request)).process(request, response);} RequestProcessor包含了Struts控制器的所有处理逻辑,它调用不同的processXXX方法来完成不同的处理。下表列出其中几个主要的方法:方法 功能 processPath 获取客户端的请求路径 processMapping 利用路径来获得相应的ActionMapping processActionForm 初始化ActionForm(如果需要)并存入正确的scope中 processActionCreate 初始化Action processActionPerform 调用Action的execute方法 processForwardConfig 处理Action返回的ActionForward ActionForm对于ActionForm你可以从以下几个方面来理解它: 1.ActionForm 表示HTTP窗体中的数据,可以将其看作是模型和视图的中介,它负责保存视图中的数据供模型或者视图使用。Struts 1.1文档中把它比作HTTP和Action之间的防火墙,这体现了ActionForm具有的过滤保护的作用,只有通过ActionForm验证的数据 才能够发送到Action处理。 2.ActionForm是与一个或多个ActionConfig关联的JavaBean,在相应的action的execute方法被调用之前,ActionForm会自动利用请求参数来填充自己(初始化属性)。 3.ActionForm是一个抽象类,你必须通过继承来实现自己的类。 ActionForm 首先利用属性的getter和setter方法来实现初始化,初始化完毕后,ActionForm的validate方法被调用,你可以在其中来检查请求 参数的正确性和有效性,并且可以将错误信息以ActionErrors的形式返回到输入窗体。否则,ActionForm将被作为参数传给action的 execute方法以供使用。ActionForm bean的生命周期可以设置为session(缺省)和request,当设置为session时,记得在reset方法中将所有的属性重新设置为初始值。由 于ActionForm对应于HTTP窗体,所以随着页面的增多,你的ActionForm将会急速增加。而且可能同一类型页面字段将会在不同的 ActionForm中出现,并且在每个ActionForm中都存在相同的验证代码。为了解决这个问题,你可以为整个应用实现一个ActionForm 或者至少一个模块对应于一个ActionForm。但是,聚合的代价就是复用性很差,而且难维护。针对这个问题,在Struts 1.1中提出了DynaActionForm的概念。DynaActionForm类 DynaActionForm 的目的就是减少ActionForm的数目,利用它你不必创建一个个具体的ActionForm类,而是在配置文件中配置出所需的虚拟 ActionForm。例如,在下表中通过指定的type为 "org.apache.struts.action.DynaActionForm"来创建一个动态的ActionForm--loginForm。 动态的ActionForm的使用方法跟普 通的ActionForm相同,但是要注意一点。普通的ActionForm对象需要为每个属性提供getter和setter方法,以上面的例子而言, 我们需要提供getUsername() 和 setUsername()方法取得和设置username属性,同样地有一对方法用于取得和设置password属性和actionClass属性。如 果使用DynaActionForm,它将属性保存在一个HashMap类对象中,同时提供相应的get(name) 和 set(name)方法,其中参数name是要访问的属性名。例如要访问DynaActionForm中username的值,可以采用类似的代码:String username = (String)form.get("username"); 由于值存放于一个HashMap对象,所以要记得对get()方法返回的Object对象做强制性类型转换。正是由于这点区别,如果你在Action中非常频繁地使用ActionForm对象,建议还是使用普通的ActionForm对象。在Struts 1.1中,除了DynaActionForm以外,还提供了表单输入自动验证的功能,在包org.apache.struts.validator中提供了许多有用的类,其中最常见的就是DynaValidatorForm类。DynaValidatorForm类 DynaValidatorForm是DynaActionForm的子类,它能够提供动态ActionForm和自动表单输入验证的功能。和使用DynaActionForm类似,你必须首先在配置文件中进行配置: 同时要定义验证的插件: 其中的validator.xml和validator-rules.xml分别表示验证定义和验证规则的内容(可以合并在一起),比如针对上例中的DynaValidatorForm,我们有如下验证定义(validator.xml):
从上述定义中,我们可以看到对于字段 username有三项验证:required, minlength, maxlength,意思是该字段不能为空,而且长度在3和16之间。而validator-rules.xml文件则可以采用Struts提供的缺省文 件。注意在中定义的form是如何与validation.xml中的form关联起来的。最后,要启动自动验证功 能,还需要将Action配置的validate属性设置为true。 此时,Struts将根据xml配置文件中的定义来检验表单输入,并将不符合要求的错误信息输出到页面。但是你可能会想:这个功能虽然好,可是什么检验都跑到服务器端执行,效率方面和用户易用性方面是不是有些问题?你可能会怀念起那简单的JavaScript客户端验证。不 用担心,在Struts 1.1中也支持JavaScript客户端验证。如果你选择了客户端验证,当某个表单被提交以后,Struts 1.1启动客户端验证,如果浏览器不支持JavaScript验证,则服务器端验证被启动,这种双重验证机制能够最大限度地满足各种开发者的需要。 JavaScript验证代码也是在validator-rules.xml文件中定义的。要启动客户端验证,你必须在相应的JSP文件中做如下设置: 1.为增加onsubmit属性 2.设置Javascript支持 下表中列出了一JSP文件的示例代码,红字部分为Javascript验证所需代码。<%@ taglib uri="/WEB-INF/struts-html.tld" prefix="html" %>Panel 3: Profile- Struts1.1应用初步
- Struts1.1应用初步
- struts1.X初步
- struts1.1中的异常应用实践
- struts1.x的初步认识
- Struts1的应用
- struts1中配置应用
- struts1+json的应用
- Struts1.x spring3 hibernate4 初步整合
- 在struts1.1中使用应用模块(Application Modules)
- struts1.1中validation校验框架的应用
- 在struts1.1中使用应用模块(Application Modules)
- 多媒体应用程序设计初步
- ant应用初步- -
- postgreSQL初步应用
- PHP_SELF 应用初步
- PHP_SELF 应用初步
- JSON的初步应用
- Android超简易侧滑菜单的实现
- iOS 应用架构谈 本地持久化方案
- iOS开发翻转动画效果
- 等待一个异步function的结果
- iOS中旋转加载动画的实现
- Struts1.1应用初步
- Fedora23 安装 BCM43142 无线网卡驱动
- 实现炫酷的卡片式动画!
- BIRT4.4导出xlsx文件单sheet
- JavaScript异步编程
- nyoj-35 表达式求值
- 做android爽到爆的东西,一般人我不告诉他
- 使用CALayer的Mask实现注水动画效果
- 安卓开发之动态注册网络监听广播