jojo's blog--快乐忧伤都与你同在
为梦想而来,为自由而生。 性情若水,风起水兴,风息水止,故时而激荡,时又清平……
posts - 11,  comments - 30,  trackbacks - 0
http://tech.blogbus.com/logs/139683.html

  在Spring最新的文档里,有关于如何将Tapestry整合到Spring里去的说明,见这里http://www.springframework.org/docs/reference/view.html#view-tapestry。Spring中文论坛应该会翻译出来,我就不做重复的工作,只摘要说明一下。

  先看看Tapestry。下图说明了Tapestry是怎么样获取到service的。

  在文档里,基于Tapestry和Spring的应用被划分成五层,我们只关注前边两层:User Interface Layer和Service Layer。这种划分对于单独使用Tapestry的应用也是成立的,从上图可以看出,那是对Service Layer的操作。当进行整合之后,User Interface Layer仍然是由Tapestry提供,而Service Layer则由Spring接手来提供。

  Service实际上就是Bean,Tapestry原本一套取得Service的机制:getEngine()->getService()。现在,我们用Spring将这些Serviec,也就是Bean管理起来,那么,要解决的问题就只有一个,如何让Tapestry获得由Spring管理起来的的Service?

  在Application Context里我们定义了需要被调用的Bean(见文档),我们给它个名字就userService。那么,在Tapestry的page里,就需要载入这个context,然后取得beanA。

  一个最简单的方法是利用Spring的static工具WebApplicationContext在Tapestry page对应的Java class definition里直接载入Application Context,并取得userService。

WebApplicationContext appContext = WebApplicationContextUtils.getApplicationContext(
        getRequestCycle().getRequestContext().getServlet().getServletContext());
    UserService userService = appContext.getBean("userService");

  不过这种用法和我们用Spring的原意有点违背——这不符合DI模式。应该在page里才决定我们调哪个Service。

  所以,推荐的做法如下。

  第一步,让Tapestry page能够获得ApplicationContext,但这次不直接由Tapestry page来做,因为在我们需要访问ApplicationContext的时候,Tapestry page很难拿到ServletContext,所以我们将其放到Enging里去做。代码如下:

package com.whatever.web.xportal;
...
import ...
...
public class MyEngine extends org.apache.tapestry.engine.BaseEngine {
 
    public static final String APPLICATION_CONTEXT_KEY = "appContext";

    protected void setupForRequest(RequestContext context) {
        super.setupForRequest(context);
    
        // insert ApplicationContext in global, if not there
        Map global = (Map) getGlobal();
        ApplicationContext ac = (ApplicationContext) global.get(APPLICATION_CONTEXT_KEY);
        if (ac == null) {
            ac = WebApplicationContextUtils.getWebApplicationContext(
                context.getServlet().getServletContext()
            );
            global.put(APPLICATION_CONTEXT_KEY, ac);
        }
    }

  这样就把ApplicationContext放到了global里去,然后我们指定MyEngine是后边应用里实际使用的的Engine:

<application
    name="Whatever xPortal"
    engine-class="com.whatever.web.xportal.MyEngine">
</application>

(写着写着又像翻译了……不爽-_-)

  第二步,在Tapestry page里取得Bean,代码如下:

<property-specification name="userService"
                        type="com.whatever.services.service.user.UserService">
    global.appContext.getBean("userService")
</property-specification>

  第三步,在page对应的Java class definition增加一个abstract访问者,也就是一个abstract getter
方法。代码如下:

public abstract UserService getUserService();

  当Tapestry实际载入页面的时候,会对类文件执行runtime code方法以增加定义了的properties,并将上边的abstract getter
方法与新建的fields挂钩起来。(瀑布汗^^|||)

  ok,这就完成了。详细的example请看文档。

  简单总结一下。Tapestry与Spring的整合实际上是把原本由Tapestry自己负责的Service Layer,也就是对Service/Bean的调用,交给Spring负责。实际的切入点,则在于上图所示的Engine处。

posted on 2008-10-05 23:27 Blog of JoJo 阅读(332) 评论(0)  编辑  收藏 所属分类: Programming 相关

只有注册用户登录后才能发表评论。


网站导航:
 

<2024年11月>
272829303112
3456789
10111213141516
17181920212223
24252627282930
1234567

常用链接

留言簿(6)

随笔档案

文章分类

文章档案

新闻分类

新闻档案

相册

收藏夹

搜索

  •  

最新评论

阅读排行榜

评论排行榜