欢迎光临
我们一直在努力

取代JSP的新技术-tapestry-JSP教程,Jsp/Servlet

建站超值云服务器,限时71元/月

在如今的web开发中,基于java的应用越来越多。在这其中,servlet又扮演着十分重要的角色。本系列文章就是要介绍一些辅助进行servlet开发的工具,让大家进行开发时,有多种技术可供选择。

servlet技术无疑是一种优秀的技术,java服务器端技术大都基于servlet技术。但这种技术也有其自身的不足,例如:表示层(html代码)与代码混在一起,可重用性不高。sun于是提出了jsp技术,jsp也是基于servlet的一种技术,使用它你可以在html中嵌入java代码。jsp在servlet的基础上迈进了一大步,但单纯的jsp也有上面提到的servlet的缺点。不过利用jsp+javabean+taglib这种开发模式可以解决上面提到的缺点。但jsp本身还有其它一些不足,具体参看the problems with jsp这篇文章。于是人们便开发了其它一些基于servlet的技术。我们首先介绍一下tapestry。

简介

tapestry是一个开源的基于servlet的应用程序框架,它使用组件对象模型来创建动态的,交互的web应用。一个组件就是任意一个带有jwcid属性的html标记。其中jwc的意思是java web component。tapestry使得java代码与html完全分离,利用这个框架开发大型应用变得轻而易举。并且开发的应用很容易维护和升级。tapestry支持本地化,其错误报告也很详细。tapestry主要利用javabean和xml技术进行开发。

第一个应用程序

在介绍第一个应用之前,先介绍一下tapestry的安装。从sourceforge下载其最新版,解压后,将lib目录下的jar文件放到classpath中,将其中的war文件放到tomcat的webapp目录下。然后就可以通过http://localhost:8080/tutorial访问其tutorial应用。

在tapestry中一个应用程序有以下几部分组成,我们以其自身带的helloworld程序为例介绍:

servlet:

这是一个应用的主体部分:servlet类,这个类必须是applicationservlet的子类,并且必须实现getapplicationspecificationpath()方法。示例如下:

import com.primix.tapestry.*;

public class helloworldservlet extends applicationservlet

{

protected string getapplicationspecificationpath()

{

return "/tutorial/hello/helloworld.application";

}

}

/tutorial/hello/helloworld.application是一个应用的说明文件。

application specification:

其实就是描述这个应用的一个xml文件,在这个应用中有许多参数需要设置,engine-class将在下面介绍,page中的name属性指定html文件名,specification-path指定对这个页面的说明文件。在一个应用中可以有很多个page,但必须有一个page的name为"home",因为当访问你的应用时,首先显示的就是这个page。

<?xml version="1.0" encoding="utf-8"?>

<!doctype application public "-//howard ship//tapestry specification 1.1//en" "http://tapestry.sf.net/dtd/tapestry_1_1.dtd">

<application name="hello world tutorial" engine-class="com.primix.tapestry.engine.simpleengine">

<page name="home" specification-path="/tutorial/hello/home.jwc"/>

</application>

application engine:

当客户连接到tapestry应用时,tapestry将会创建一个engine对象(类似于session)。通常我们程序中的application engine 一般是simpleengine类的一个实例,当然这个类的子类也可以。

page specification:

跟应用说明相似,页说明也是一个xml描述文件:

<?xml version="1.0" encoding="utf-8"?>

<!doctype specification public "-//howard ship//tapestry specification 1.1//en" "http://tapestry.sf.net/dtd/tapestry_1_1.dtd">

<specification class="com.primix.tapestry.basepage"/>

因为这个应用是静态的,所以使用com.primix.tapestry.basepage即可,如果是动态的应用,则需在这个文件中定义一些component,当然使用basepage为基类的派生类也可以。

html页面:

这个应用的html页面非常简单:

<html>

<head>

<title>hello world</title>

</head>

<body>

<b>helloworld</b>

</body>

</html>

注意上面所讲到的各种文件都要放到放在war的web-inf/classes目录下。

一个复杂的应用

在这个应用中我们以一个简单的学生管理系统为例介绍一下tapestry的常用功能。我们要实现学生的增加和显示,因此我们需要两个html页面。至于studentservlet类和student.application我们就不描述了,在student.application中定义了两个page:home和editstudent,具体看附件。学生数据存放在数据库中,我们用student类表示数据中的一条记录,用studentfactory类检索学生数据,这两个类用到了一个jdbc包装器,关于这个jdbc包装器可以见我的另外一篇文章<<对一个简单的 jdbc 包装器的扩展及应用>>。

首先看一下home.html

<html>

<head>

<title>学生管理</title>

<meta http-equiv="content-type" content="text/html; charset=gb2312">

</head>

<body bgcolor="#ffffff">

<p align="center">学生列表</p>

