问题的提出: 默认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:
// CustomSpecificationResolver.java
//
// Copyright 2004 Michael J. Henderson & Associates LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package com.mjhenderson.users.tapestry;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.tapestry.INamespace;
import org.apache.tapestry.IRequestCycle;
import org.apache.tapestry.IResourceLocation;
import org.apache.tapestry.Tapestry;
import org.apache.tapestry.engine.ISpecificationSource;
import org.apache.tapestry.resolver.ISpecificationResolverDelegate;
import org.apache.tapestry.spec.IComponentSpecification;
/**
* @author <a href="mailto:
[email protected]?subject=com.mjhenderson.users.tapestry.CustomSpecificationResolver">Mike Henderson</a>
*
*/
public class CustomSpecificationResolver implements
ISpecificationResolverDelegate {
private static final Log LOG = LogFactory.getLog(RecursiveFileLocator.class);
private ISpecificationSource _specificationSource;
private RecursiveFileLocator _locator;
//private boolean _applicationIsExplodedWAR;
private boolean _initialized;
private String _folder;
private String _realRootFolder;
public CustomSpecificationResolver() {;
}
public void setFolder(String value) {
_folder = value;
}
public String getFolder() {
return _folder;
}
private void _init(IRequestCycle cycle) {
//IResourceLocation rootLocation = Tapestry.getApplicationRootLocation(cycle).getRelativeLocation("/WEB-INF/");
IResourceLocation rootLocation = Tapestry.getApplicationRootLocation(cycle).getRelativeLocation("/");
//_applicationIsExplodedWAR = rootLocation.getResourceURL().toString().startsWith("file:");
//if (_applicationIsExplodedWAR) {
_realRootFolder = cycle.getRequestContext().getServlet().getServletContext().getRealPath("/");
_locator = new RecursiveFileLocator(rootLocation,_realRootFolder);
_specificationSource = cycle.getEngine().getSpecificationSource();
//}
_initialized = true;
}
// private boolean checkLocationIsFileLocation(IResourceLocation location) {
// String url = location.getResourceURL().toString();
// System.out.println("url = "+url);
// return url.startsWith("file:");
// }
/**
* @see org.apache.tapestry.resolver.ISpecificationResolverDelegate#findPageSpecification(org.apache.tapestry.IRequestCycle, org.apache.tapestry.INamespace, java.lang.String)
*/
public IComponentSpecification findPageSpecification(IRequestCycle cycle,
INamespace namespace, String name) {
if (!_initialized) {
_init(cycle);
}
//if (!_applicationIsExplodedWAR) {
// return null;
//}
IResourceLocation location = _locator.resolveLocation(name+".page");
if (location != null) {
return _specificationSource.getPageSpecification(location);
}
return null;
}
/**
* @see org.apache.tapestry.resolver.ISpecificationResolverDelegate#findComponentSpecification(org.apache.tapestry.IRequestCycle, org.apache.tapestry.INamespace, java.lang.String)
*/
public IComponentSpecification findComponentSpecification(
IRequestCycle cycle, INamespace namespace, String type) {
if (!_initialized) {
_init(cycle);
}
//if (!_applicationIsExplodedWAR) {
// return null;
//}
IResourceLocation location = _locator.resolveLocation(type+".jwc");
if (location != null) {
return _specificationSource.getComponentSpecification(location);
}
return null;
}
}
RecursiveFileLocator.java:
// RecursiveFileLocator.java
//
// Copyright 2004 Michael J. Henderson & Associates LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package com.mjhenderson.users.tapestry;
import java.io.File;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.tapestry.IResourceLocation;
/**
* @author <a href="mailto:
[email protected]?subject=com.mjhenderson.users.tapestry.RecursiveFileLocator">Mike Henderson</a>
*
*/
public class RecursiveFileLocator {
private static final Log LOG = LogFactory.getLog(RecursiveFileLocator.class);
private IResourceLocation _location;
private File realRoot ;
private Map _locations = new HashMap();
public RecursiveFileLocator(IResourceLocation location,String _realRootFolder) {
realRoot = new