`

自由组织Tapestry页面规范文件

阅读更多
问题的提出:

默认Tapestry的页面模板文件(.html)及其对应的规范文件(.page),可以放在web根目录或其下的WEB -INF/目录中,Tapestry可以不用任何配置(在以前的版本中需要在.application文件中定义一下页面)就能正确运行,如果你需要在这些根目录下以文件系统的目录形式组织你的页面,则Tapestry是不会自动搜索这些子目录的,你必须在.application文件中定义这些不在默认位置的页面。这样一来,每加一个页面都需要定义一下,如果页面数目众多,定义起来就会比较麻烦,如何才能避免这些配置呢?本文的目的就是尝试解决这个问题。

问题的解决:

    本文是在参考文档(http://www.behindthesite.com/blog/C1931765677/E381917869/index.html)源代码的基础上稍作修改而成,主要是为了解决不能在Tomcat中使用的问题。为了更好的了解,朋友们最好能阅读一下原文和原来的代码。主要修改的地方是给RecursiveFileLocator传递一个真实路径地址,以便能够列出目录下面的子目录,从而实现层次查找。
    解决的途径就是定义一个ISpecificationResolverDelegate,以便Tapestry在常规路径下找不到文件时进行处理。
    CustomSpecificationResolver.java:

   1.
   2. // CustomSpecificationResolver.java
   3. //
   4. // Copyright 2004 Michael J. Henderson & Associates LLC
   5. //
   6. // Licensed under the Apache License, Version 2.0 (the "License");
   7. // you may not use this file except in compliance with the License.
   8. // You may obtain a copy of the License at
   9. //
  10. //     http://www.apache.org/licenses/LICENSE-2.0
  11. //
  12. // Unless required by applicable law or agreed to in writing, software
  13. // distributed under the License is distributed on an "AS IS" BASIS,
  14. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  15. // See the License for the specific language governing permissions and
  16. // limitations under the License.
  17.
  18. package com.mjhenderson.users.tapestry;
  19.
  20. import org.apache.commons.logging.Log;
  21. import org.apache.commons.logging.LogFactory;
  22. import org.apache.tapestry.INamespace;
  23. import org.apache.tapestry.IRequestCycle;
  24. import org.apache.tapestry.IResourceLocation;
  25. import org.apache.tapestry.Tapestry;
  26. import org.apache.tapestry.engine.ISpecificationSource;
  27. import org.apache.tapestry.resolver.ISpecificationResolverDelegate;
  28. import org.apache.tapestry.spec.IComponentSpecification;
  29.
  30. /**
  31.  * @author <a href="mailto:michaelh@mjhenderson.com?subject=com.mjhenderson.users.tapestry.CustomSpecificationResolver">Mike Henderson</a>
  32.  *
  33.  */
  34. public class CustomSpecificationResolver implements
  35.         ISpecificationResolverDelegate {
  36.    
  37.
  38.     private static final Log LOG = LogFactory.getLog(RecursiveFileLocator.class);
  39.
  40.     private ISpecificationSource _specificationSource;
  41.
  42.     private RecursiveFileLocator _locator;
  43.     //private boolean _applicationIsExplodedWAR;
  44.     private boolean _initialized;
  45.     private String _folder;
  46.     private String _realRootFolder;
  47.    
  48.     public CustomSpecificationResolver() {;
  49.     }
  50.    
  51.     public void setFolder(String value) {
  52.         _folder = value;
  53.     }
  54.    
  55.     public String getFolder() {
  56.         return _folder;
  57.     }
  58.    
  59.     private void _init(IRequestCycle cycle) {
  60.             //IResourceLocation rootLocation = Tapestry.getApplicationRootLocation(cycle).getRelativeLocation("/WEB-INF/");
  61.         IResourceLocation rootLocation = Tapestry.getApplicationRootLocation(cycle).getRelativeLocation("/");
  62.         //_applicationIsExplodedWAR = rootLocation.getResourceURL().toString().startsWith("file:");
  63.         //if (_applicationIsExplodedWAR) {
  64.         _realRootFolder = cycle.getRequestContext().getServlet().getServletContext().getRealPath("/");
  65.         _locator = new RecursiveFileLocator(rootLocation,_realRootFolder);
  66.         _specificationSource = cycle.getEngine().getSpecificationSource();
  67.         //}
  68.         _initialized = true;
  69.     }
  70.    
  71. //    private boolean checkLocationIsFileLocation(IResourceLocation location) {
  72. //        String url = location.getResourceURL().toString();
  73. //        System.out.println("url = "+url);
  74. //        return url.startsWith("file:");
  75. //    }
  76.    
  77.     /**
  78.      * @see org.apache.tapestry.resolver.ISpecificationResolverDelegate#findPageSpecification(org.apache.tapestry.IRequestCycle, org.apache.tapestry.INamespace, java.lang.String)
  79.      */
  80.     public IComponentSpecification findPageSpecification(IRequestCycle cycle,
  81.             INamespace namespace, String name) {
  82.
  83.         if (!_initialized) {
  84.             _init(cycle);
  85.         }
  86.         //if (!_applicationIsExplodedWAR) {
  87.         //    return null;
  88.         //}
  89.         IResourceLocation location = _locator.resolveLocation(name+".page");
  90.         if (location != null) {
  91.             return _specificationSource.getPageSpecification(location);
  92.         }
  93.         return null;
  94.     }
  95.
  96.     /**
  97.      * @see org.apache.tapestry.resolver.ISpecificationResolverDelegate#findComponentSpecification(org.apache.tapestry.IRequestCycle, org.apache.tapestry.INamespace, java.lang.String)
  98.      */
  99.     public IComponentSpecification findComponentSpecification(
100.             IRequestCycle cycle, INamespace namespace, String type) {
101.        
102.         if (!_initialized) {
103.             _init(cycle);
104.         }
105.         //if (!_applicationIsExplodedWAR) {
106.         //    return null;
107.         //}
108.         IResourceLocation location = _locator.resolveLocation(type+".jwc");
109.         if (location != null) {
110.             return _specificationSource.getComponentSpecification(location);
111.         }
112.         return null;
113.     }
114.
115. }
116.



RecursiveFileLocator.java:

   1.
   2. // RecursiveFileLocator.java
   3. //
   4. // Copyright 2004 Michael J. Henderson & Associates LLC
   5. //
   6. // Licensed under the Apache License, Version 2.0 (the "License");
   7. // you may not use this file except in compliance with the License.
   8. // You may obtain a copy of the License at
   9. //
  10. //     http://www.apache.org/licenses/LICENSE-2.0
  11. //
  12. // Unless required by applicable law or agreed to in writing, software
  13. // distributed under the License is distributed on an "AS IS" BASIS,
  14. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  15. // See the License for the specific language governing permissions and
  16. // limitations under the License.
  17.
  18. package com.mjhenderson.users.tapestry;
  19.
  20. import java.io.File;
  21. import java.net.URL;
  22. import java.util.ArrayList;
  23. import java.util.HashMap;
  24. import java.util.Iterator;
  25. import java.util.List;
  26. import java.util.Map;
  27.
  28. import org.apache.commons.logging.Log;
  29. import org.apache.commons.logging.LogFactory;
  30. import org.apache.tapestry.IResourceLocation;
  31.
  32. /**
  33.  * @author <a href="mailto:michaelh@mjhenderson.com?subject=com.mjhenderson.users.tapestry.RecursiveFileLocator">Mike Henderson</a>
  34.  *
  35.  */
  36. public class RecursiveFileLocator {
  37.    
  38.     private static final Log LOG = LogFactory.getLog(RecursiveFileLocator.class);
  39.
  40.     private IResourceLocation    _location;
  41.    
  42.     private File realRoot ;
  43.    
  44.     private Map _locations      = new HashMap();
  45.    
  46.     public RecursiveFileLocator(IResourceLocation location,String _realRootFolder) {
  47.         realRoot = new File(_realRootFolder);
  48.         _location = location;
  49.     }
  50.
  51.     /* (non-Javadoc)
  52.      * @see org.apache.tapestry.INamespace#getPageSpecification(java.lang.String)
  53.      */
  54.     public IResourceLocation resolveLocation(String expectedName) {
  55.         if (LOG.isDebugEnabled()) {
  56.             LOG.debug("getLocation("+expectedName+")");
  57.         }
  58.         IResourceLocation location = _resolveThisFolderLocation(expectedName);
  59.         if (location == null) {
  60.             location = _resolveChildFolderLocation(expectedName);
  61.         }
  62.         return location;
  63.     }
  64.
  65.    
  66.     private IResourceLocation _resolveThisFolderLocation(String expectedName) {
  67.         if (LOG.isDebugEnabled()) {
  68.             LOG.debug("_resolveThisFolderLocation("+expectedName+")");
  69.         }
  70.         IResourceLocation location = (IResourceLocation)_locations.get(expectedName);
  71.         if (location == null) {       
  72.             location = _location.getRelativeLocation(_location.getPath()+"/"+expectedName);
  73.            
  74.             if (location.getResourceURL() == null) {
  75.                 return null;
  76.             }
  77.             _locations.put(expectedName, location);
  78.         }
  79.         return location;
  80.     }
  81.    
  82.    
  83.     private IResourceLocation _resolveChildFolderLocation(String expectedName) {
  84.         List children = _getChildFolderLocators();
  85.         Iterator iterator = children.iterator();
  86.         while (iterator.hasNext()) {
  87.             RecursiveFileLocator child = (RecursiveFileLocator)iterator.next();
  88.
  89.             if (LOG.isDebugEnabled()) {
  90.                 LOG.debug("_resolveChildFolderLocation() child = " + child + ", expectedName = " + expectedName);
  91.             }
  92.             IResourceLocation location = child.resolveLocation(expectedName);
  93.             if (location != null) {
  94.                 return location;
  95.             }
  96.         }
  97.         return null;
  98.     }
  99.    
100.     public String toString() {
101.         return "RecursiveFileLocator { "+_location+" }";
102.     }
103.    
104.     private List _children = new ArrayList();
105.     private boolean _childrenLoaded = false;
106.    
107.     private List _getChildFolderLocators() {
108.         if (!_childrenLoaded) {
109.             _loadChildFolderLocators();
110.              _childrenLoaded = true;
111.         }
112.         return _children;
113.     }
114.    
115.     private void _loadChildFolderLocators() {
116.        
117.         if (LOG.isDebugEnabled()) {
118.             LOG.debug("_loadChildFolderLocators() this = " + this);
119.         }
120.
121.         File file = realRoot;//new File(path);
122.         if (file.isDirectory()) {
123.             File[] files = file.listFiles();
124.             for (int i = 0; i < files.length; i++) {
125.                 File f = files[i];
126.                 if (f.isDirectory() && !f.getName().equals("classes") && !f.getName().equals("lib")) {
127.                     RecursiveFileLocator child = new RecursiveFileLocator(_location.getRelativeLocation(f.getName()+"/"),file.getAbsolutePath()+"/"+f.getName());
128.                     if (LOG.isDebugEnabled()) {
129.                         LOG.debug("_loadChildFolderLocators() child = " + child);
130.                     }
131.                     _children.add(child);
132.                 }
133.             }
134.         }
135.     }
136. }



.application文件中增加如下定义:

   1.
   2.     <extension name="org.apache.tapestry.specification-resolver-delegate"
   3.             class="com.mjhenderson.users.tapestry.CustomSpecificationResolver"
   4.             immediate="yes">
   5. </extension>   
6.



以上代码已经在Tomcat和JBoss上经过测试,希望朋友们可以在别的应用服务器上帮我测测,呵呵。代码比较粗糙,谁要是发现了什么问题或有什么改进思路,希望能联系我。

顺便提醒一下,在http://www.t-deli.com上有一个Ant Task,可以根据你的页面存放路径自动更新.application文件里面的页面定义,这样似乎定义几百个页面也是很简单的事情,不过我还是倾向于不用配置直接使用的方法,就看你的需要和使用习惯了。
分享到:
评论

相关推荐

    tapestry页面编辑组件

    在本篇文章中,我们将深入探讨Tapestry的页面编辑组件,以及如何利用这些组件创建交互式的用户界面,包括文本框、单选框、多选框和下拉框。 首先,让我们理解什么是Tapestry页面编辑组件。在Tapestry中,组件是可...

    Tapestry 5.4.1 相关jar文件

    1. **tapestry-core.jar**:这是Tapestry框架的核心库,包含了框架的基本组件、服务、事件处理和页面生命周期管理等功能。 2. **tapestry-ioc.jar**:Tapestry依赖注入(IoC)容器,用于管理对象的创建、配置和生命...

    tapestry文件下载实例

    基于tapestry5.0的文件下载实例,已经完美实现,请参考。

    Tapestry

    Tapestry是一个基于Java的全栈Web应用程序框架,它的设计目的是为了简化Web应用开发,提供组件化和高度交互性的页面。Tapestry并不是一个应用服务器,而是一个可以在应用服务器中运行的框架,用于构建动态、复杂的...

    Tapestry 5 電子書

    本书首先会介绍Tapestry 5的基本概念,包括组件模型、事件处理和页面生命周期。组件是Tapestry 5的核心,它们是可重用的、自包含的代码块,可以是简单的HTML元素或者复杂的用户交互逻辑。读者将学习如何创建和定制...

    tapestry官方中文文档

    Tapestry管理着页面和组件的生命周期,包括创建、初始化、渲染和销毁等阶段。开发者可以为每个阶段提供定制的代码,以满足特定需求。 5. **事件处理和页面导航**: Tapestry支持事件驱动的编程模型。当用户与页面...

    Tapestry简单入门.rar_java Tapestry_tapestry

    4. **编写第一个页面**:在Tapestry中,一个页面是由一个或多个组件组成的。你需要定义一个类来表示页面,并在HTML模板中声明组件。 接下来,我们转向"tapestry组件.docx",组件是Tapestry的核心组成部分,它们是可...

    tapestry3开发指南,带tapestry3所有jar包

    2. **模板和元数据**:Tapestry使用HTML模板定义页面布局,并通过元数据(如TML文件)来指定组件的属性和行为。元数据文件通常与HTML模板一起存放,提供了一种声明式配置组件的方式。 3. **请求处理**:当用户发送...

    Tapestry教程

    例如,`Login.html`文件包含了页面的布局和交互元素,其中`jwcid`属性用于指定Tapestry组件。在本例中,我们看到一个简单的用户登录表单,使用`@Shell`定义整个页面,`@Conditional`处理错误消息,以及`@Form`和`@...

    tapestry源码 api等

    7. **Tapestry-webresources**: 处理应用中的静态资源,如CSS、JavaScript文件,确保它们能正确地被浏览器访问。源码展示了资源管理、版本控制和URL生成的实现细节。 8. **Tapestry5-annotations**: 提供了基于Java...

    Tapestry4.1.2 入门-介绍

    相反,Tapestry的核心关注点在于页面、组件、事件、对象、方法和属性的管理。 Tapestry4.1.2 版本基于Servlet技术,构建在request-response模式之上,它将复杂的HTTP交互隐藏在幕后,使得开发者能够专注于业务逻辑...

    Tapestry 5.0.18 环境搭建(eclipse)

    页面配置文件,如`login.tml`和`Result.tml`,是Tapestry应用的核心。`.tml`文件是Tapestry的模板语言,结合HTML和Tapestry指令来定义页面布局和交互。在`login.tml`中,我们看到了一个简单的登录页面,包含一个链接...

    Tapestry通用WEB框架

    5. **页面生命周期**:Tapestry定义了页面从初始化到销毁的完整生命周期。每个页面都有一个对应的Java类,该类在页面加载、提交表单等操作时被实例化和调用。 6. **切换皮肤**:在Tapestry中,可以轻松实现皮肤的...

    tapestry5.2.6 jar包

    8. **上传组件**:tapestry-upload模块提供了文件上传功能,包括文件大小限制、多文件上传等。 9. **日志和许可证**:在提供的LICENSE和NOTICE文件中,可以看到Tapestry 5.2.6遵循的开源许可协议,以及其依赖的其他...

    Tapestry例子

    Tapestry的核心概念包括组件、页面、服务和模块,这些元素共同构成了一个完整的Web应用。 模块(Module)在Tapestry中的作用至关重要,它是Tapestry应用的基础构造单元。模块负责组织相关的组件、服务和配置,使得...

    tapestry5中文文档

    Apache Tapestry 5 是一个基于Java的Web应用开发框架,其设计目的是为了简化Web应用程序的构建,提供组件化的页面构建、输入验证、本地化、状态管理和URL映射等功能。Tapestry 5 强调易用性,不仅对终端用户友好,...

    Tapestry spindle插件下载

    Tapestry通过组件事件处理和页面导航规则来管理应用程序的流程,这使得开发者能够专注于业务逻辑,而不是繁琐的页面跳转和状态管理。 **Tapestry Spindle插件的功能** 1. **代码提示与补全**:Tapestry Spindle...

Global site tag (gtag.js) - Google Analytics