31
Struts Struts 核核核核核 核核核核核 核核核核 核核核核

Struts 核心组件及 运行机制

Embed Size (px)

DESCRIPTION

Struts 核心组件及 运行机制. Struts 运行机制. Struts 架构从本质上是 MVC 设计模式的具体实现 表示层一般使用视图组件实现 、 控制层使用控制器组件实现 , 而应用逻辑层则使用模型组件实现 。作为表示层和应用逻辑层之间的中介,控制器处于视图及模型之间,起到了桥梁的沟通作用. 对应的实现组件. 与控制器组件相关的类主要包括: ActionServlet : Struts 架构的中央控制器 ,用于接受浏览器客户端用户请求以及状态改变,并依据处理结果选择表示层不同视图的重定向。 - PowerPoint PPT Presentation

Citation preview

Page 1: Struts 核心组件及 运行机制

StrutsStruts 核心组件及核心组件及运行机制 运行机制

Page 2: Struts 核心组件及 运行机制

StrutsStruts 运行机制运行机制 Struts 架构从本质上是 MVC 设计模式的具体实现 表示层一般使用视图组件实现、控制层使用控制器组件实现,而应用逻辑层则使用模型组件实现。作为表示层和应用逻辑层之间的中介,控制器处于视图及模型之间,起到了桥梁的沟通作用

Page 3: Struts 核心组件及 运行机制

对应的实现组件对应的实现组件 与控制器组件相关的类主要包括:

– ActionServlet : Struts架构的中央控制器,用于接受浏览器客户端用户请求以及状态改变,并依据处理结果选择表示层不同视图的重定向。– RequestProcessor :包含了 Struts 控制器在处理 servlet 请求时所遵循的控制逻辑。– Action :控制器的一部分,用于模型交互,执行状态改变或状态查询,以及告诉 A

ctionServlet 下一个选择的视图。– ActionForm :用于保存于表单数据相关的状态数据的改变。– ActionMapping :用于控制在状态数据改变后的事件处理的方式。 – ActionForward :用户指向或者视图选择。

与视图组件相关的工具主要包括 Struts架构中提供的强大标记库,常用的标记库功能如下所示:– struts-html.tld 标记库:扩展 HTML Form 的 JSP 标记– struts- bean.tld 标记库:扩展扩展处理 JavaBean 的 JSP 标记– struts-logic.tld 标记库:扩展测试属性值的 JSP 标记

与模型组件相关的工具主要包括:– 开发者提供的其他数据服务和 API ,例如: JavaBean 等。

Page 4: Struts 核心组件及 运行机制

控制器组件控制器组件 Struts 架构中控制器组件所承担的主要功能包括:

– 接受浏览器客户端的处理请求– 根据用户的不同请求,调用对应的模型组件来执行相应的业务逻辑– 获取模型组件业务逻辑的处理结果– 根据当前的状态数据及业务逻辑的处理结果,选择合适的视图组件呈现在浏览器客户端。

在 Struts 框架中 , 整个控制工作是在一系列的相关组件的配合下共同完成的

Page 5: Struts 核心组件及 运行机制

ActionServletActionServlet 在 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 和 doPos

t 中调用 process 方法– Process 方法首先会获得 RequestProcessor 类的对象 , 然后调用该类的 pro

cess 方法进行处理 . 实际上控制器所执行的控制逻辑就包含在 RequestProcessor 这个类中 , 而不是在 ActionServlet 中 .ActionServlet 处理业务的过程是借助 RequestProcessor 这个类的功能来实现的

Page 6: Struts 核心组件及 运行机制

RequestProcessorRequestProcessor 类类RequestProcessor 类 一个应该模块对应一个 RequestProcessor 类 ; ActionSerlvet 接收请求后调用 RquestProcessor 类的 process 方法 , 并把 request 和 res

ponse 传给它 ; 根据配置文件创建 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 对象一起传给 Acti

on 类的 execute() 方法 Action 类的 execute() 方法执行完毕 , 返回一个表明相应页面的 ActionForward 对象 .

