十二. 自定义tapestry组件时,如果定义的组件包含有.html模板的话(即:allow-body="no",不使用组件的body,直接用.html的body),则该自定义组件对应的java类必须extends BaseComponent类,否则如果定义的组件的输出是通过对应的java类来输出html标签(没有.html模板,allow-body="yes"),则必须继承AbstractComponent类,并覆盖renderComponent()方法.;
在java中输出Html代码需要使用Markup Writer, 对于有.html模板的自定义组件,在定义该组件的时候需要用 "$content$"的形式来处理该模板中其他的<html/>,<body/>等元素。
对于"$content$"的形式的说明及必要性:
如果自定义的组件模板如下:
<html>
<body jwcid="$content$">
<hr>
Copyright <span jwcid="year">2005</span>. Foo Inc. All rights reserved.
</body>
</html>
说明: <body>有一个"jwcid"属性,说明了是Tapestry 组件.并且发现该组件的 id是"$content$". 这个id对于tapestry来说有相当的意义:它不是一个真实的组件的It ,它主要告诉Tapestry 使之丢掉到当前时间为止的所有该模板的html脚本,只使用其以后的元素(starting from the <hr> tag)作为真实的也面元素。
结果,则在实际的运行过程中被解析为:
<hr>
Copyright <span jwcid="year">2005</span>. Foo Inc. All rights reserved.
另例:<tr jwcid="$remove$"><td>2</td><td>Elton</td><td>John</td><td>285984</td></tr>表示为空的html代码;
在自定义组件的时候如果要用到 informal 参数,则要在调用时在.jwc中设置inherit-informal-parameters="yes" 属性.
其他:如果组件使用<reserved-parameter>元素来声明它的保留名称,这些保留名称不允许使用非正式参数,因为组件不想让非正式参数去覆盖它的值,并会自己产生这些命名属性.
十三. Contrib组件应用
<page-specification ...>
<component id="table" type="Contrib:Table">
<binding name="source" value="entries"/>
<binding name="columns"
value="literal:id, firstName:name.firstName, lastName:name.lastName, telNo"/>
</component>
</page-specification>
注释:其中的<binding name="columns" value="literal:id, firstName:name.firstName, lastName:name.lastName, telNo"/> 中的firstName:name.firstName表示通过OGNL的方式解析id为firstName的组件,该组件没有指定标题,表示调用getName()方法,获得Name对象,然后调用其getFirstName()方法,获得name的first属性.
如果改为<binding name="columns" value="literal:id, firstName:First Name:name.firstName, lastName:name.lastName, telNo"/>具有上面的特色外,另外在表头的标题为First Name;
十四. 如果程序中用注入元数据的方式给元素属性赋值时, 可以利用 @InjectMeta 的注入方式;
例如:
@InjectMeta("com.ttdev.album.image-folder")
public abstract String getImageFolder();
表示通过注入的方式给属性赋值,其中的 "com.ttdev.album.image-folder" 属性可以按下列方法找:
1. 在.page 文件中找<meta key="???" value="???"/>,如果找不到则
2. 在.application 文件中找
<application ...>
<meta key="???" value="???"/>
</application>
3. 在context部署描述中找:
<Context ...>
<Parameter name="???" value="???"/>
</Context>
4.在web.xml文件中找:
<web-app ...>
<context-param>
<param-name>???</param-name>
<param-value>???</param-value>
</context-param>
</web-app>
十五. 在页面中嵌入 .script脚本,可以利用Script组件
A. 例如有脚本文件:Confirm.script放在web-inf下
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE script PUBLIC
"-//Apache Software Foundation//Tapestry Script Specification 3.0//EN"
"http://jakarta.apache.org/tapestry/dtd/Script_3_0.dtd">
<script>
<input-symbol key="msg" required="yes"/>
<body>
function getConfirmation() {
return confirm("${msg}");
}
</body>
</script>
其中的<input-symbol key="msg" required="yes"/>中的msg表示是要求调用者输入的参数
B. 如果要在home.html中调用刚才的script,则要声明如下:
.page文件中:
<page-specification class="com.ttdev.confirmdelete.Home">
<component id="insertConfirmScript" type="Script">
<binding name="script" value="literal:Confirm.script"/>
<binding name="symbols" value="ognl:#{'msg': 'Are you sure?'}"/>
</component>
</page-specification>
其中<binding name="symbols" value="ognl:#{'msg': 'Are you sure?'}"/> 表示给msg赋值为"Are you sure?" ,在此也可以在.java中动态赋值;
.html文件中
<body jwcid="@Body">
<span jwcid="confirmDeleteScript"/>
<form action="http://www.foo.com">
<input type="Submit" value="Delete" onclick="return getConfirmation()"/>
</form>
</body>
十六. HtmlUnit用于页面单元测试。
配置:从http://htmlunit.sourceforge.net下载htmlunit-1.6.zip 或之后版本,将其解压,将解压后的文件夹打开,将htmlunit\lib下的所有.jar文件加入到Eclipse 的buildPath中;另外还要将eclipse\org.junit_3.8.8\junit.jar也加入。
步骤及方法:
1.新建一个test class继承TestCase类。
2.该该类中定义测试方法,测试方法只有以test开头才能被junit测试到,否则不被处理;
3.如果该类中有setUp()方法存在,则先执行该方法,该方法中可以放许多初试化的信息。
4.如果工程中有许多的测试类,我想一次测试所有的测试类中的方法,则可以考虑用suite()方法,例如:
static public TestSuite suite() {
TestSuite suite = new TestSuite();
suite.addTestSuite(TestsForCalculation.class); //将要执行的测试类加入到该对象中
suite.addTestSuite(TestsForHistory.class); //将要执行的测试类加入到该对象中
return suite;
}
说明:
HtmlUnit can help you create automated tests for your web application. You can use it to simulate user actions through a simulated browser.
After getting a response page for a URL, you can check it by getting various elements such as <span>, <input>, <select>, <table> using their id's or names and then check their contents.
To check a Javascript alert dialog, use an alert handler to collect the alert message.
To check the contents of a popup window, use a web window listener.
To open a link in a popup window, use a PopupLinkRenderer with the link component.
十七. 开发tapetsry时,注意的事项:
关闭Tapestry缓存池,提高开发效率
Tapestry对页面有自己的缓存策略。一旦页面被第一次访问,页面对象就会被加载到缓存中。因此,每次对HTML、page或java的修改,并不会马上生效,必须重新启动服务器。在我们开发程序的时候,这样相当不方便。因此我们可以关闭Tapestry的缓存策略,等到项目发布的时候,再开启。
在MyTapestry.application中添加:
<meta key="org.apache.tapestry.disable-caching" value="true"/>
<meta key="org.apache.tapestry.enable-reset-service" value="true"/>
并在JVM中添加:
-Dorg.apache.tapestry.disable-caching=true
-Dorg.apache.tapestry.enable-reset-service=true
十八。对session和application对象的管理
a.对session对象的管理:
tapestry中我们将session的管理交给了visit对象,在MyTapestry.application中声明visit对象:
1。 <meta key="org.apache.tapestry.visit-class" value="com.tapestry4.MyVisit"/>
然后我们在页面中,可以这样调用visit对象:
MyVisit visit = (MyVisit)this.getVisit();
2。 我们可以通过annotation来声明对visit对象的调用:
@InjectState("visit")
public abstract MyVisit getMyVisit();
3。如果不使用annotation,可以在page中声明:
<inject property="myVisit" type="state" object="visit"/>
然后在页面中仍然以抽象方法获取visit对象。
b.对application对象的管理:
对于session对象的管理,Tapestry是放到一个独立的visit对象中的,@InjectState有两个默认参数,一个是visit,另外一个是global,用于获取visit对象和global对象。
对于application对象的管理,Tapestry是放到一个独立的global对象中的,该对象的用法与visit一摸一样,不同的仅仅是对象的生命周期。同样,我们可以定义一个自己的global对象,在MyTapestry.application文件中声明:
<meta key="org.apache.tapestry.global-class" value="com.tapestry4.MyGlobal"/>
十九. DirectLink组件
作用:当用户点击时,触发页面java中一个特定的监听方法。
例如:
html中: <a href="#" jwcid="buyFruitLink"> XXX</a>
page中:
<component id="buyFruitLink" type="DirectLink">
<binding name="listener" value="listener:buyFruit"/>
<binding name="parameters" value="fruit.id"/>
</component>
java中: 直接将DirectLink中传递过来的参数作为监听方法的参数.(但在T3中不支持)
public IPage buyFruit(Integer ig) {
BuyFruit page = this.getBuyFruitPage();
page.setFruitId(ig);
return page;
}
在这个监听方法中,我们获取到了DirectLink传递的参数,并且我们向下一个页面传递水果的ID值,在下一个页面,我们就可以根据这个ID值,查找到对应的水果详细信息。
区别T3: T4中监听方法的用法有很大区别,现在我们看到的是监听方法的另外一种用法。直接将DirectLink传递的输入参数作为其监听方法的参数。一旦DirectLink触发监听方法,我们直接就可以从监听方法的输入参数中获取到被传递过来的fruit.id。当然,监听方法的输入参数是与fruit.id类型相对应的。
二十. 数据类型自动转换机制(translator)
translator目前支持的类型有三种:date,number,String。
例如:
<component id="age" type="TextField">
<binding name="value" value="age"/>
<binding name="translator" value="translator:number"/>
<binding name="displayName" value="literal:Age"/>
</component>
此处translator的作用是:如果用户输入的值不是数值类型,则脚本提示输入有误.
二十一. @Persist("client") 和 Hidden
使用@Persist("client")的效果与Hidden一样。实际上,@Persist("client")的作用远比Hidden强大。细心的朋友在页面运行之后,查看BuyFruit页面在浏览器中的源代码会发现,Tapestry4向页面中添加了下面这样的内容:
<input type="hidden" name="state:BuyFruit" value="BrO0ABXcOAAAAAQAAB2ZydWl0S
WRzcgARamF2YS5sYW5nLkludGVnZXIS4qCk94GHOAIAAUkABXZhbHVleHIAEGphdmE
ubGFuZy5OdW1iZXKGrJUdC5TgiwIAAHhwAAAAAQ=="/>
<input type="hidden" name="reservedids" value="state:BuyFruit"/>
Hidden组件只能在Form表单中使用,并且只能够被Form表单获取。而@Persist("client")保存的数据却可以被页面上的任意监听方法获取。比如DirectLink,ActionLink等。呵呵,很方便。
二十一. @Persist("client") 和 @Persist("session")
@Persist("client"):每个页面有不同的属性值,则用该持久属性;
注意:在tapestry的page pool中可能有一个页面的不同示例; 例如:一个productDetailPage页面,可能有productId=1的productDetailPage页面实例和可能有productId=2 的productDetailPage页面实例存在; 当用户想从 page pool 取页面事例的时候,会根据productID来取得已经存在的页面.
@Persist("session") :每个用户有不同的属性,则用该属性;
注意: 当使用 持久化到session的时候,可能出现的问题:
例如:
如果将客户产品明细页面中用到的productId放在session中, 当一个客户在网上浏览产品,该产品有 id=01, id=02 两件, 可能出现的错误:
首先,客户从list页面查看 id=01产品的详细信息,那么session中保存了的id=01,
然后客户回到list页面,查看id=02的产品信息,那么session中就会保存id=02.
现在,客户按 浏览器的"后退"按钮,返回到id=01的产品明细页面. 直接按"Add to cart" 按钮, 此时,
客户以为将id=01的产品放入了购物车, 但实际上在session中保存的id=02, 该页面提交时,会从session中取的id,所以放到购物车的id=02,而不是01;
二十二. Tatestry内部js.
当我们用tapestry开发页面的时候,tapestry会自动将对应的js引入进来,开发人员只需要直接调用即可:
例如:
function checkBlankSelect(form,field,msg,event){
Tapestry.onsubmit(form,
function(event) {
var fieldObj = document.getElementById(field);
if(fieldObj.value == 0){
event.invalid_field(fieldObj , msg);
}
}
);
当页面在运行生成的html中会产生如下的代码:<script type="text/javascript" src="/tapestry4test/assets/1f7008d3e65882519740d925d6c5a813/org/apache/tapestry/form/Form.js"></script>
也就是tapestry帮我们做了一些工作,具体实现可以查找 org/apache/tapestry/form/目录下的具体.js文件;
分享到:
相关推荐
本书《Enjoy Web Dev With Tapestry》不仅是一本入门指南,更是一部深入浅出的实战教程,旨在让读者在学习过程中体验到开发的乐趣。以下为本书的主要特点: 1. **易于上手**:即使是没有Servlet或JSP背景的读者也能...
基于openocd开源工具实现的C#桌面应用工具
精品-2025人工智能神经网络基本原理解析.pdf
施耐德ATV312变频器通过MCGS RTU通讯实现双机监控与控制的触摸屏集成解决方案,无PLC的施耐德ATV312变频器通讯示例:触摸屏控制监控两台变频器,功能多且省成本,改进型可调整步长 P&O MPPT(二区MPPT复现),光储系统MPPT 直流负载供电的单级离网光伏系统中,降压转器将太阳能光伏阵列和直流负载连接起来,同时确保最大功率点跟踪(MPPT) 和电池充电控制的良好运行。 在MPPT方面,提出了一种改进的自适应步长扰动观测(P&O)方法,以达到不同天气条件下太阳能光伏阵列的实际最大功率点(MPP),同时减少稳态振荡和功率损耗。 此外,电池充电控制侧使用三级充电控制器 (TSCC) 为铅酸电池站充电。 ,改进型P&O; 复现二区MPPT; 光储系统MPPT; 最大功率点跟踪(MPPT); 步长扰动观测; 降压转换器; 太阳能光伏阵列; 电池充电控制; 三级充电控制器(TSCC); 铅酸电池站。,改进型P&O MPPT技术,光储系统高效能量管理
redis学习脑图笔记
大学生创业项目源码
Spring Boot企业员工管理系统(包含万字论文+MYSQL)
对应博客地址:https://blog.csdn.net/u011561335/article/details/146312389
相关文章:https://blog.csdn.net/liu_23yanfeng/article/details/146319189
从春晚看科技技术-陈雄 - 公开版本.pptx
在计算机上安装制造装备物联及生产管理ERP系统软件来发挥其高效地信息处理的作用,可以规范信息管理流程,让管理工作可以系统化和程序化,同时,制造装备物联及生产管理ERP系统的有效运用可以帮助管理人员准确快速地处理信息。 制造装备物联及生产管理ERP系统在对开发工具的选择上也很慎重,为了便于开发实现,选择的开发工具为Eclipse,选择的数据库工具为Mysql。以此搭建开发环境实现制造装备物联及生产管理ERP系统的功能。其中管理员管理用户,新闻公告。 制造装备物联及生产管理ERP系统是一款运用软件开发技术设计实现的应用系统,在信息处理上可以达到快速的目的,不管是针对数据添加,数据维护和统计,以及数据查询等处理要求,制造装备物联及生产管理ERP系统都可以轻松应对。 关键词:制造装备物联及生产管理ERP系统;SpringBoot框架,系统分析,数据库设计
传统信息的管理大部分依赖于管理人员的手工登记与管理,然而,随着近些年信息技术的迅猛发展,让许多比较老套的信息管理模式进行了更新迭代,问卷信息因为其管理内容繁杂,管理数量繁多导致手工进行处理不能满足广大用户的需求,因此就应运而生出相应的问卷调查系统。 本问卷调查系统分为管理员还有用户两个权限,管理员可以管理用户的基本信息内容,可以管理新闻资讯信息以及新闻资讯的租赁信息,能够与用户进行相互交流等操作,用户可以查看问卷信息,可以查看新闻资讯以及查看管理员回复信息等操作。 该问卷调查系统采用的是WEB应用程序开发中最受欢迎的B/S三层结构模式,使用占用空间小但功能齐全的MySQL数据库进行数据的存储操作,系统开发技术使用到了JSP技术。该问卷调查系统能够解决许多传统手工操作的难题,比如数据查询耽误时间长,数据管理步骤繁琐等问题。总的来说,问卷调查系统性能稳定,功能较全,投入运行使用性价比很高。 关键词:问卷调查系统;MySQL数据库;SSM技术
VID20250317191237.mp4
西门子S7-1511 PLC PID控制阀门开度与模拟量转换——博途WinCC监控画面程序实践,西门子S7-1511 PLC PID控制阀门开度与模拟量转换——博途WinCC监控画面程序实践,matlab验证码识别系统,基于数字图像处理实现。 经过对图像的预处理、二值化、区域剪裁、数字定位、模板匹配法识别数字。 有gui界面和测试图像数据集。 ,核心关键词:Matlab验证码识别系统; 数字图像处理; 图像预处理; 二值化; 区域剪裁; 数字定位; 模板匹配法识别; GUI界面; 测试图像数据集。,基于Matlab的数字图像处理验证码识别系统
内容概要:本文提供了详细的 VMware 虚拟机安装指南,涵盖软件选择(Pro 和 Player 版区别)、安装步骤(适用于 Windows 和 Linux 主机系统)、虚拟机创建以及操作系统安装指导。详细介绍了配置虚拟机的各项关键设置,如资源分配、硬件参数定制、安装 VMware Tools 提升虚拟机性能和稳定性。并且列出了快照、克隆等高级功能的具体应用,还包括共享文件夹配置和几种常见错误的排除解决方案。 适合人群:初次接触虚拟化的用户和对虚拟环境搭建有一定兴趣的技术爱好者。 使用场景及目标:帮助用户快速部署自己的虚拟机,并掌握虚拟环境中常见的配置技巧,能够针对具体应用场景灵活地调整虚拟机的相关参数,提高工作效率,满足测试、学习、开发的需求。 其他说明:提供了一些安装过程可能遇到的问题及对应解决方案,在创建和维护过程中给予指导性的意见来确保用户的使用体验尽可能顺畅无阻,并给出了部分性能优化建议。
Matlab开发初学者视频教程,零基础入门,非常适合初学者。
质子交换膜燃料电池(PEMFC)Simulink模型:静态与动态模型分析及参数计算,基于Simulink的质子交换膜燃料电池模型:静态和动态模拟,计算输出和效率,cst仿真超表面 极化复用 ,核心关键词: 1. CST仿真 2. 超表面 3. 极化复用 以上信息以分号隔开,即为“CST仿真;超表面;极化复用”。,CST仿真超表面极化复用技术
PEMFC的Simulink静态与动态模型:输出电压、功率、效率等多维度性能计算指南,质子交换膜燃料电池Simulink模型:涵盖静态与动态特性,全面计算输出性能与效率,附参考公式与文献指南,C#运动控制系统源码。 雷赛运动控制卡控制系统。 像高川控制卡、高川控制器、或者固高运动控制卡以及正运动控制器、正运动控制卡可以用这个框架,自己替一下库文件等代码就可以。 功能丰富,注释多,非常适合新手学习,也可以做框架。 ,核心关键词:C#运动控制系统源码; 雷赛运动控制卡控制系统; 高川控制卡/高川控制器/固高运动控制卡; 正运动控制器/正运动控制卡; 功能丰富; 注释多; 新手学习; 框架。,C#雷赛运动控制系统源码框架:通用控制卡编程指南