`
ybhuxiao
  • 浏览: 192857 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

懒人策略之:Tapestry4中,去掉累赘的.page文件

阅读更多
写给和我一样的懒人。

/**
 *
 * 原帖地址:http://huxiao.iteye.com/blog/604053
 * 转载请您保留作者信息
 * 
 * @author 杨凯 http://www.blogjava.net/ycyk168
 * @author 胡晓 http://huxiao.iteye.com kskr@qq.com QQ:376665005
 * 
 * @Time 2010-02-26 23:44
 * 
 * 祝大家新年、元宵快乐,祝凯哥步步高升,祝自己工作顺利
 *
 */



一、起因:
    tapestry中,一般我们在.html中写展示程序,用BasePage的子类处理程序,用.page关联.html和Page类。
    因为.page的存在,Page类不管放在哪,只要路径记录在.page文件中,都可以找得到Page类,这样有很大的灵活性,但是同时也造成每次都要写一个.page文件的麻烦。
    实际开发中,考虑到团队合作、开发效率、规范性、条理性等因素,作为一个正常人我们都不会把那些Page类胡乱摆放,通常的做法是路径一一对应,文件名一一对应,这么看起来条理很清晰,时间久了,就寻思,既然路径有了规则,还要.page文件做什么呢?

二、目的:
去掉.page文件,让tapestry根据我们定义的规则去寻找相应的Page类

我这里就实现一种一一对应的关系,如:
/admin/test.html 对应 com.djwl.pages.admin.test.java
/aaa/bbb/ccc/Tapestry.html 对应 com.djwl.pages.aaa.bbb.ccc.Tapestry.java

说干就干,Go !

三、搭建一个最基本的支持tapestry的项目
为了方便演示,我这里新建一个web项目,等下我就用tapestry Quick Start(http://tapestry.apache.org/tapestry4.1/quickstart/helloworld.html)里面的一个例子给大家做例子。

1. 新建一个web工程

2. 下载tapestry v4.1.6,解压,jar包copy到lib目录下,编译后如下图所示



3. web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.4" 
	xmlns="http://java.sun.com/xml/ns/j2ee" 
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
	xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee 
	http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">

  <servlet>
    <servlet-name>app</servlet-name>
    <servlet-class>org.apache.tapestry.ApplicationServlet</servlet-class>
    <load-on-startup>0</load-on-startup>
  </servlet>
  <servlet-mapping>
    <servlet-name>app</servlet-name>
    <url-pattern>/app</url-pattern>
  </servlet-mapping>

</web-app>



4. 在根目录下新建Home.html文件,里面输出一个new java.util.Date().toLocaleString(),
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>Home.html</title>

<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
<meta http-equiv="description" content="this is my page">
<meta http-equiv="content-type" content="text/html; charset=gbk">

</head>
  
<body>
	<span jwcid="@Insert" value="ognl:new java.util.Date().toLocaleString()"></span>
</body>
</html>



至此,如果不出什么意外,运行项目,在地址栏中输入地址(如http://localhost:8080/app)应该就可以访问了,这一步如果你没看懂,可以去看一下tapestry的文档,我这里就不再赘述了

四、分析
ps:这一部分是分析,讲述代码一步一步怎么来的,如果你着急也可以跳过此步直接看下一步总结出来的代码,但是分析过程还是很重要的,就像谈恋爱一样,过程大于结果嘛

1. 寻找突破口
细心的朋友可能已经注意到,我上面的Home.html其实并没有.page文件,纯粹的html文件肯定是不能解析new java.util.Date().toLocaleString()这段程序的,所以说Home.html实际上肯定对应了某个Page类,当然并不是我们新建的,我们上面并没有新建任何类,说到这里其实已经很明了了,这个类就是我们新建Page类要继承的org.apache.tapestry.html.BasePage.java

也就是说,当系统找不到.page文件的时候,他会用BasePage作为该html的对应Page类,那么我们能不能照葫芦画瓢,当没有.page文件的时候,让系统根据html的文件名和路径去找与之对应的Page类呢?

2. 初试牛刀
经过一番测试,发现完全模仿一边tapestry的思路并不容易,按照我们上面的思路,需要判断.page死否存在,如果存在则如何,如果不存在又如何,这个判断做起来相对复杂。但是我们有一个简单的路可走。既然tapestry已经判断好了,那么我们何必还要去判断呢?

打个简单的比喻吧,暑假期间,你去美国找你的朋友小明玩儿。一天小明和你一起去菜市场买猪肉,A和B在卖肉(.page存在和不存在),甲上前问价钱,如果A便宜就买A的(如果.page存在就根据.page找),否则买B的(否则使用BasePage类)。这时你也想买肉,但是英语不好不好问屠夫价钱(就是我们上面的问题,不好判断.page是否存在)。试问,如果遇到这种情况你会怎么办呢?

我觉得你会问小明,对吗?回到我们这上面来,既然tapestry判断并知道了.page是否存在,那么我们问问tapestry不就ok了吗?

tapestry这个小明出国多年,汉语讲得很一般,我跟他交流了半天,他才告诉我,存在不存在不知道,但是我准备买B的肉(使用BasePage类)

就是在这里,他告诉我的,org.apache.tapestry.pageload.PageLoader.java中的instantiatePage方法:

	private IPage instantiatePage(String name, INamespace namespace, IComponentSpecification spec) {
		Location location = spec.getLocation();
		ComponentClassProviderContext context = new ComponentClassProviderContext(name, spec, namespace);
                  
                  // 这个className,就是他要使用的Page类的路径
		String className = _pageClassProvider.provideComponentClassName(context);


                  // 这个if是我加的,其他的代码都是原来的
                     // 那么我们就可以判断,如果他使用BasePage,说明.page不存在,那么我们就去找我们对应的Page类啦!!
		if (StringUtils.equals(className, "org.apache.tapestry.html.BasePage")) {
			String fullName = namespace.constructQualifiedName(name);
			className = "com.djwl.pages." + fullName.replaceAll("/", ".");
		}

		Class pageClass = _classResolver.findClass(className);

		if (!IPage.class.isAssignableFrom(pageClass)) {
			throw new ApplicationRuntimeException(PageloadMessages.classNotPage(pageClass), location, null);
		}

		String pageName = namespace.constructQualifiedName(name);

		ComponentConstructor cc = _componentConstructorFactory.getComponentConstructor(spec, className);

		IPage result = (IPage) cc.newInstance();

		result.setNamespace(namespace);
		result.setPageName(pageName);
		result.setPage(result);
		result.setLocale(_locale);
		result.setLocation(location);

		return result;
	}


改好了这个之后,我们新建com.djwl.pages.Home.java文件试一下:
package com.djwl.pages;

import org.apache.tapestry.html.BasePage;


public abstract class Home extends BasePage {

}



重启,浏览,没有问题

作为一个态度严谨的程序员-_-!! 为了进一步证实他对应的真的是我们的Home.java而不是BasePage,我们还是再做一个测试吧,在Home.java里面定义一个变量在前台输出出来:

Home.java
package com.djwl.pages;

import org.apache.tapestry.html.BasePage;

public abstract class Home extends BasePage {

	private String info = "hello, huxiao";

	public String getInfo() {

		return info;
	}

}




Home.html
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>Home.html</title>

<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
<meta http-equiv="description" content="this is my page">
<meta http-equiv="content-type" content="text/html; charset=gbk">

</head>
  
<body>
	<span jwcid="@Insert" value="ognl:new java.util.Date().toLocaleString()"></span>
	<span jwcid="@Insert" value="ognl:info"></span>
</body>
</html>



哇塞,居然有成功了!!我们就是天才啊,这程序,太完美了!!

3. 问题又来了

然而我们高兴的还太早,也许当前你还没有发现问题,但是当你使用过一段时间之后,你就会发现,经过我们上面的修改,我们以后的工作更累啦-_-!!程序员就是代码机器啊代码机器……

原因是,对于Home.html,他就去找Home.java。有一天你或者你的美工朋友写一个纯静态的test.html,发现页面上豁然写着“An exception has occurred. ”,原因很明显啊,tapestry发现没有.page文件,去找 BasePage,半路被我们截住,去找test.java,问题来了,没人写过test.java啊,当然找不到了,当然报错了。

ok,我们强忍了,写一个空的类test.java,继承一下BasePage,算是ok了,但是有一天你发现,你的美工朋友引用了一个叫fckeditor的东西(当然也可能是别的),里面有几十上百个html文件。。。编码机器啊……

4. 解决问题

我曾一度写了n个空的Page类(n约等于30~50,大虾们不要笑俺,俺一直在努力),终于有一天美工朋友新添加的几十个html文件把我敲醒了,愣了半响,发现原来是一个多么easy的问题,哎,白写了这么多多余的Page类

还是刚才那个PageLoader类,在if代码段,下面加上这个try,catch,意思是,如果类不存在,再去找BasePage去,呵呵,又绕回去了
		/**
		 * 经过上面的修改,似乎大功告成了,但是问题来了,凡是没有.page文件的html,
		 * tapestry会去寻找对应的Page类,如果这个Page类不存在,就会出错,
		 * 这意味着你必须为每个html文件写一个对应的Page类,哪怕是一个纯静态文件,你也要写一个空的Page与之对应
		 * 
		 * 解决办法是还原tapestry的处理方式,没有.page是吧,那么都交给一个默认的类去处理,
		 * 我这里就交给默认的那个BasePage了,你也可以交给你自定义的Page类
		 * 到这里就搞定啦
		*/
		try {
			Class c = Class.forName(className);
			Object.class.isAssignableFrom(c);
		} catch (Exception e) {
			System.out.println("Class \"" + className + "\" not found.We will use \"org.apache.tapestry.html.BasePage\" instead.");
			className = "org.apache.tapestry.html.BasePage";
		}


五、总结一下

说了这么多,我们实际上就修改了一个方法的几句话,如下:

org.apache.tapestry.pageload.PageLoader.instantiatePage(String, INamespace, IComponentSpecification):


	private IPage instantiatePage(String name, INamespace namespace, IComponentSpecification spec) {
		Location location = spec.getLocation();
		ComponentClassProviderContext context = new ComponentClassProviderContext(name, spec, namespace);

		String className = _pageClassProvider.provideComponentClassName(context);

		/**
		 * 如果没有.page文件,那么我们就去寻找自定义的类,当然要找哪个类,规则是你自己定义的
		 * 
		 * 我这里的规则是,root下的html文件和com.djwl.pages包下面的类文件一一对应
		 * 如"/admin/test.html" --> "com.djwl.pages.admin.testPage.java"
		 */
		if (StringUtils.equals(className, "org.apache.tapestry.html.BasePage")) {
			String fullName = namespace.constructQualifiedName(name);
			className = "com.djwl.pages." + fullName.replaceAll("/", ".");
		}
		
		/**
		 * 经过上面的修改,似乎大功告成了,但是问题来了,凡是没有.page文件的html,
		 * tapestry会去寻找对应的Page类,如果这个Page类不存在,就会出错,
		 * 这意味着你必须为每个html文件写一个对应的Page类,哪怕是一个纯静态文件,你也要写一个空的Page与之对应
		 * 
		 * 解决办法是还原tapestry的处理方式,没有.page是吧,那么都交给一个默认的类去处理,
		 * 我这里就交给默认的那个BasePage了,你也可以交给你自定义的Page类
		 * 到这里就搞定啦
		*/
		try {
			Class c = Class.forName(className);
			Object.class.isAssignableFrom(c);
		} catch (Exception e) {
			System.out.println("Class \"" + className + "\" not found.We will use \"org.apache.tapestry.html.BasePage\" instead.");
			className = "org.apache.tapestry.html.BasePage";
		}

		Class pageClass = _classResolver.findClass(className);

		if (!IPage.class.isAssignableFrom(pageClass)) {
			throw new ApplicationRuntimeException(PageloadMessages.classNotPage(pageClass), location, null);
		}

		String pageName = namespace.constructQualifiedName(name);

		ComponentConstructor cc = _componentConstructorFactory.getComponentConstructor(spec, className);

		IPage result = (IPage) cc.newInstance();

		result.setNamespace(namespace);
		result.setPageName(pageName);
		result.setPage(result);
		result.setLocale(_locale);
		result.setLocation(location);

		return result;
	}


这样就实现了我们的目的,如果是带程序的html,会去找对应的Page类,如果不是,则去找BasePage

这只是一种解决方式,不是最好的,但是可以解决。重要的思考的过程。大家有好的点子也给我分享一下。
Email:kskr@qq.com
QQ:376665005
原帖地址:http://huxiao.iteye.com/blog/604053



  • 大小: 40.2 KB
1
0
分享到:
评论

相关推荐

    tapestry-bin-5.1.0.5

    8. **tapestry-hibernate-NOTICE.txt, tapestry-hibernate-core-NOTICE.txt, tapestry-ioc-NOTICE.txt**:与对应的LICENSE文件类似,这些NOTICE文件列出了在Tapestry的这些特定模块中使用到的第三方组件和它们的版权...

    apache-tapestry-5.3.8-bin.zip

    `apache-tapestry-5.3.8-bin.zip` 是Apache Tapestry 5.3.8版本的二进制发行包,包含了运行和开发Tapestry应用所需的各种库文件。 1. **Tapestry框架**:Tapestry是由Howard Lewis Ship创建的一个MVC(Model-View-...

    tapestry 5 ..........

    - **添加Tapestry依赖项**:在项目的`pom.xml`文件中添加必要的Tapestry依赖项。 - **创建初始页面**:根据Tapestry的约定创建初始页面和组件。 - **运行项目**:使用IDE内置的功能或者命令行工具运行项目。 #### 4...

    Tapestry4开发指南.rar

    《Tapestry4开发指南》是一份针对Tapestry 4框架的详尽教程,旨在帮助开发者深入理解和熟练运用这一强大的Web应用开发工具。Tapestry是一个开源的Java框架,由Apache软件基金会维护,它提供了组件化、MVC模式以及...

    Tapestry5, Packt.Publishing.Tapestry.5.Building.Web.Applications.Jan.2008.RETAiL.eBOOk-sUppLeX.pdf

    1. **组件化编程**:Tapestry5的核心理念之一就是组件化编程。这意味着开发者可以将复杂的用户界面分解成小而独立的组件,每个组件都可以独立管理其状态和行为。这种方式有助于提高代码的复用性和可维护性。 2. **...

    优化大使tapestry-bin-5.0.18.zip

    4. **Tapestry Upload**:此模块专注于处理文件上传功能,提供了处理用户通过表单上传文件的工具和API。LICENSE和NOTICE文件将详细阐述文件上传功能的使用和版权限制。 5. **Tapestry Spring**:Tapestry与Spring...

    Manning.Tapestry.in.Action.Mar.2004.rar

    这本书的PDF文件包含了完整的文本内容,读者可以通过阅读获取上述所有知识,并通过书中示例进行实践操作,提升对Tapestry框架的理解和应用能力。对于想要深入学习和使用Tapestry的Java Web开发者来说,这是一份非常...

    apache-tapestry-5.3.7-bin.zip

    Apache Tapestry是一个强大的Java web应用程序框架,由Apache软件基金会维护,专注于构建动态、交互式的Web应用。Tapestry 5.3.7是该框架的一个版本,提供了许多增强的功能和改进,以帮助开发者更高效地构建高质量的...

    Tapestry5开发文档手册.doc

    在Eclipse中导入Tapestry 5 应用的WAR文件,或者使用Maven的quickstart原型来创建新项目。一旦项目设置完成,可以通过Run As &gt; Run on Server启动应用,访问http://localhost:8080/app即可看到运行的Tapestry应用。 ...

    Tapestry.5.Building.Web.Applications.pdf

    ### Tapestry 5:构建 Web 应用程序 #### 一、Tapestry 5 概述 Tapestry 5 是一个强大的 Java Web 开发框架,它为开发者提供了高效且简洁的方式去创建复杂的 Web 应用程序。本书《Tapestry 5:构建 Web 应用程序》...

    tapestry-src-5.1.0.5.zip

    包含: tapestry 的源代码, tapestry集成spring2.0 tapestry快速启动 tapestry upload tapestry hibernate tapestry annotations

    Tapestry-3-Getting Started.doc

    ### Tapestry 3入门教程知识点概述 #### 一、项目背景与目标 - **项目名称**:Tapestry-3-Getting Started - **项目目标**:开发一个基于Web的货币转换器应用。 - **技术栈**:Tapestry 3、Eclipse IDE、Apache ...

    tapestry-bin-5.0.14.zip

    标题中的“tapestry-bin-5.0.14.zip”指的是Tapestry的最新版本5.0.14的二进制发行包,它包含了开发人员构建基于Tapestry应用所需的所有组件和库。 Tapestry 5.0.14的发布旨在提供更加稳定和高效的开发环境,为...

    Tapestry 4 官方文档中版本

    Tapestry 4的核心特性之一是组件化。它允许开发者将UI分解为可重用的组件,每个组件有自己的独立逻辑和视图。这样不仅提高了代码的复用性,还简化了复杂应用程序的维护。 2. **MVC模式**: 虽然Tapestry 4不是...

    Packt.Publishing.Tapestry.5.Building.Web.Applications.Jan.2008.pdf

    ### Tapestry 5:构建Web应用程序 #### 一、引言 Tapestry 5是一款功能强大且易于使用的Java Web开发框架,它旨在简化复杂的Web应用程序的开发过程。本书《Packt Publishing Tapestry 5 Building Web Applications ...

    Tapestry 5 Building Web Applications.pdf

    - **配置文件详解**:解析 Tapestry 5 配置文件的各个部分及其功能。 ##### 3. **组件开发** - **基本组件开发**:教授如何创建简单的组件并将其嵌入到页面中。 - **高级组件特性**:介绍更复杂的组件功能,如事件...

    tapestry官方中文文档

    虽然Tapestry 4的中文文档较少,但提供的《Tapestry4 用户指南》和《Tapestry4 快速启动》是宝贵的参考资料。它们将帮助初学者理解Tapestry的基本概念、组件使用、事件处理等方面的知识。 总的来说,Tapestry 4是...

    Tapestry-3.0.rar

    4. **模板和组件脚本**:Tapestry使用HTML模板文件来定义页面布局,而组件脚本(如JSP或FreeMarker)则用来插入动态内容和逻辑。 5. **URL映射**:Tapestry通过URL映射自动将URL与页面和组件对应,无需手动配置,...

Global site tag (gtag.js) - Google Analytics