300 likes | 514 Views
02 - Struts 核心组件 及运行机制. 中科软培训部. 回顾. 什么是 MVC? Struts 是怎么去实现 MVC 的 ? Struts 基本组件有那些 ? 基本组件之间有什么关系 ? Struts 标签的运行机制是什么 ? Struts 标签库的分类 ; 什么时候用什么标签 ;. 重点. 了解 Struts 的核心组件及运行机制 掌握如果扩展 ActionServlet 和 RequestProcessor 了解 DTO 对象 掌握 ActionForm 的配置和使用 ; 掌握 ActionForm 与 Action 的邦定 ;
E N D
02-Struts核心组件及运行机制 中科软培训部
回顾 • 什么是MVC? • Struts是怎么去实现MVC的? • Struts基本组件有那些? • 基本组件之间有什么关系? • Struts标签的运行机制是什么? • Struts标签库的分类; • 什么时候用什么标签;
重点 • 了解Struts的核心组件及运行机制 • 掌握如果扩展ActionServlet和RequestProcessor • 了解DTO对象 • 掌握ActionForm的配置和使用; • 掌握ActionForm与Action的邦定; • 掌握ActionForm的数据验证; • 掌握ActionForm的动态现实;
Struts运行机制 • Struts架构从本质上是MVC设计模式的具体实现 • 表示层一般使用视图组件实现、控制层使用控制器组件实现,而应用逻辑层则使用模型组件实现。作为表示层和应用逻辑层之间的中介,控制器处于视图及模型之间,起到了桥梁的沟通作用 • 在Struts框架中对应着每一层一般都提供了相应的实现组件 数据库 表示层 控制层 逻辑层
对应的实现组件 • 与控制器组件相关的类主要包括: • ActionServlet:Struts架构的中央控制器,用于接受浏览器客户端用户请求以及状态改变,并依据处理结果选择表示层不同视图的重定向。 • RequestProcessor:包含了Struts控制器在处理servlet请求时所遵循的控制逻辑。 • Action:控制器的一部分,用于模型交互,执行状态改变或状态查询,以及告诉ActionServlet 下一个选择的视图。 • ActionForm:用于保存于表单数据相关的状态数据的改变。 • ActionMapping:用于控制在状态数据改变后的事件处理的方式。 • ActionForward:用户指向或者视图选择。 • 与视图组件相关的工具主要包括Struts架构中提供的强大标记库,常用的标记库功能如下所示: • struts-html.tld标记库:扩展HTML Form的JSP标记 • struts- bean.tld标记库:扩展扩展处理JavaBean的JSP标记 • struts-logic.tld标记库:扩展测试属性值的JSP标记 • 与模型组件相关的工具主要包括: • 开发者提供的其他数据服务和API,例如:JavaBean等
控制器组件 • Struts 架构中控制器组件所承担的主要功能包括: • 接受浏览器客户端的处理请求 • 根据用户的不同请求,调用对应的模型组件来执行相应的业务逻辑 • 获取模型组件业务逻辑的处理结果 • 根据当前的状态数据及业务逻辑的处理结果,选择合适的视图组件呈现在浏览器客户端。 • 在Struts框架中,整个控制工作是在一系列的相关组件的配合下共同完成的
ActionServlet • 在Struts架构中Controller组件的核心控制器组件是ActionServlet • 是org.apache.struts.action.ActionServlet类型的servlet • 所有客户端提交的用户请求都由它进行处理 • 负责接收客户端请求后将之分发到相应的Action Bean处理,再根据处理的结果将不同的显示请求重定向到响应页面。 • 实际上,ActionServlet完全是在幕后工作,它将其他组件绑定在一起。 • 该类继承自javax.servlet.http.HttpServlet,有标准的生命周期中所用到的方法.另外在ActionServlet类添加了一个特殊的process方法.process()方法的作用是处理接收的请求并作出相应 • 代码参见ActionServlet.java 第1184行 • ActionServlet接收到Servlet容器的新的客户端请求后,它采取的具体的处理过程如下: • 根据请求的种类执行相应的doGet或doPost方法,然后在doGet和doPost中调用process方法 • Process方法首先会获得RequestProcessor类的对象,然后调用该类的process方法进行处理.实际上控制器所执行的控制逻辑就包含在RequestProcessor这个类中,而不是在ActionServlet中.ActionServlet处理业务的过程是借助RequestProcessor这个类的功能来实现的
RequestProcessor类 RequestProcessor类 • 一个应该模块对应一个RequestProcessor类; • ActionSerlvet接收请求后调用RquestProcessor类的process方法,并把request和response传给它; • 根据配置文件创建ActionMapping对象 • RquestProcessor类的process方法从struts-config.xml文件中根据请求URI查询匹配的<action>子元素,然后根据<action>子元素中的“name”属性在配置文件中查找匹配的<form-bean>子元素,确定下一步要用到的ActionForm Bean类 • RquestProcessor类的process方法调用ActionForm Bean类的setXXX方法,将表单中的数据填充到FormBean类的相应的属性中,然后根据<action>子元素中的validate属性的值,判断是否调用FormBean类的validate方法校验表单的数据 • 查找匹配的<action>子元素中的“type”属性寻找相应的可用的ActionBean类的对象,如果找不到就新创建一个 • 将FormBean类的对象,ActionMapping对象,request对象,reponse对象一起传给Action类的execute()方法 • Action类的execute()方法执行完毕,返回一个表明相应页面的ActionForward对象. RequestProcessor类根据ActionForward对象进行调整
RequestProcessor类的process方法调用的方法列表 • processMultipart()—预处理request的请求方式以及分析请求的contentType属性 • processPath()—得到请求的url,分析后选择合适的Action组件; • processLocale()—得到请求的locale,适当时候存放到session中; • processContent()—通过ControllerConfig对象的contentType属性设置字符编码; • processNoCache()--通过ControllerConfig对象的nocache属性设置页面缓存机制; • processPreprocess()—这是一个空方法,直接返回true,一般用来扩展用的; • processMapping()—匹配用户请求的URL只否有相应的ActionMapping对象; • processRoles()—判断用户是否配置了安全角色; • processActionForm()—查找ActionMapping对象邦定的ActionForm,并实例化; • processPopulate()—如果找到ActionForm就把request中的表单值填到actionForm; • ProcessValidate()—如果ActionMapping中validate属性为true.就调用表单的validate方法进行数据验证; • processForward()—调用requestDispatcher的forward()方法进行页面跳转; • processInclude()--调用requestDispatcher的include()方法进行页面输出; • processActionCreate()—创建一个action的实例存放到缓存中; • processActionPerform()—调用action的execute()方法; • precessActionForward()—根据action的execute()的返回值进行页面跳转;
扩展RequestProcessor处理文字编码问题 • 我们可以去重写requestProcessor类的processPreprocess方法去处理编码; • 并在struts-config.xml文件里面配置 <controller processorClass="struts.requestprocessor.MyRequestProcessor"> </controller>
例:MyRequestProcesser类 publicclass MyRequestProcessor extends RequestProcessor { protectedboolean processPreprocess(HttpServletRequest request, HttpServletResponse response) { try { request.setCharacterEncoding("GBK"); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } returnsuper.processPreprocess(request, response); } }
DTO数据传输对象 DTO:Data Transfer Object 作用:用于model层和view层之间传递数据 • 减少数据的冗余,提高传输效率. • 有助于实现各个层之间的独力性.
Struts框架中的DTO ActionForm Bean是Struts提供的DTO,用于视图层和控制层之间传递HTML表单数据; • 在action中直接得到ActionForm Bean实体得到数据;
ActionForm的生命周期 接收控制器的请求 如果校验失败,将请求转发给<action> 的input属性所指定的web组件,并将 FormBean保存在指定的范围中 从request或session范围中取出 ActionForm对象,如果不存在就new一个 调用ActonForm对象的reset方法 如果校验成功调用Action的execute方法 并将FormBean传递给该方法 将FormBean对象保存在scope 指定的范围内 将请求转发给<action指定的web组件, 并将FormBean保存在指定的范围中 将用户的表单数据封装在FormBean中 如果<action>中的validate属性为true,调 用FormBean的validatte()方法
创建ActionForm • 创建一个与HTML中表单一一对应的JavaBean; • JavaBean继承org.apache.struts.action.Actionform类; • 重写reset()方法; • 重写validate()方法;
Validate()方法 当Struts的配置文件满足以下两个条件,Struts控制器就会调用ActionForm的validate()方法; • 为ActionForm配置了Action映射,即<form-bean>元素里面name和<action>元素里面的name相匹配; • <action>元素的validate属性为true; 方法返回ActionErrors对象,如果该对象为空或不包含任何ActionMessage对象,那么就表示验证通过;反之把ActionErrors存到request中并返回input页面;
表单数据验证 • 重写ActionForm的validate方法; • 在validate方法里根据ActionForm中填充的属性值判断是否适合程序的要求; • 返回一个ActionErrors对象; • ActionErrors对象是一个MAP集合,存放的全都是ActionMessage对象; • ActionMessage对象的错误提示配合Resource bundle文件使用; • 如果ActionErrors集合里没有ActionMessage对象,则通过数据验证,执行Action的execute方法,否则返回ActionMapping对象用的input页面,并通过<html:errors>标签显示ActionMessage中的错误提示;
例:ActionFormBean的validate public ActionErrors validate(ActionMapping mapping, HttpServletRequest request) { ActionErrors errors = new ActionErrors(); if(userName==null||userName.equals("")){ errors.add("userName",new ActionMessage("errors.tip.username.null")); } if(userPwd==null||userPwd.equals("")){ errors.add("userPwd",new ActionMessage("errors.tip.userpwd.null")); } if(address==null||address.equals("")){ errors.add("address",new ActionMessage("errors.tip.address.null")); }elseif (address.length()<4){ errors.add("address",new ActionMessage("errors.tip.address.length",4)); } if(phone==null||phone.equals("")){ errors.add("phone",new ActionMessage("errors.tip.phone.null")); }elseif(phone.length()!=11){ errors.add("phone",new ActionMessage("errors.tip.phone.length")); }else{ try { Double.parseDouble(phone); } catch (NumberFormatException e) { errors.add("phone",new ActionMessage("errors.tip.phone.int")); } if(age<16||age>90){ errors.add("age",new ActionMessage("errors.tip.age.format",16,90)); } } return errors; }
Reset()方法 不管ActionForm存在于那个scope,实例化之后ActionForm就会调用reset方法; Reset()方法用于恢复ActionForm的默认值,例如把boolean设置成true或false,把String设置为空;
例:ActionFormBean的reset() publicvoid reset(ActionMapping mapping, HttpServletRequest request) { userName=null; userPwd=null; address=null; phone=null; age=0; }
配置ActionForm 在struts配置文件的<form-beans>元素中配置ActionForm,如: <form-bean name=“loginForm” type=“com.actionform.LoginForm”/> Name:为实例化后的ActionForm取名; Type:ActionForm的类路径;
访问ActionForm • 通过Struts HTML标签库访问; • 从request或session范围内取出ActionForm实例; • 在Action的execute()方法中直接访问;
处理表单跨页 • 通过struts-config.xml配置多个action邦定一个ActionForm; • ActionForm配置一个属性用于区分页面索引--page; • ActionForm对象必须保存在session范围内; • 根据条件重写reset和validate方法;
动态ActionForm ActionFrom和DynaActionForm的区别 • ActionForm对于大型的Struts应该必须以编程方式创建大量的ActionForm,如果HTML表单字段发生变化,就必须改源代码; • Struts1.1 对此做出了改进,引入了动态ActionForm的概念,DynaActionForm类以及其子类实现了动态ActionForm,而必须主意的是DynaActionForm本身是ActionForm的子类;
配置动态ActionForm 动态ActionFormp完全支持在Struts-config.xml文件中完成ActionForm的全部配置; 动态ActionForm标签: <form-bean>:name指定ActionForm的实例名称;type指定org.apache.struts.action.DynaActionForm; <form-property>:name指定动态ActionForm Bean的成员属性名;type指定该属性的数据类型;initial指定初始化值,相当于reset操作;
Type属性指定的JAVA类型 • Java.lang.BigDecimal • Java.lang.BigInteger • Java.lang.Boolean • Java.lang.Byte • Java.lang.Character • Java.lang.Class • Java.lang.Double • Java.lang.Float • Java.lang.Integer • Java.lang.Long 如果表单的字段值是java基本类型,在配置时应该用上面相应的封装类来代替
例:动态ActionForm的配置 <form-bean name="loginForm" type="org.apache.struts.action.DynaActionForm"> <form-property name="userName" type="java.lang.String" initial="请输入用户名"> </form-property> <form-property name="userPwd" type="java.lang.String" initial=""> </form-property> </form-bean>
动态ActionForm的访问 Action和Struts HTML标签都可以访问动态ActionForm,如果是标准的ActionForm,在Action的execute方法中可以使用getter和setter方法操作,但是DynaActionForm把所有的数据都封装到一个MAP集合中,所有动态ActionForm提供的是一个用于访问所有属性的通用方法: public Object get(String name) public void set(String name,Object value) • 其实有人在想,动态的ActionForm怎么去实现数据验证? 我们将结合下一个知识点,struts的验证框架一起来实现;
例:在Actiom中访问动态ActionForm对象 DynaActionForm daf = (DynaActionForm) form; String userName = (String) daf.get("userName"); String userPwd = (String) daf.get("userPwd");
总结: • ActionForm在MVC中的位置; • ActionForm的运行机制; • ActionForm配置及使用; • ActionForm的reset和validate方法; • 动态ActionForm的配置和使用;