??xml version="1.0" encoding="utf-8" standalone="yes"?> 摘要 参?/P>
[Core] Core J2EE Patterns by Deepak Alur et. al. (Prentice Hall, 2001) 我们简单的讨论前面解释的交互动作。我们将看到struts怎样从本地特定消息中获得消息keyQ又怎么在视图中以一致的方式得到处理。我们将用jsp作ؓ(f)视图lg?/P>
用ActionError标识错误 实现Action.execute(? ?ActionForm.validate(?Ҏ(gu)Q应该可以捕捉验证和应用E序特定错误到ActionErrors对象中,他们l成了ActionError对象。一个ActionError对象有一个消息key和一个可选对象用来存攑֊态返回的消息。参考上一节的相关信息Q一个ActionErros对象不用兛_本地化和相关的资源包可以创建。我们可以处?18N当ActionError对象处理消息时。可以参考ActionErrorAPI获得完全的创建ActionError对象的方法列表。一旦一个ActionError对象创徏Q就应该使用ActionError对象的ActionError.addҎ(gu)d到ActionError对象l中Qƈ且传递ActionError和检到校验错误的属性名。ؓ(f)了保存错误消息而不兌到属性,可以用ActionErrors.GLOBAL_ERROR代替属性参数。用属性名创徏ActionError对象在ActionErrors一节解释。ActionErrorcL展ActionMessagec;和struts1.1一PActionErrorcȝ单的把调用委托给ActionMessagecR?/P>
用ActionErrors理错误 ActionErrors对象使用HashMap方式理所有ActionError对象Q名是消息属性名Q值是ActionMessageItem对象。ActionMessageItem作ؓ(f)innercd明在ActionMessages中。每一个ActionMessageItem对象׃个唯一的序列号和一个包含属性对应所有校验错误的的ArrayList对象l成。序列号用来排序ActionMessageItem集合Q其中的校验错误通过开始标Cؓ(f)invalid的属性获得。ActionErrors.getq回一个ArrayList的P代器Q其中容U了ActionError对象集合。这个P代对象通过定制ErrorsTag标签引用Q将在下节解释?/P>
在请求处理器Q比如在Action.execute中,ActionErrors应该用属性名Action.ERROR_KEY保存到HttpServletRequest中;q个操作通过调用action基类的saveErrorsҎ(gu)Q传递请求对象和ActionErrors对象作ؓ(f)参数。ActionErrors作ؓ(f)ActionForm.validate(?的结果生,由在h对象中的RequestProcessor使用Action.ERROR_KEY保存。下一个视囑֏以用ErrorsTag来获得ActionErrors对象QErrorsTag可以用在jsp中?/P>
ActionErrorscL展了actionMessagescRActionErrors提供了静态成员GLOBAL_ERRORQActionMessages提供了静态成员GLOBAL_MESSAGEQ这些静态成员当消息不是特定属性时可以作ؓ(f)keys用。如果要保存ActionMessages对象到请求处理对象中Q传递请求对象和ActionMessages对象lAction.saveMessages(?Ҏ(gu)卛_QAction.saveMessages(?对象使用Action.MESSAGE_KEY保存到请求对象中?/P>
如果想简单的获得消息keysQ不用属性和动态参敎ͼ可以用org.apache.struts.util.RequestUtils.getActionErrors(?Ҏ(gu)转换一个String对象QString数组Q或一个ErrorMessages对象QVectorQ到一个ActionErrors对象中。对于这U方式,getActionErrors(?会用ActionErrors.GLOBAL_ERROR代替属性参数?/P>
用ErrorsTag昄错误 q个定制的标{显C消息到HTML文档中。它使用Action.ERROR_KEY从HttpServletRequest中获得ActionErrors对象Q然后用ActionErrors.get()Ҏ(gu)获得容纳ActionError对象的ArrayList的P代器。对ArrayList中的每一个ActionError对象Q一个本地消息被写到response中。默认用session中的本地对象Q但是可以在标签中定义相反的本地属性。默认情况下Q资源包用Action.MESSAGES_KEY保存C下文中,除潜昵┒ㄒ菽似渌_ʎQ孕枰哺亲试HQL鲆陨pd咀试次募枰芾薄Q蛃truts1.1一P一个ErrorsTag仅能使用一个资源包家族Q有相同的基本名UͼQ因此在ActionErrors对象中的所有错误应该在资源包家族中都可以找到。因为ActionErrors对象中的所有ActionError对象都用属性名登记了,消息可以通过在ErrorsTag中定义一个属性名对应。ErrorsTag使用消息keys‘errors.header’和‘errors.footer’提供错误消息显C的标题和格式?/P>
ValidatorPlugIncd其它所有插件类有控制器初始化时实例化。每个插件对象?PLUG-IN />的className属性实例化。这个插件对象遵循JavaBeans规范的设计模?对于每个定义?PLUG-IN />元素的属性都提供了属性处理方法。一旦一个插件实例化Q它的initҎ(gu)被调用,以让开发h员完成插件自q实例化操作。比如,ValidatorPlugIn.initҎ(gu)会初始化它的资源q用ValidatorPlugIn.VALIDATOR_KEY保存资源C下文中;q些资源在创徏框架的上下文中的org.apache.commons.validator.Validatorcȝ实例时用。控制器初始化的插g用Action.PLUG_INS_KEY关键字,把org.apache.struts.action.PlugIn对象的数l保存在上下文中Q接着使用控制器的destroyҎ(gu)调用每个插g的destroyҎ(gu)释放h的资源?/P>
实现Zhttp协议的请?相应的MVC模式所p的时间和努力会是有利可图的。选择一个合适的框架解决q个问题会提供一个领先的开始,它会允许架构师和开发h员更多的x业务而不是集成。struts也提供了完整的模块比如validator实现表单的声明式校验QTilesl织复合视图Q这些模块加Z框架的功能,极大的简化了设计和开发应用程序的d。更多关于strutsQ安装配|信息可以在http://jakarta.apache.org/struts/userGuide/index.html扑ֈ。因为struts一直在修改Q可能在你读到本文章的时候,一些实现可能发生改变,因此最好通过http://jakarta.apache.org/struts发布的文档和更新声明完成q些内容
[Gof] Design Patterns by Erich Gamma et. al. (Addison-Wesley, 1995)
]]>
分派的角?BR> 像在RequestProcessor一节讨论的一Prequest processor调用request handler的executeҎ(gu)。Q何request handler抛出的异帔R被RequestProcessor捕获然后在strutsconfig.xml中找到可能的
在request handlers中这是一个创建exceptions的基cR它?yu)装了异常发生原因属性(Q和相关的ActionError对象。一个AppException的子cd以提供合适的构造函敎ͼ通过可选的属性名和对象参敎ͼ用消息key正确初始化对象。消息key可以从和异常对应的ExceptionConfig对象中获得。涉及到AppException的API是构造函数列表(可以被子c调用)QAppException作ؓ(f)ExceptionHandler.execute的方法参C递的?/P>
转换异常到ActionErrors?BR> RequestProcessor查询ExceptionConfig的异常处理定义。RequestProcessor创徏特定的ExceptionHandlerq调用它的executeҎ(gu)q传AppException作ؓ(f)参数。org.apache.struts.action.ExceptionHandler的一个默认的异常处理是预先配|在ExceptionConfig对象中的。ExceptionHandler从AppException对象获得ActionError对象Q然后根据ErrorsTag创徏ActionErrors对象使用。如果异怸是AppExceptioncL其承类QExceptionHandler会用定义?EXCETION>元素创徏一个ActionErrors对象。这样就减轻了请求处理的开发h员写额外的异常处理代码。然而这样就限制了框架仅能调用ActionError的一个构造函敎ͼ接收一个key参数倹{如果需要可以用
]]>
if (!isTokenValid(request)) {
errors.add(ActionErrors.GLOBAL_ERROR,
new ActionError("transaction.token.invalid"));
//errors object is of type ActionErrors
}
isTokenValid同步处理session对象的token来阻止表单重复提交请求。在request handlers中,isTokenValidҎ(gu)必须跟一个resetToken来从session中移除token;q样可以保证M后箋h都将DisTokenValidq回faQ因此组l表单多ơ提交。request handler的saveTokenҎ(gu)应该被调用来重徏一个新的事务token满下次的请求?BR> 获得表单数据
jsp规范使用
用FormTag初始化ActionForm对象
用前面介l的方式FormTag初始化ActionForm对象Q在HTML表单中的action URL对应
用ActionForm存储表单数据
被承的ActionForm对象是用来存放表单请求对象参数的Q因此他们是和用L(fng)耦合的。一个ActionForm子类是一个带属性存取方法的JavaBeanQ这些属性与HttpServletRequest对象的参数对应。如果一个ActionForm对象通过FormTag创徏Q前面介l了Q,那么在接下来通过FormTag解析的表单请求将由RequestProcessor在特定范围处理。表单通过相关的action映射标识扑ֈ。RequestProcessor为重|表单属性,通常表单带有h旉参数Q然后调用表单对象的validateҎ(gu)完成服务端校验用戯入。仅当ActionMapping对象的校验属性设为trueӞvalidateҎ(gu)才会被调用。这是一个默认的行ؓ(f)。用request.getParameterValues(parameterName)获得一个String数组对象Q这个对象用来存放表单数据;在请求参数类型{换一节将做解释。校验结构是一个ActionErrors对象Q在错误处理一节解释了Q,它用org.apache.struts.taglib.html.ErrorsTag昄校验错误l用戗ActionForm也能存储中间层模型状态,q些状态数据接下来会视图(jspQ引用ƈ展示l用戗?BR> 一个ActionFormcM可以被RequestProcessor创徏。这U情况发生在D到URLQ该URL映射到控制器servlet而不是jspQ相关的action映射定义了表单属性。在q种情况下,RequestProcessor搜烦form bean的尝试会D创徏一个新的ActionForm对象Q如果在特定范围没有扑ֈ的话Q或者在特定范围通过
用动态属性创建ActionForm对象
DynaActionForm对象是带动态集合属性的对象。DynaActionForm扩展了ActionForm对象Q通过在struts-config.xml文g中声明来创徏form对象。例子略。RequestProcessor创徏Q操作,校验DynaActionForm的方式和操作ActionForm是一致的Q也是说对于在DynaActionForm的动态属性(定义?FORM-BEAN />元素的动态集合属性)Q请求对象参数是可操作的。其它参数被单蟩q?/P>
h参数cd转换
q节讨论request.getParameterValues(parameterName)获得的String数组cd怎样转换到表单对象的对应属性类型上。下面是支持的目标类型列表?BR>java.lang.BigDecimal
java.lang.BigInteger
boolean and java.lang.Boolean
byte and java.lang.Byte
char and java.lang.Character
double and java.lang.Double
float and java.lang.Float
int and java.lang.Integer
long and java.lang.Long
short and java.lang.Short
java.lang.String
java.sql.Date
java.sql.Time
java.sql.Timestamp
目标cdQ也是说和表单对象属性关联的cd,是通过自省机制扑ֈ的;一个特定struts定制的自省机制是在DynaActionForm对象中用的。struts也支持烦引属性,parameterName[n];索引?开始。这U命名{换的form bean的方法是通过按照下面定义的javabeans规范描述的,使用了烦引属性模式。下面的Ҏ(gu)用来处理所有的索引属性的数组元素?BR>public
public void set
下面的方法是用来处理单独的数l元?BR>public
public void set
下面描述了用简单的属性和索引属性的语法?BR> 1.当bean的属性是数组Q且h参数名没有用烦引符号parameterName[n]Ӟ由request.getParameterValues(parameterName)q回的String[]{换成目标lgcd的数l。由struts框架内部实现该方法。ActionForm子类应该定义下面的方法声明?BR>public void set
public
2.当bean的属性是数组,且请求参数名使用索引W号parameterName[n],由request.getParameterValues(parameterName)q回的String[]被认ؓ(f)仅容U一个简单的|仅String[0]被{换成数组的组件类型。由struts框架内部实现该方法。ActionForm子类应该定义下面的方法声明来接收索引参数?BR>public void set
public
上面的方法声明遵循了javabeans规范中定义的索引属性设计模式。当q些Ҏ(gu)都没有时Q通过实现下面的方法也可以处理索引存取属性?BR>public
在这个场景中Q请求数l的d是通过struts框架处理Q首先获得根本的数组对象然后处理l定序号的元素。这个模式也支持Zlist的请求参数实玎ͼ使用parameterName[n]讉K?BR> 3.对于单的属性类型,由request.getParameterValues(parameterName)q回的String[]被认ؓ(f)仅容U一个简单的|仅String[0]被{换成目标cd。由struts框架内部实现该方法。对于简单的属?ActionForm子类应该定义下面的方法声明?BR>public void set
public
strutsl定的标{ֺ提供了处理简单属性和索引属性的方式Qorg.apache.struts.taglib.nested包容U了q些标签。struts中的完全的标{ֈ表请参?A >http://jakarta.apache.org/struts/userGuide/index.html; 更多的资源请参?A >http://jakarta.apache.org/struts/resources/index.html. struts来的趋势是采用JSTL?BR>JSF上?/SETPROPERTY />
控制器对?/P>
控制器实CActionServletcR它集中处理所有客L(fng)的请求。它清晰的划分了控制层的作用Q处理视囑֒D理Q保留模型处理和操作l请求处理器QCommand objects[Gof]Q处理。发布文档中定义了所有输入请求映到中央控制器的描述Q如下:
所有URIsh以dol尾的都映射到servlet中,如下Q?/P>
匚w该模式的表单h如下所C:
http://www.my_site_name.com/mycontext/actionName.do
映象前缀叫做扩展映象Q然而,你也可以定义路径映象?*l尾Q如?/P>
对应hQ?A >http://www.my_site_name.com/mycontext/do/action_Name
通过配置文g可以不用改变E序代码可以改变映的方式Q这个映方案也涉及到Mulitplexed Resource Mapping。对于所有表现层hQ控制器提供了一个集中处理点。控制器委托h处理器处理每一个请求。请求处理器分配h到相关的form bean处理表单校验Q处理模型。控制器和请求处理器的联合构成了控制器处理机制的核心。由控制器提供的q种抽象减轻了开发h员创建公共应用程序服务比如管理视图,sessionsQ表单数据的力_。开发h员可以遵循标准的机制处理例如Q错误异常处理,DQ国际化Q数据验证,数据转换{?/P>
在Struts1.1中,struts的配|通过控制器的initҎ(gu)加蝲。配|文件控制框架的行ؓ(f)Q包括用ActionMapping配置对象映射URIs 到请求处理器Q配|消息资源,通过插g处理外部资源{。实际上ActionServlet委托所有输入请求给RequestProcessorQ由它实际处理所有请求?/P>
分配器对?/P>
RequestProcessor把请求处理器和关联的form bean联合提供分派和处理客戯求的功能。form bean的错误创建,抛出异常和请求处理器都由RequestProcessor处理Qƈ影响RequestProcessor的视囄理函数。form beans协助RequestProcessor存储表单数据Q或者传递视N要的模型数据。通过strutsQconfig.xml?ACTION />配置。所有请求被控制器委托给分配器,分配器是RequestProcessor对象。RequestProcessorҎ(gu)a(chn)ction标识查请求URIQ利用ActionMapping配置对象Q下一节介l)的信息创求处理对象,调用requesthandler.executeҎ(gu)。该Ҏ(gu)和应用程序的模型交互。根据处理结果,h处理器会q回一个ActionForward配置对象QActionForward是带?FORWARD />元素的运行时表示Q在使用ActionForwardD一节解释)lRequestProcessor。它会用ActionForward对象通过调用RequestDispatcher.forwardҎ(gu)或response.sendRedirectҎ(gu)ȀzM一个视图?/P>
ActionMapping的命令模式(译注Q本节翻译从Q因为涉及到具体语法。)
struts通过xml语法指定URI和servlet的映。这个实现和GOf的命令模式非常相伹{?/P>
模型和RequestHandlers的交?/P>
Action的子cȝ来适配h和模型。一个Action的子cM叫request handlerQ根据具体请求创建。一个action由RequestProcessor最先解释,q返回一个相关的request handler。对应每个请求创建的action的父cȝ分配器对象创建。request handler实现了命令模式。一个客L(fng)h在URI中封装了惌的行为,路径信息由分配器QRequestProcessorQ提取ƈ创徏一个相关的h处理对象实例。命令模式解耦请求处理和UI?/P>
基本的ActioncL供了公用的函数处理框架相关的资源和方法,保存子类executeҎ(gu)执行时检到的错误。这些错误通过使用在用ErrorsTag昄错误一节介l的定制的org.apache.struts.taglib.html.ErrorsTag昄在html表单中。request handler的executeҎ(gu)应该包含控制程处理h参数和相兌的ActionFormQ它应该装模型交互语法Q提供基于模型操作结果的下一个视图。Request handlers由RequestProcessor在第一ơ创建时~存Q给其它h使用Q因此request handlers不能够包含用L(fng)D的状态信息;而且当需要串行处理时Qrequest handlers必须加上同步机制处理资源?/P>
对于分布式应用来_一个actioncd含和EJBlg中的业务逻辑交互的控刉辑Q类g业务委托对象。业务委托得request handlers不用直接处理复杂的分布式lg。因为处理服务端lg的逻辑被嵌入到业务委托中,所以业务委托设计模式request handlers 和服务端lg松耦合。一个request handler由开发h员在表示层编写,然而一个业务委托通常由开发h员在创徏业务层服务时~写。对于小的非分布式应用,actioncd以包含业务逻辑。当不需要分布式处理和业务逻辑嵌入到request handlers中时Q数据处理对象[Core]可以被用来提取数据处理的实现Q它提供了request handlers和数据处理层松耦合Q因此保证表C层不用实现中间层的变化。action的基cL供了方便的方法,请参?A >http://jakarta.apache.org/struts/api/index.html.的API文档
用ActionForwardD
ActionForward对象是配|对象。这些配|对象都有基于有意义名称比如'success','failure'{的唯一标识W保证可以被扑ֈ。request handlers使用装了URL路径的ActionForward对象识别目的视图。ActionForward对象Ҏ(gu)struts-config.xml?FORWARD />元素创徏。例子略?/P>
1.文本Q错误提C,异常提示QGUIlg标签必须攑ֈ资源文g中。这些资源文件容U下面介l的特定的信息?/P>
2.日期Q时_货币Q数字,计量单位和电(sh)话号码必d于本地参数和文化格式化显C?/P>
在今天的全球化市Z个带国际化支持的应用是很重要的。实现国际化功能比在E序开发完后合q多语言要方便得多。国际化c通过JDK提供的本地类处理本地昄。一个本地对象表C一个特定地区的地理Q政治,文化。下面讨论struts怎么实现国际化?/P>
本地对象
strutscL供了118N支持Q用getAttribute(Action.LOCALE_KEY)从HttpSession中获得本地特定信息。本地对象用下面介l的几种方式保存在session中?/P>
使用HtmlTagQ定制的标签org.apache.struts.taglib.html.HtmlTag插入到jsp?q是也声明的方式保存。当locale为trueӞ标签逻辑会用HttpServletRequest.getLocale()Ҏ(gu)获得本地对象。getLocaleҎ(gu)q回客户端浏览器ZAcceptQLanguage header接受的内容的首选本地对象。当客户端没有提供一个AcceptQLanguage header一个默认的本地对象返回。如果session不存在就会创建,然后本地对象用Action.LOCALE_KEY存到session对象中。HTML标签接着使用本地对象的语a属性设|特定语a到输出流中。这U方式本地对象存储一ơ;以后的localeQtrue的操作将不能替换session中的本地对象。这U方式最好用在用hҎ(gu)览器本地讄时?/P>
使用action对象
如果要变成改变本地对象,actioncL供了setLocaleҎ(gu)使用Action.LOCALE_KEY保存本地对象到session中。这U设|本地对象的方式最好用在用户通过点击UIlg选择HTML表单的本地化方式时。但是,如果本地化资源正在加载,而用h在改变本地化方式时会引v错误。当一个本地化改变时最好在重置所有本地资源且可控的方式下q行?/P>
使用
在struts-config.xml文g中通过controller标签Q标记RequestProcessor?/P>
国际化提C和标签
因ؓ(f)要支持国际化Q所以所有的错误提示Q指导性的提示Q信息,标题QGUIlg的标{,输入标签必须必须单独保存Q通过本地特定方式处理。struts框架提供了MessageResourcescȝ来模拟JDK提供的ResourceBundlecR本地特定的资源包提供一个分L地特定信息的方式。资源包的成员都使用一个共同的基本名字Q但是名字的额外部分标识不同的本地性。默认的资源包也有同L(fng)基本名字Q没有找到匹配的本地信息时就用默认包。例如:
如果资源包名为MyApplicationResourcesQ这q个包家族的成员名字会是?/P>
MyApplicationResources_en 英文?/P>
MyApplicationResources_fr 法语?/P>
MyApplicationResources_fr_FR 法国的法语包
MyApplicationResources_fr_CA 加拿大的法语?/P>
资源包搜索顺序如下:
1. MyApplicationResources_fr_FR 预期的包
2. MyApplicationResources_fr 预期包没有时扑֮
3. MyApplicationResources_en_US 没有匚w包时用默认包
4. MyApplicationResources_en 没有默认包时用它
5. MyApplicationResources 最基本的包
struts使用MessageResources对象提供相对Ҏ(gu)的方式实Cq的机制。MessageResources对象通过下面的属性文件定义的?值对初始化。你只需要在struts-config.xml定义MessageResources的基本名字,可以按一致的搜烦方式处理本地资源文g?/P>
配置文g中的parameter属性值声明了基本的不带本C息的属性文件。这个基本的资源文g名ؓ(f)MyApplicationResources.propertiesQ本地文件可能取名ؓ(f)MyApplicationResoures_localeSpecificExtension.properties.Ҏ(gu)一个程序,我们可以定义一个或多个基本包名字。消息资源对象由控制器中的ActionServletҎ(gu)Globals.MESSAGES_KEYQ和Action.MESSAGES_KEY相同Q保存到ServletContext中,或者是多个消息资源Ӟ所有消息资源对象?MESSAGE-RESOURCES>元素保存。ؓ(f)了能讉Krequest handlers中的消息资源对象QactioncL供了方便的方法Action.getResources通过消息对象特定的标识Key从ServletContext中获得消息资源。每个消息资源对象通过处理下列的本地属性文件来获得本地消息。属性文仉过配蝲文g参数 要获得本地消息,传递本地消息key参数lMessageResources.getMessage卛_。用Action.LOCALE_KEY可以从session中获得本地对象。当lMessageResources.getMessage提供一个对象参敎ͼ获得的消息将作ؓ(f)一个消息格式模式ƈ转换为消息格式对象。消息格式对象然后调用MessageFormat.formatҎ(gu)同时传递被适当格式化的对象。消息格式化cM是本地特定的Q因此相x息格式模式和对象必须获得本地化信息到帐号中。消息资源API提供了许多方法处理消息;相关JavaDoc可以?A >http://jakarta.apache.org/struts/api/index.html查到?/P>
Titles允许包含模板和组件。实际上所有的机制都是怼的:你定义页面的所有部分(一个TitleQ。每个部分可带参敎ͼ允许动态内容,能够作ؓ(f)一个方法在java代码中用?/P>
注意Q这章的所有例子都是基于Tiles.war?examples目录下的C子?/P>
q篇文章的目的是lstruts用户介绍struts的好处,同时解释光|和用法。我们会对一个健壮的表现层框架下一个定义,同时讨论struts框架如何实现q些要求。我们也探究struts中的设计模式的实玎ͼ控制器的语义Q相兌助组件的语义Q当你需要设计组件和struts框架交互或者ؓ(f)了适应目的特D需要扩展struts框架时这些知识将会非常有用。本文介l的信息可以?A >http://jakarta.apache.org/struts获得?/P>
MVC架构
mvc架构把一个应用分Mؓ(f)3部分Q模型,视图Q控制器。它通常应用于图形交互用h型的输入Q处理,输入?/P>
模型Q一个模型表C应用程序中需要逻辑处理和操作的数据。在应用E序中Q何有E_状态的数据都应该放到模型对象中。提供模型的服务必须支持多个客户端。粗略看看模型的公共Ҏ(gu)列表Q就应该很容易明白怎么控制模型的行为。模型组l相关的数据和操作ƈ提供特定的服务;q些操作的组合包装和抽象了业务逻辑。模型接口公布了处理模型状态的Ҏ(gu)和封装到模型中的复杂业务逻辑的方法。模型服务通过控制器处理模型状态的查询或更攏V当模型状态变化时Q由模型通知视图?/P>
视图Q视图表现模型的状态。表C层语义被封装在视图中,因此同样的模型数据可以适合多个不同cd的客L(fng)。当模型变化q知视图后,p图更新自w。视图传递用戯入到控制器?/P>
控制器:控制器获取和转换用户输入到模型的action中。模型基于用戯入返回处理结果给控制器,由控制器选择适当的视图显C?/P>
在基于J2EE的应用程序中QMVC架构通过JavaBeans或EJB处理业务逻辑Qƈ同表C层JSP分离Q中间通过Z控制器的servlet联系。然而,控制器的设计必须适应不同cd的客L(fng)Q包括web客户端的HTTPhQ无U客L(fng)的WMLQ供应商和业务伙伴的ZXML的文档。拿HTTPh/相应ZQ输入的HTTPh被\由到中央控制器,׃央控制器解释和委托请求到合适的h处理器。这个也涉及到MVC2架构。框架的h处理器提供开发h员实现具体的业务逻辑和模型交互。依赖交互的l果Q控制器可以军_下一个视囑ƈ产生一个正的相应?/P>