RequestProcessor 类根据 ActionForward 对象进行调整

Page 7: Struts 核心组件及 运行机制

RequestProcessorRequestProcessor 类的类的 processprocess 方法调用的方法列方法调用的方法列表表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() 的返回值进行页面跳转 ;

Page 8: Struts 核心组件及 运行机制

扩展扩展 RequestProcessorRequestProcessor处理文字编码问题处理文字编码问题我们可以去重写 requestProcessor 类的 pr

ocessPreprocess 方法去处理编码 ;

并在 struts-config.xml 文件里面配置<controller processorClass="struts.requestprocessor.MyRequestProcessor"></controller>

Page 9: Struts 核心组件及 运行机制

例例 :MyRequestProcesser:MyRequestProcesser 类类public class MyRequestProcessor extends RequestProcessor { protected boolean processPreprocess(HttpServletRequest request, HttpServletResponse response) { try { request.setCharacterEncoding("GBK"); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } return super.processPreprocess(request, response); }}

Page 10: Struts 核心组件及 运行机制

ActionFormActionForm org.apache.struts.action.ActionForm 的子类的实例 用于保存用户请求表单中的数据,并可保持其状态的连续性,即在不同的页面间传递这些数据 由开发者定义的子类( ActionForm Bean 类)中主要包含和用户表单数据同名的属性以及相应的存取方法(属性的 get 方法和 set 方法),而没有商业逻辑此外,还可根据需要重写从父类继承来的 reset()和 validate() 方法,实现属性重置和表单数据验证功能

Page 11: Struts 核心组件及 运行机制

处理处理 ActionForm BeanActionForm Bean 的基本的基本步骤步骤1 )检查并确认在 Action 中已经配置了对表单 Bean 的映射。2 )根据表单 Bean 的 name 属性,查找表单 Bean 的配置信息。3 )检查该表单 Bean 的使用范围,查找在该范围内,是否已存在该

Bean 的实例。如果已经存在,那么就重用该实例。否则,就重新创建一个。4 )调用该 Bean 实例的 reset() 方法重置其状态。5 )调用该 Bean 实例相应的 setter 方法,使用请求表单中的数据填充 Bean 的属性。6 )如果起用了 validate 机制,则调用表单 Bean 的 validate() 方法。如果 validate ()方法返回任何错误,则跳过步骤 7 )转到预定的出错处理页面。7 )将该表单 Bean 实例作为参数,传给处理器对象的 execute ()方法并执行。

Page 12: Struts 核心组件及 运行机制

ActionFormActionForm 的生命周期的生命周期接收控制器的请求

从 request 或 session 范围中取出ActionForm 对象 , 如果不存在就 new 一个

调用 ActonForm 对象的 reset 方法

将 FormBean 对象保存在 scope指定的范围内

将用户的表单数据封装在 FormBean 中

如果 <action> 中的 validate 属性为 true, 调用 FormBean 的 validatte() 方法

如果校验失败 , 将请求转发给 <action>的 input 属性所指定的 web 组件 , 并将FormBean 保存在指定的范围中

如果校验成功调用 Action 的 execute 方法并将 FormBean 传递给该方法

将请求转发给 <action 指定的 web 组件 ,并将 FormBean 保存在指定的范围中

Page 13: Struts 核心组件及 运行机制

Action BeanAction Bean Action 类是 Struts 架构中控制器组件的重要组成部分 . 它是用户请求和业务逻辑之间的媒介 . org.apache.struts.action.Action 子类类型, RequestProcessor 调用它以处

理不同的页面请求 它通过如下的方式发挥作用 : 开发者事先创建一个或多个 Action 的子类 , 在子类中加入所需要的处理逻辑 , 用于处理不同的业务逻辑 . 我们称这些子类为处理器类或 ActionBean类 当 Struts 架构的核心控制器 ActionServlet 委托 RequestProcessor 对象处理一个用户的请求时 , RequestProcessor 对象除了使用 FormBean 来接受表单的数据外 , 还会查找配置文件中的 <action-mapping> 元素 , 根据请求页面的 URI 确定匹配的 <action> 子元素 ( 参见下面的蓝色代码 ) RequestProcessor 对象会针对当前用户请求寻找一个可用的 Action 类型的对象 . 如果找不到就创建一个新的对象 , 然后将客户端的请求发送给该处理器类的对象 , 并调用 Action 子类的 execute 方法进行处理 .