<table width="100%" border="1">

<tr>

<td >学号</td>

<td >姓名</td>

<td >性别</td>

<td >班级</td>

</tr>

<span jwcid="liststudent">

<tr>

<td><span jwcid="id">20012400</span></td>

<td><span jwcid="sname">宗锋</span></td>

<td><span jwcid="gender">男</span></td>

<td><span jwcid="department">计算机研一</span></td>

</tr>

</span>

<tr jwcid="$remove$">

<td>20011389</td>

<td>桑一珊</td>

<td>男</td>

<td>计算机研一</td>

</tr>

</table>

<a jwcid="add">添加学生</a>

</body>

</html>

与前面的简单应用不同,我们在这个页面中定义了七个组件,下面看一下部分home.jwc文件,我们将详细讲述一下怎样描述这些组件。

<specification class="test.liststudent">

<component id="liststudent" type="foreach">

<binding name="source" property-path="student"/>

<binding name="value" property-path="eachstudent"/>

</component>

<component id="id" type="insert">

<binding name="value" property-path="eachstudent.id"/>

</component>

<component id="add" type="page">

<static-binding name="page">editstudent</static-binding>

</component>

</specification>

在这里,我们的specification的class属性值不再是basepage,而是其派生类liststudent。对于每一个组件,id属性指定唯一的标识符,这个值与html文件中的jwcid值相对应,type 指定组件名,binding指定组件怎得到数据,property-path是一系列属性的集合,这些属性一般定义在javabean中,例如上面的property-path="student",则在相应的javabean类liststudent中应该有个函数getstudent。liststudent是一个foreach组件,这个组件其实是一个for循环,它从source中读入一个数组,将其一个一个的赋值给value参数指定的属性。id,name,gender,department四个是insert组件,这个组件用来插入文本数据,参数value指定要插入的值,property-path指定怎样获取这些值,eachstudent.id相当于调用javabean的geteachstudent().getid()。add是一个page组件,page属性指定页面名(定义在application文件中),static-binding表明要绑定的数据是不可修改的。$remove$组件没有在这个文件中描述,因为tapestry运行时会自动删除这种组件。

下面看一下liststudent类:

package test;

import com.primix.tapestry.*;

import sun.jdbc.odbc.jdbcodbcdriver ;

/**

* 返回每个学生的数据

*

*/

public class liststudent extends basepage

{

private student eachstudent;

private student[] student;

public void detach()

{

eachstudent=null;

student=null;

super.detach();

}

public student geteachstudent()

{

return eachstudent;

}

public void seteachstudent(student value)

{

eachstudent = value;

}

public student[] getstudent()

{

try{

class.forname("sun.jdbc.odbc.jdbcodbcdriver");

student=studentfactory.findallstudents();

}catch(exception e){

e.printstacktrace();

}

return student;

}

}

这个类有四个函数,其中detach函数是将页面放入缓冲池时执行的操作,getstudent函数返回所有的学生记录,这是给jwc文件中liststudent组件的source参数赋值,geteachstudent给这个组件的value参数赋值,因为source是一个数组,每次循环需要从中取出一条记录赋值给eachstudent,所以还有一个函数为seteachstudent,你会注意到这个函数很简单,其实是tapestry帮你做了大部分工作。

至此,显示学生的部分已经完成,下面看一下editstudent.html

<html>

<head>

<title>增加学生</title>

<meta http-equiv="content-type" content="text/html; charset=gb2312">

</head>

<body>

<p><img src="student.gif" width="32" height="32"/> 学生管理系统</p>

<form jwcid="form">

<span jwcid="iferror">

<font size=+2 color=red><span jwcid="inserterror"/></font>

</span>

<p>学号:

<input jwcid="id"/>

</p>

<p>姓名:

<input jwcid="name"/>

</p>

<span jwcid="gender">

<p>性别:

<input jwcid="male"/>



<input jwcid="female"/>



</p>

</span>

<p>班级:

<input jwcid="department"/>

</p>

<p>

<input type="submit" value="确定">

</p>

</form>

</body>

</html>

在这个文件中,用到了另外一些常用的组件,先看一下editstudent.jwc中的这些组件的描述:

<specification class="test.editstudent">

<component id="form" type="form">

<binding name="listener" property-path="listeners.formsubmit"/>

</component>

<component id="gender" type="radiogroup">

<binding name="selected" property-path="gender"/>

</component>

<component id="iferror" type="conditional">

<binding name="condition" property-path="error"/>

</component>

<component id="inserterror" type="insert">

<binding name="value" property-path="error"/>

</component>

<component id="id" type="textfield">

<binding name="value" property-path="id"/>

</component>

<component id="male" type="radio">

<field-binding name="value" field-name="test.editstudent.male"/>

</component>

</specification>

