2008-02-15
stripes开发
3.2.3 Stripes DispatcherServlet的处理
Filter只是拉开生命周期的序幕,真正的的生活周期处理应该是对action的操作和处理,也就是说重头戏还在DispatcherServlet之中呢。在DispatcherServlet要解决请求的action和程序员实现的action的对应。还有如何找到事件处理方法,如何把数据传入/回传(repopulate)actionbean中,处理验证,处理类型转换(stripes中类型和验证是结合在一起的)、拦截处理等等。Stripes把这个周期分成六段: ActionBeanResolution(解析aciotbean,找到与请求所对应的actionbean), HandlerResolution(找到与请求所对应的处理方法,当然在actionbean), BindingAndValidation(把数据bind到actionbean属性字段和柜架annotation验证), CustomValidation(处理用户的自定义的验证和类型转换), EventHandling(执行请求所对应的处理方法,即事件处理),ResolutionExecution(处理事件方法完成之后的流程转向,是跳转到Jsp页面、流输出等) 看一下代码:protected void doPost(final HttpServletRequest request, final HttpServletResponse response)
throws ServletException {
//判断annotation验证或类型转换的错误出现,还要不要继续处理验证方法。默认否;
doOneTimeConfiguration();
log.trace("Dispatching request to URL: ", request.getRequestURI());
PageContext pageContext = null;
try {
//从stripesFilter中取得线程安全的配置对象
final Configuration config = StripesFilter.getConfiguration();
// First manufacture an ActionBeanContext
final ActionBeanContext context =
config.getActionBeanContextFactory().getContextInstance(request, response);
context.setServletContext(getServletContext());
// Then setup the ExecutionContext that we'll use to process this request
final ExecutionContext ctx = new ExecutionContext();
ctx.setInterceptors(config.getInterceptors(LifecycleStage.ActionBeanResolution));
ctx.setLifecycleStage(LifecycleStage.ActionBeanResolution);
ctx.setActionBeanContext(context);
//主要为了在annotation验证能用到jsp的EL表达式而生成jsp的//pageContext对象。有可能有的容器不支持这种用法。也就是说
// stripes的EL验证有可能会失效。Tomcat支持。
try {
ActionBeanContext abc = ctx.getActionBeanContext();
pageContext = JspFactory.getDefaultFactory().getPageContext(this, // the servlet inst
abc.getRequest(), abc.getResponse(), null, abc.getResponse().getBufferSize(),
true); DispatcherHelper.setPageContext(pageContext);
}
catch (Exception e) {
saveActionBean(request);
//解析aciotbean,找到与请求所对应的actionbean
Resolution resolution = resolveActionBean(ctx);
//找到与请求所对应的处理方法,当然在actionbean
if (resolution == null) {
resolution = resolveHandler(ctx);
// 把数据bind到actionbean属性字段和柜架annotation验证
if (resolution == null) {
// Then run binding and validation
resolution = doBindingAndValidation(ctx);
//处理用户的自定义的验证
if (resolution == null) {
// Then continue on to custom validation
resolution = doCustomValidation(ctx);
//处理验证错误
if (resolution == null) {
// And then validation error handling
resolution = handleValidationErrors(ctx);
//调用事件处理方法
if (resolution == null) {
// And finally(ish) invoking of the event handler
resolution = invokeEventHandler(ctx);
// 事件处理方法出现验证错误,就进行错误处理
DispatcherHelper.fillInValidationErrors(ctx);
}
}
}
}
}
// Whatever stage it came from, execute the resolution
if (resolution != null) {
executeResolution(ctx, resolution);
}
}
catch (ServletException se) { throw se; }
catch (RuntimeException re) { throw re; }
catch (InvocationTargetException ite) {
if (ite.getTargetException() instanceof ServletException) {
throw (ServletException) ite.getTargetException();
}
else if (ite.getTargetException() instanceof RuntimeException) {
throw (RuntimeException) ite.getTargetException();
}
else {
throw new StripesServletException
("ActionBean execution threw an exception.", ite.getTargetException());
}
}
catch (Exception e) {
throw new StripesServletException("Exception encountered processing request.", e);
}
finally {
// Make sure to release the page context
if (pageContext != null) {
JspFactory.getDefaultFactory().releasePageContext(pageContext);
DispatcherHelper.setPageContext(null);
}
//把actionbean保存在request中
restoreActionBean(request);
}
}
上面的代码首先从actionbean上下文工厂(ActionBeanContextFactory)中创建该请求的actionbean上下文(ActionBeanContext),该context主要是为了隔离容器和actionbena之间的高耦合的关系。在structs中,action能直接调用request、response一直为人们诡病。Stripes把request、response、servletcontext等全封装在ActionBeanContext。这样actionbean更好单元测试。看一下:
ActionBeanContext.javaprivate HttpServletRequest request;
private HttpServletResponse response;
private ServletContext servletContext;
private String eventName;
private ValidationErrors validationErrors;
除了上面三种,actionbeanContext还封装了这次请求的处理方法名,和该actionbean所有出现的验证错误。我们有可能有时候要在处理方法中验证和事务结合的验证。这时我们可以用上下文中取得validationErrors,把我们手动生成的Error(如:SimpleError、LocalizableError)放在validationErrors中,stripes会自动把它传到页面和<s:errors>结合起来。Actionbean如需要和外面交互,都可以通过上下文来交互。Stripes的开发者Tim fenne就是建议我们自已继承actionbeanContext,写出自己的上下文,把系统通用的一些东西放在上下文,比如,等陆的用户信息等。
创建了actionbeanContext,接下来就是解析actonbean.stripes现在默认的解析方式是基于命名的解析方式(NameBasedActionResolver),这种解析方式是建立在annotation的urlBind()基础之上。我们可以用actionbean类的urlbind(“XXX”)的annotation来建立请求的URL地址和actionbean对应,还可以用现在流利的约定俗成的命名方法:比如:Register.action就可以访问RegisterAction的actionbean(具体后面分析)。找到actionbean的类之后,就是创建该的对象。由于actionbean可以放在httpsession中(建立不要用),如果标记了@SessionScope的actionbean就有可能使用原来的对象了。actionbean是基于接口的实现,每个action都实现setContext(ActionBeanContext context)。Stripes接下来要做是就是我们梦寐以求的事:调用setContext(context),把ActionBeanContext传到我们的actionbean中来,我们就可以用到ActionBeanContext的强大功能了。接下来就是把该实例化的actionbean放在request的actionBean属性中,让接下的程序或页面中调用。 找到了actionbean,接下就是要找到事件的处理方法了,比如第二章的regiser事件。怎么找到处理的事件呢,stripes首先从RequestParams中取,我们提交的表单字段全都是RequestParams,如果没有取到,再从请求的路径中取,如果路径没有取到,再看RequestParams中_eventName的值能不能取到。最后就是取默认的处理方法(标记为@DefaultHandler)。一般的处理方法都是从RequestParams中取到的, 这里的取的是RequestParam名,而不是值,要注意的是:如第二章:regiseraction有两个处理方法,checkname,register.我们点两个按钮同一时刻只有一个事件,但是假如我们有一个文本字段为checkname,这个在register按键之前,当我们按register,stripes也只能取到第一个处理方法checkname,而不会去体会register。这样的话,就出错了。有时候,我们会写这样:/user/register.action/checkname。那么stripes在RequestParams没有取到,就会取checkname的处理方法。 在找到事件处理方法之后,stripes把reqeust中RequestParams捆绑到actionbean的属性字段中。在捆绑的同时进行验证。根据配置,验证通不通过都可以处理定制验证。也就是验证方法的处理。 再之后就是执行actionbean的事件方法。3.3stripes配置
3.3.1闲话配置
说到配置文件,先扯几句,笔者在和朋友聊.net技术,发现.net世界有一种趋势,什么都喜欢用web.config配置文件,而java世界正相反,在反对配置文件。孔子说过:过犹不及。Java用配置文件用过了。而stripnate它的反配置也过度,把Hibernate.cfg.xml中配置也放在web.xml中,结果会形成一个巨大的web.xml文件,又形成了structs-config.xml文件那样。.net世界什么配置都放在web.config中。也会导致这个结果。任何事情都有一个度。 在上一章中们也可以看到Stripes的配置很简单,除了annotaion(这应该不算配置),除下就是全部都在web.xml。其实stripes配置很复杂。Stripes是扩展性极强的框架,基本所有的功能模块都解耦的,完成可以在web.xml中stripesFilter去配置自己的实现类,实现功能强大又适合自己的框架。Stripes中有11种可配置组件,这些组件又可以配置自己的参数。而组合这11个配置组件的配置类也可以配置。我们可以通过stripesFilter来配置扩展连自己都不知道的web框架出来。 Stripes的所有的配置都是通过stripesFilter在web.xml中的<init-param>实现的。没有层次,没有顺序,看起来比较混乱,但是stripes基本都给了我们默认值。我们一般不要去考虑很多,但是对于想完全了解stripes功能和扩展stripes,那就得精通这个配置。Stripenate就是扩展stripes,把stripes和hibernate结合起来,使我们开发中小型的应用系统非常备方便。
发表评论
- 浏览: 6326 次
- 性别:

- 来自: 南昌

- 详细资料
搜索本博客
最近加入圈子
最新评论
-
jquery core 源码分析
樓主夠狠,通讀了源代碼。肯定獲益非淺。
-- by zhouyrt -
Ext.template分析
for指令,if指令等 在 Ext.XTemplate 中实现了
-- by xxf_cz -
jquery core 源码分析
打倒标题党.
-- by jonee -
Ext.Event分析(二)
var args = Array.prototype.slice.call(ar ...
-- by jljlpch -
Ext.Event分析(三)
请排一下版,看起来太费劲了
-- by cagway






评论排行榜