<action-mappings> <action path="/regist"

type="test.RegistAction" name="formBean1" scope="session" />

<action path="/overview" forward="/links.jsp"/></action-mappings>

Page 14: Struts 核心组件及 运行机制

ActionBeanActionBeanpublic ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception mapping : 是对 struts-config.xml 文件中配置信息的一个映射 , 它封装了当前处理器类对象

( 既 ActionBean) 的相关信息

Page 15: Struts 核心组件及 运行机制

ActionBeanActionBean

设计 ActionBean时注意事项1. RequestProcessor 对象对于每种 ActionBean 类型只创建一个实例 . 该实例将被用于所有匹配的请求 , 这就需要我们在定义 ActionBean 类时考虑如果在多线程的条件下使用 . 一个重要的原则就是在 ActionBean类中尽量使用局部变量而不是实例变量2. 尽量在 ActionBean 类中加入异常处理逻辑 , 在方法内部捕获和处理可能出现的异常 , 而不是简单的抛出3. 在控制器将请求重新定向到其他页面前 , 释放 ActionBean 组件作占用的资源 ( 如数据库连接 )4. 要避免将所有的业务逻辑都直接写在 ActionBean 类中 , 这样会导致 A

ctionBean 类的可读性和可维护性变差 . 由于这些商业的业务逻辑代表被嵌入到只能运行在 Web 应用程序环境的组件中 , 很难做到代码重用5. 综上所述 ,ActionBean 通常负责将客户端请求映射到处理这些请求的业务逻辑 Bean, 在转向生成响应回送到客户端解码 , 实际上起到 Contr

oll 和 Model 之间的适配器作用 , 属于低层面的控制器

Page 16: Struts 核心组件及 运行机制

ActionMapping ActionMapping org.apache.struts.action.ActionMapping 类型 系统针对每个 <action> 元素都创建一个与之对应的 ActionM

apping 当 ActionServlet 转发请求时, ActionMapping 实例被作为参数之一传递给相应 Action 对象的 execute() 方法 ActionMapping 对象映射的配置信息主要来自配置文件中的

<action-mapping> 和 <global-forward> 元素

Page 17: Struts 核心组件及 运行机制

ActionForward ActionForward 一种配置对象,映射配置文件 struts-config.xml 中的 <forward> 元素,封装目标响应页面 URI 。 <forward> 元素不但可以定义在 <global-forwards> 元素中 , 作为全局的配置信息 , 也可以定义在 <action> 元素中 , 此时只能用于特定的 Action 处理 . ActionForward 的主要属性:

– name - 本 ActionForward 对象的标识,在 Action Bean 类 – 的 execute() 方法中, ActionMapping 对象的 – findForward() 方法就是根据此标识来查找相应– 的 ActionForward 对象的。– path - 目标响应页面 URI– redirect - 标明页面转向的方式<global-forwards>

<forward name="failed" path="/error.jsp"/><forward name="successed" path="/right.jsp"/>

</global-forwards>

Page 18: Struts 核心组件及 运行机制

模型组件模型组件一般使用 JavaBean 来实现 Model 组件,对应着其作用可以分为两方面 :

系统状态 Bean ( Application State ) 业务逻辑 Bean ( Business Logic Bea

n )JavaBean 的作用范围 :

page request sessionapplication

Page 19: Struts 核心组件及 运行机制

视图组件视图组件 视图组件中提交的请求被控制器组件接收 . 在实际的开发中 , 在视图组件内可以提交请求的途径主要有两种1. HTML 表单 : 通过表单的 action 属性来指定2. HTML 超连接 <a href=“regist.do”> 注册新用户 如果需要在发送请求的时候携带参数 , 可以按照如下 的方式 <a href=“regist.do”?name=aaa&password=aaa> 注册 在视图组件中还可以使用 Struts 标记库

