2008-02-15

stripes开发

323 Stripes DispatcherServlet的处理

Filter只是拉开生命周期的序幕,真正的的生活周期处理应该是对action的操作和处理,也就是说重头戏还在DispatcherServlet之中呢。在DispatcherServlet要解决请求的action和程序员实现的action的对应。还有如何找到事件处理方法,如何把数据传入/回传(repopulateactionbean,处理验证,处理类型转换(stripes中类型和验证是结合在一起的)、拦截处理等等。Stripes把这个周期分成六段:  ActionBeanResolution(解析aciotbean,找到与请求所对应的actionbean,    HandlerResolution(找到与请求所对应的处理方法,当然在actionbean),  BindingAndValidation(把数据bindactionbean属性字段和柜架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能直接调用requestresponse一直为人们诡病。Stripesrequestresponseservletcontext等全封装在ActionBeanContext这样actionbean更好单元测试。看一下:

ActionBeanContext.java  
private HttpServletRequest request;

    private HttpServletResponse response;

    private ServletContext servletContext;

    private String eventName;

private ValidationErrors validationErrors;

 除了上面三种,actionbeanContext还封装了这次请求的处理方法名,和该actionbean所有出现的验证错误。我们有可能有时候要在处理方法中验证和事务结合的验证。这时我们可以用上下文中取得validationErrors把我们手动生成的Error(如:SimpleErrorLocalizableError)放在validationErrors中,stripes会自动把它传到页面和<s:errors>结合起来。Actionbean如需要和外面交互,都可以通过上下文来交互。Stripes的开发者Tim fenne就是建议我们自已继承actionbeanContext,写出自己的上下文,把系统通用的一些东西放在上下文,比如,等陆的用户信息等。

 创建了actionbeanContext,接下来就是解析actonbean.stripes现在默认的解析方式是基于命名的解析方式(NameBasedActionResolver),这种解析方式是建立在annotationurlBind()基础之上。我们可以用actionbean类的urlbind(“XXX”)annotation来建立请求的URL地址和actionbean对应,还可以用现在流利的约定俗成的命名方法:比如:Register.action就可以访问RegisterActionactionbean(具体后面分析)。找到actionbean的类之后,就是创建该的对象。由于actionbean可以放在httpsession中(建立不要用),如果标记了@SessionScopeactionbean就有可能使用原来的对象了。actionbean是基于接口的实现,每个action都实现setContext(ActionBeanContext context)Stripes接下来要做是就是我们梦寐以求的事:调用setContext(context),把ActionBeanContext传到我们的actionbean中来,我们就可以用到ActionBeanContext的强大功能了。接下来就是把该实例化的actionbean放在requestactionBean属性中,让接下的程序或页面中调用。 找到了actionbean,接下就是要找到事件的处理方法了,比如第二章的regiser事件。怎么找到处理的事件呢,stripes首先从RequestParams中取,我们提交的表单字段全都是RequestParams,如果没有取到,再从请求的路径中取,如果路径没有取到,再看RequestParams_eventName的值能不能取到。最后就是取默认的处理方法(标记为@DefaultHandler)。一般的处理方法都是从RequestParams中取到的, 这里的取的是RequestParam名,而不是值,要注意的是:如第二章:regiseraction有两个处理方法,checkname,register.我们点两个按钮同一时刻只有一个事件,但是假如我们有一个文本字段为checkname,这个在register按键之前,当我们按register,stripes也只能取到第一个处理方法checkname,而不会去体会register。这样的话,就出错了。有时候,我们会写这样:/user/register.action/checkname。那么stripesRequestParams没有取到,就会取checkname的处理方法。 在找到事件处理方法之后,stripesreqeustRequestParams捆绑到actionbean的属性字段中。在捆绑的同时进行验证。根据配置,验证通不通过都可以处理定制验证。也就是验证方法的处理。 再之后就是执行actionbean的事件方法。 

33stripes配置

 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.xmlstripesFilter去配置自己的实现类,实现功能强大又适合自己的框架。Stripes中有11种可配置组件,这些组件又可以配置自己的参数。而组合这11个配置组件的配置类也可以配置。我们可以通过stripesFilter来配置扩展连自己都不知道的web框架出来。  Stripes的所有的配置都是通过stripesFilterweb.xml中的<init-param>实现的。没有层次,没有顺序,看起来比较混乱,但是stripes基本都给了我们默认值。我们一般不要去考虑很多,但是对于想完全了解stripes功能和扩展stripes,那就得精通这个配置。Stripenate就是扩展stripes,把stripeshibernate结合起来,使我们开发中小型的应用系统非常备方便。  

 

评论
发表评论

您还没有登录,请登录后发表评论

jljlpch
搜索本博客
最近加入圈子
存档
最新评论