form是一个form组件,它的参数listener指定submit这个form时有那个函数处理。iferror是一个conditional组件,这个组件指定当condition满足时才会显示,在本例中,如果error不为空,则condition满足。在这个组件中,有嵌套了一个insert类型的组件,用于将错误显示。这是tapestry中经常用到的处理错误的方式。gender是一个radiogroup组件,它绑定了javabean中的gender属性,selected参数指定那个radio被选中,在这个组件中,又嵌套了两个radio组件,分别用来表示男,女。radio的value参数指定当用户选定这个radio时,radiogroup绑定的属性值将会等于field-name中指定的值(这个值必须是static的),在本例中,gender=test.editstudent.male。id是一个textfield组件,其参数value绑定到javabean中的id属性。

下面是相应的editstudent类:

package test;

import com.primix.tapestry.*;

public class editstudent extends basepage

{

public static final int male = 1;

public static final int female = 2;

private int gender;

private string error;

private string id;

private string sname;

private string department;

public void detach()

{

error = null;

id=null;

sname=null;

gender=0;

department=null;

super.detach();

}

public int getgender()

{

return gender;

}

public string getid()

{

return id;

}

public string getsname()

{

return sname;

}

public string getdepartment()

{

return department;

}

public void setgender(int value)

{

gender = value;

fireobservedchange("gender", value);

}

public void setid(string value)

{

id = value;

fireobservedchange("id", value);

}

public string geterror()

{

return error;

}

public void setsname(string value)

{

sname = value;

fireobservedchange("sname", value);

}

public void setdepartment(string value)

{

department = value;

fireobservedchange("department", value);

}

public void formsubmit(irequestcycle cycle)

{

//判断用户是否添完了所有数据

if (gender== 0||id==null||id.equals("")||sname==null||sname.equals("")||

department==null||department.equals(""))

{

error = "请填充完所有选项";

return;

}

//将学生保存

try{

student student=new student();

student.setid(id);

student.setname(sname);

if(gender==1)

student.setgender("男");

else

student.setgender("女");

student.setdepartment(department);

student.save(null);

}catch(exception e){

e.printstacktrace();

}

//清空当前的各个属性,以免再次进入此页面时,各属性仍旧保留原来的值

setsname(null);

setdepartment(null);

setid(null);

setgender(0);

//重定向到home页面

cycle.setpage("home");

}

}

在本类的一些设置属性的函数中使用了fireobservedchange这个函数,这个函数激发一个改变事件,通知当前的属性的值已经改变。

其他应用

tapestry中自带的例子中的workbench中的localization例子演示了怎样使用本地化,你只需要创建不同语言的html模板,还有图形等其它一些html中用到的资源。例如创建一个法语版的editstudent.html,则相应的html文件名为editstudent_fr.html,而jwc中定义的组件的描述不用有多个版本。这里要介绍一下tapestry本地化中经常用到的一个概念:assets。assets是一些web应用中用到的资源,如图象,视频。assets有三种:external, internal 和private。external类型的assets来源于任意的url。internal类型的assets来源于和tapestry应用在同一个服务器上的url。private 类型的assets允许部署在war的web-inf/classes目录下(同上面的html模板,jwc文件一样),这个目录对于web服务器来说是不可见的。

看一下workbench中localization例子中的localization.jwc文件的片断:

<component id="changebutton" type="imagesubmit">

<binding name="image" property-path="assets.change-button"/>

</component>

<private-asset name="change-button" resource-path="/tutorial/workbench/localization/change.gif"/>

在changebutton组件中就使用了private assets,而这些图像文件就放在war的web-inf/classes下,注意图像跟html一样也有多个语言的版本。

注意jwc文件中的inputlocale这个组件,其实localization应用就是通过这个组件来实现本地化。具体参数请看其developer guide。

<component id="inputlocale" type="propertyselection">

<binding name="value" property-path="page.engine.locale"/>

<binding name="model" property-path="localemodel"/>

</component>

tapestry还支持创建自己的可重用组件,其自身带了一个这样的例子:border。同时它还有其它一些例子:inspector展示了怎样监视你的应用程序。vlib是一个用tapestry作表示层的j2ee应用程序(用jboss作为应用服务器)。

tapestry的功能非常强大,本文只是介绍了其一小部分,还有很多方面没有涉及到,例如javascript在tapestry中的应用。具体可以看其文档,相信如果你用一下这个框架,你就会被它深深吸引。tapestry的文档做的不是很全,不过经过不断的摸索,相信你会很快掌握它。 

赞(0)
版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com 特别注意:本站所有转载文章言论不代表本站观点! 本站所提供的图片等素材,版权归原作者所有,如需使用,请与原作者联系。未经允许不得转载:IDC资讯中心 » 取代JSP的新技术-tapestry-JSP教程,Jsp/Servlet
分享到: 更多 (0)