Page 20: Struts 核心组件及 运行机制

标记库初步标记库初步 Struts 在国际化的过程中会用到一个特殊的 JSP 标记 <bean:message/>, 用来获取属性文件中存放的字符串信息,在使用前,首先要部署包含此标记定义的 Struts 标记库,具体做法是:1. 将 Struts 发布包中的标记库文件 struts-bean.tld 复制到当前应用程序的 WEB-INF 下2. 在 web.xml 文件中添加相应的 <taglib> 子元素<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd"> <web-app> <taglib> <taglib-uri>/WEB-INF/struts-bean.tld</taglib-uri> <taglib-location>/WEB-INF/struts-bean.tld</taglib-location> </taglib> </web-app>3. 在使用 <bean:message/> 标记的 JSP 文件中开头引入标记库文件 <%@ taglib uri="/WEB-INF/struts-bean.tld" prefix="bean" %> 这样我们就可以在 JSP 中使用 <bean:message> 标记了

Page 21: Struts 核心组件及 运行机制

应用程序国际化 应用程序国际化 本地化 : 针对不同的语言版本环境的客户开发出不同语言环境的软件版本 .如果需要对 Web 应用进行中文本地化操作 , 要注意处理中文乱码的问题 :<%@ page pageEncoding="GBK" contentType="text/html; charset=GBK"%> 国际化:应用程序在运行时能够根据客户端请求所来自的国家 / 地区、语言的不同而显示不同的用户界面 internationalization, 简称 I18N 。 资源包和属性文件 : 国际化能够提供多种语言界面,就应该在某个地方存放着所用到的各种语言的标签信息。这些字符串类型的信息事先已保存在多个文本文件中,每个文本文件对于一种不同语言的版本。这些文件我们称为属性文件,所有属性文件合作一起,我们称为资源包。 在 struts-config.xml 文件中添加 <message-resources/> 元素,用来指明所要用到的资源包 <struts-config> <message-resources parameter=“MyResource”> <struts-config> 属性文件中包含的是“键-值”对形式的字符串信息。该文件在程序启动时被载入内存,并根据客户端请求所携带的语言 / 地区信息进行匹配和使用,

Page 22: Struts 核心组件及 运行机制

应用程序国际化应用程序国际化 属性文件的命名格式:

– 文件名前缀 .properties– 文件名前缀 _ 语言种类 .properties– 前缀由开发者自行确定,后缀名必须固定为 .properties ,语言– 种类是有效的 ISO 语言代码, ISO639 标准定义的这些代码的– 格式为:英文小写、双字符,见下表– 缺省的属性文件

语言 编码汉语 (Chiness) zh

英语 (Englist) en

法语 (French) fr

德语 (German) de

日语 (Japanese) ja

Page 23: Struts 核心组件及 运行机制

案例案例 : : 实现程序国际化实现程序国际化 英文属性文件 MyResource.properties# Simple properties file for test.

title.welcome = Welcome you!title.imageEnter=/enter.giftitle.imgEnterHint=classmatetitle.imageRegist=/register.giftitle.imgRegistHint=regist

label.deny = Sorry,Login Failed!

item.submit = submititem.reset = resetitem.username = UserName item.password = Passworditem.password2 = Confirm Passworditem.regist = click here to registitem.loginAgain = login againitem.registsubmit = registitem.back = go back to login

Page 24: Struts 核心组件及 运行机制

中文属性文件 MyResource_zh.properties# 中文属性文件title.welcome = 欢迎欢迎title.imageEnter=/enter.giftitle.imgEnterHint= 同学录title.imageRegist=/register.giftitle.imgRegistHint= 注册label.deny = 抱歉 , 登陆失败item.submit = 提交item.reset = 重制item.username = 用户名 item.password = 密码item.password2 = 确认item.regist = 注册新用户item.loginAgain = 重新登陆item.registsubmit = 注册item.back = 返回登陆

