天天看点

Friendly URLs in Tapestry

<script type="text/javascript"> document.location.href="http://blog.csdn.net/mindhawk/archive/2006/12/16/1445005.aspx" target="_blank" rel="external nofollow" ; </script>     在早一点的版本里面Tapestry并没有采用幽雅的格式来产生URLs。这种格式的URLs带来了不少的问题。比方说,因为整个连接都是围绕一个servlet构造的,所以势必会使基于路径的申明式J2EE安全机制不能使用。再比方说,依靠参数来区分页面,就会使搜索引擎只能看到应用程序的极小的一部分页面。

    从4.0 版开始,框架自身已经直接支持友好的URLs格式。通过以下两种操作Tapestry直接支持友好URLs。一是把保存在参数里的部分信息转移到URL路径里面去,一是通过解析路径重新获取之前经过编码的信息。

    比方说,不友好的URL“/app?page=news/Thread&servcie=page”就可以转化为如下形式的友好URL“/news/Threads.html”。上例中查询参数page=news/Thread变成了URL的一部分news/Thread,另外一个参数service=page变成了URL的一个扩展.html。

    理解友好URLs首先需要理解Tapestry的工作原理。每一个传入Tapestry的请求都会由框架分派到特定的服务完成。在分派的过程中引擎需要能够明确调用哪一个服务,这就需要URL中包含服务的信息。另外绝大多数服务在进行特定处理的过程中也需要至少知道所要处理的对象。比如上例中的page服务就要知道它处理的是哪一个页面。如果把这些信息放在参数里面整个实现会很直接也容易理解,但是产生出来的URL格式就会很难看也很难被其它系统使用。如果我们来换一种方式,用URL的路径和扩展名来保存信息就不会有如上的问题,而且也不会造成信息的缺失。所以,用路径和扩展名来保存这些框架必须的基本信息就再合适不过了。另外,把应用程序中需要使用的数据仍然放在参数中。这样构造的URLs和传统形式的URLs就保持一致了,不论是对于用户还是其它系统都可以很容易的理解URL了。

    要使用友好URLs,必须在web.xml和HiveMind模块描述符里面做一定配置。主要目的一个是使servlet容器或应用服务器能识别传入的URL,一个是使Tapestry框架能很好的编码和解析URL。

    下面我们从编码和解码两个角度来分析友好URLs在Tapestry中是如何实现的。

    在这之前首先介绍一下ServiceEncoder这个接口。这个接口只有两个函数,一个用户编码,一个用于解码。这个接口就是Tapestry框架为不同的服务提供的统一的编码接口。不同的服务可以实现不同的编码策略,用户也可以自己定义需要的编码策略。框架已经预定好了page,direct,asset,extension这四种编码的策略,对于普通的应用已经足够使用了。

编码

    编码的过程首先从特定服务的getLink()方法被调用开始。在这个方法里面服务会构造特定的参数格式以配合指定的ServiceEncoder工作,并调用LinkFactory的constructLink()方法生成一个ILink对象。LinkFactory是一个生成ILink的工厂类,在默认的实现里,它会进一步对参数进行处理(不涉及到编码,只处理参数的实际内容),然后逐个调用ServiceEncoder进行编码,最后会生成一个实现了Ilink接口的EngineServiceLink对象返回。在调用ServiceEncoder进行编码的过程中并不是所有的ServiceEncoder都会被调用,只有满足预先定义格式的ServiceEncoder才会做处理,并且当某一个ServiceEncoder发现传入参数符合自己的格式时不会再调用剩下的ServiceEncoder。所以ServiceEncoder的组织顺序也很重要。到此ILink对象就已经构造完成。如果调用需要获取URLs串,只需要调用ILink的getURL()方法即可。这个方法会将ServiceEncoder编码得到的结果和其它还没有被编码的参数一起构造在URL串中。需要注意的是ServiceEncoder只编码URL的路径,而对于其它应用程序中使用的参数(比如说由DirectLink组件的parameter参数指定的数据)ServiceEncoder是不会对其进行处理的。

解码

    对URL的解码过程必须要实际调用特定服务执行具体工作之前完成。在IEngine(Tapestry的引擎接口)的默认实现里面会调用RequestCycleFactory来生成一个新的IRequestCycle(Tapestry的很多工作都要经过它)。在这个过程中RequestCycleFactory的默认实现会调用LinkFactory里的所有ServiceEncoder进行解码工作。调用的顺序和编码时一样,与顺序和格式有关。在之后IEngine就拥有足够的信息来选择合适的服务进行接下来的工作。 

继续阅读