Page 25: Struts 核心组件及 运行机制

为了更好的解决中文问题 , 使用 java 提供的 native2ascii 命令来对中文属性文件进行编码 . 在 cmd 下执行该命令 格式如下 : native2ascii -encoding gb2312 MyResource

_zh.properties MyResource_zh_new.properties

Page 26: Struts 核心组件及 运行机制

重新编码后的中文属性文件格式如下# \u4e2d\u6587\u5c5e\u6027\u6587\u4ef6

title.welcome = \u6b22\u8fce\u6b22\u8fcetitle.imageEnter=/enter.giftitle.imgEnterHint=\u540c\u5b66\u5f55title.imageRegist=/register.giftitle.imgRegistHint=\u6ce8\u518c

label.deny = \u62b1\u6b49,\u767b\u9646\u5931\u8d25

item.submit = \u63d0\u4ea4item.reset = \u91cd\u5236item.username = \u7528\u6237\u540d item.password = \u5bc6\u7801item.password2 = \u786e\u8ba4item.regist = \u6ce8\u518c\u65b0\u7528\u6237item.loginAgain = \u91cd\u65b0\u767b\u9646item.registsubmit = \u6ce8\u518citem.back = \u8fd4\u56de\u767b\u9646

Page 27: Struts 核心组件及 运行机制

Validate()Validate() 方法方法当 Struts 的配置文件满足以下两个条件 ,Struts 控制器就会调用 ActionForm 的 validate() 方法 ;1. 为 ActionForm 配置了 Action 映射 , 即 <form-bean>元素里面 name 和 <action> 元素里面的 name 相匹配 ;2. <action> 元素的 validate 属性为 true;

方法返回 ActionErrors 对象 , 如果该对象为空或不包含任何 ActionMessage 对象 , 那么就表示验证通过 ;反之把 ActionErrors 存到 request 中并返回 input 页面 ;

Page 28: Struts 核心组件及 运行机制

表单验证和错误处理表单验证和错误处理 重写 ActionForm 的 validate 方法 ; 在 validate 方法里根据 ActionForm 中填充的属性值判断是否适合程序的要求 ; 返回一个 ActionErrors 对象 ; ActionErrors 对象是一个 MAP集合 , 存放的全都是 Act

ionMessage 对象 ; ActionMessage 对象的错误提示配合 Resource bundle 文件使用 ; 如果 ActionErrors集合里没有 ActionMessage 对象 , 则通过数据验证 , 执行 Action 的 execute 方法 , 否则返回

ActionMapping 对象用的 input 页面 , 并通过 <html:errors> 标签显示 ActionMessage 中的错误提示 ;

Page 29: Struts 核心组件及 运行机制

public ActionErrors validate(ActionMapping mapping,javax.servlet.http.HttpServletRequest request) { ActionErrors errors = new ActionErrors(); if(this.name.equals("") || this.name ==null){ errors.add(ActionMessages.GLOBAL_MESSAGE, new ActionMessage("error.name.required")); } if(this.psw.equals("") || this.psw ==null){ errors.add(ActionMessages.GLOBAL_MESSAGE, new ActionMessage("error.psw.required")); } return errors;}

Page 30: Struts 核心组件及 运行机制

修改语言包修改语言包 英文属性文件 error.name.required = <li><font color="red">UserName is not null</font></li> error.psw.required = <li><font color="red">Psw is not null</font></li><br> 中文属性文件 error.name.required = <li><font color="red"> \u7528\u6237\u540d\u4e0d\u80fd\u4e3a\u7a7a</font></li> error.psw.required = <li><font color="red"> \u5bc6\u7801\u4e0d\u80fd\u4e3a\u7a7a</font></li><br>

Page 31: Struts 核心组件及 运行机制

Reset()Reset() 方法方法不管 ActionForm 存在于那个 scope, 实例化之后 ActionForm 就会调用 reset 方法 ;Reset() 方法用于恢复 ActionForm 的默认值 ,例如把 boolean 设置成 true 或 false, 把 Str

ing 设置为空 ;