In today's web development, there are more and more Java-based applications. Among them, Servlet plays a very important role. This series of articles will introduce some tools to assist in servlet development, so that you can choose from a variety of technologies during development. Servlet technology is undoubtedly an excellent technology. Most Java server technologies are based on Servlet technology. However, this technology also has its own shortcomings. For example, the presentation layer (HTML code) is mixed with the code, and the reusability is not high. Sun proposed JSP technology, which is also a servlet-based technology. You can use it to embed Java code in HTML. JSP has taken a big step on the basis of servlet, but the pure JSP also has the shortcomings of servlet mentioned above. However, JSP + JavaBean + taglib can be used to solve the shortcomings mentioned above. However, JSP itself has other shortcomings. For details, refer to the article "the problems with JSP. So people developed other servlet-based technologies. Let's first introduce tapestry.
Introduction
Tapestry is an open-source servlet-based application framework that uses component object models to create dynamic and interactive web applications. A component is any HTML tag with the CID attribute. JWC indicates Java Web component. Tapestry completely isolates Java code from HTML, making it easy to use this framework to develop large-scale applications. In addition, the developed applications are easy to maintain and upgrade. Tapestry supports localization and detailed error reports. Tapestry is mainly developed using JavaBean and XML technologies.
First Application
Before introducing the first application, we will first introduce the installation of tapestry. Download the latest version from SourceForge. decompress the package and put the JAR file in the lib directory to classpath. Then, place the war file in the webapp directory of Tomcat. Then, you can access its tutorial application through http: // localhost: 8080/tutorial. An application in tapestry consists of the following parts. We will introduce it with its own helloworld program as an example:
Servlet:
This is the main part of an application: servlet class, which must be a subclass of applicationservlet and must implement the getapplicationspecificationpath () method. Example:
Import com. primix. tapestry .*;
Public class helloworldservlet extends applicationservlet
{
Protected string getapplicationspecificationpath ()
{
Return "/tutorial/Hello/helloworld. Application ";
}
}
/Tutorial/Hello/helloworld. application is an application description file.
Application specification:
In fact, it is an XML file describing this application. There are many parameters to be set in this application. Engine-class will be described below. The name attribute in page specifies the HTML file name, specification-path specifies the description file for this page. There can be many pages in an application, but the name of a page must be "home", because this page is first displayed when you access your application.
<? XML version = "1.0" encoding = "UTF-8"?>
<! Doctype application public "-// Howard ship // tapestry specification 1.1 //" 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:
When a customer connects to a tapestry application, tapestry creates an engine object (similar to session ). Generally, the application engine in our program is an instance of the simpleengine class. Of course, this class can also be a subclass.
Page specification:
Similar to the application description, the page description is also an XML description file:
<? XML version = "1.0" encoding = "UTF-8"?>
<! Doctype specification public "-// Howard ship // tapestry specification 1.1 //" http://tapestry.sf.net/dtd/Tapestry_1_1.dtd ">
<Specification class = "com. primix. tapestry. basepage"/>
Because this application is static, Com. primix. tapestry. basepage. If it is a dynamic application, you need to define some component in this file. Of course, you can use basepage as the base class's derived class.
HTML page:
The HTML page of this application is very simple:
<HTML>
<Head>
<Title> Hello World </title>
</Head>
<Body>
<B> helloworld </B>
</Body>
</Html>
Note: All the files mentioned above should be placed under the war's WEB-INF/classes directory.
A complex application
In this application, we will take a simple student management system as an example to introduce the common functions of tapestry. To add and display students, we need two HTML pages. We will not describe the studentservlet class and student. application. Two pages: Home and editstudent are defined in student. application. For details, refer to the attachment. Student data is stored in the database. Student Class is used to represent a record in the data and studentfactory class is used to retrieve student data. These two classes use a JDBC package, for more information about this JDBC package, see <extensions and Applications of a simple JDBC package>.
Download home.html
<HTML>
<Head>
<Title> Student Management </title>
<Meta http-equiv = "Content-Type" content = "text/html; charset = gb2312">
</Head>
<Body bgcolor = "# ffffff">
<P align = "center"> student list </P>
<Table width = "100%" border = "1">
<Tr>
<TD> Student ID </TD>
<TD> name </TD>
<TD> gender </TD>
<TD> class </TD>
</Tr>
<Span upload cid = "liststudent">
<Tr>
<TD> <span cid = "ID"> 20012400 </span> </TD>
<TD> <span cid = "sname"> Zong Feng </span> </TD>
<TD> <span cid = "gender"> male </span> </TD>
<TD> <span cid = "department"> Computer research 1 </span> </TD>
</Tr>
</Span>
<Tr sequence cid = "$ remove $">
<TD> 20011389 </TD>
<TD> sang Yishan </TD>
<TD> male </TD>
<TD> Computer 1 </TD>
</Tr>
</Table>
<A senior cid = "add"> Add student </a>
</Body>
</Html>
Different from the previous simple application, we have defined seven components on this page. Next, let's take a look at some home. JWC files. We will detail how to describe these components.
<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>
Here, the class attribute value of specification is no longer basepage, but its derived class liststudent. For each component, the ID attribute specifies a unique identifier. This value corresponds to the CID value in the HTML file. The type parameter specifies the component name and the binding parameter specifies how the component obtains data, property-path is a set of attributes. These attributes are generally defined in JavaBean. For example, the property-Path = "student ", then there should be a function getstudent in the corresponding listan class liststudent. Liststudent is a foreach component, which is actually a for loop. It reads an array from the source and assigns values one by one to the attribute specified by the value parameter. ID, name, gender, and Department are the insert components used to insert text data. The parameter value specifies the value to be inserted, and the property-path specifies how to obtain these values, eachstudent. the ID is equivalent to geteachstudent () that calls JavaBean (). GETID (). Add is a page component. The page attribute specifies the Page name (defined in the application file). Static-binding indicates that the data to be bound cannot be modified. $ Remove $ the component is not described in this file, because it is automatically deleted when the tapestry is running.
Let's take a look at the liststudent class:
Package test;
Import com. primix. tapestry .*;
Import sun. JDBC. ODBC. jdbcodbcdriver;
/**
* Returns the data of each student.
*
*/
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;
}
}
This class has four functions. The detach function is the operation performed when the page is put into the buffer pool. The getstudent function returns all student records, which is to assign values to the Source Parameter of the liststudent component in the JWC file, geteachstudent assigns a value to the value parameter of this component. Because source is an array, each loop needs to retrieve a record from it and assign it to eachstudent. So there is another function seteachstudent, and you will notice that this function is very simple, in fact, tapestry helped you do most of the work.
In this case, the student's website is completed, and the following figure shows editstudent.html
<HTML>
<Head>
<Title> Add students </title>
<Meta http-equiv = "Content-Type" content = "text/html; charset = gb2312">
</Head>
<Body>
<P> Student Management System </P>
<Form into cid = "form">
<Span upload cid = "iferror">
<Font size = + 2 color = Red> <span serving cid = "inserterror"/> </font>
</Span>
<P> Student ID:
<Input partition cid = "ID"/>
</P>
<P> Name:
<Input partition cid = "name"/>
</P>
<Span cid = "gender">
<P> gender:
<Input partition cid = "male"/>
Male
<Input partition cid = "female"/>
Female
</P>
</Span>
<P> class:
<Input partition cid = "department"/>
</P>
<P>
<Input type = "Submit" value = "OK">
</P>
</Form>
</Body>
</Html>
Some other commonly used components are used in this file. Let's take a look at the descriptions of these components in 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 is a form component. Its Parameter listener specifies the function to process when the form is submit. Iferror is a conditional component, which specifies that the component is displayed only when the condition is met. In this example, if the error is not empty, the condition is met. An Insert component is nested in this component to display errors. This is a common method to handle errors in tapestry. Gender is a radiogroup component bound to the Gender attribute in JavaBean. The selected parameter specifies the radio to be selected. In this component, two radio components are nested to indicate male, respectively, female. The value parameter of Radio specifies that when you select this radio, the property value bound to the radiogroup will be equal to the value specified in field-Name (This value must be static). In this example, gender = test. editstudent. male. ID is a textfield component. Its parameter value is bound to the ID attribute of JavaBean.
The corresponding editstudent class is shown below:
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)
{
// Determine whether the user has added all the data
If (Gender = 0 | id = NULL | ID. Equals ("") | sname = NULL | sname. Equals ("") |
Department = NULL | department. Equals (""))
{
Error = "fill in all options ";
Return;
}
// Save the student
Try {
Student = new student ();
Student. setid (ID );
Student. setname (sname );
If (Gender = 1)
Student. setgender ("male ");
Else
Student. setgender ("female ");
Student. setdepartment (Department );
Student. Save (null );
} Catch (exception e ){
E. printstacktrace ();
}
// Clear the current attributes to avoid retaining the original values when you enter this page again.
Setsname (null );
Setdepartment (null );
Setid (null );
Setgender (0 );
// Redirect to the Home Page
Cycle. setpage ("home ");
}
}
The fireobservedchange function is used in some attribute setting functions of this class. This function triggers a change event and notifies the current attribute that the value has changed.
Other applications
The localization example in workbench in the example of self-contained in tapestry demonstrates how to use localization. You only need to create HTML templates of different languages, as well as other resources used in HTML such as graphics. For example, if you create editstudent.html for a syntax, the corresponding HTML file name is editstudent_fr.html. The component description defined in JWC does not have to have multiple versions. Here we will introduce a concept commonly used in tapestry Localization: assets. Assets are resources used in some Web applications, such as videos. There are three assets: external, internal, and private. External assets come from any URL. The internal assets come from URLs on the same server as the tapestry application. Private assets allow deployment in the war's WEB-INF/classes directory (same as the preceding HTML template, JWC file), which is invisible to Web servers.
Take a look at the segment of the localization. JWC file in the localization example in workbench:
<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"/>
Private assets are used in the changebutton component, and these image files are placed under the war's WEB-INF/classes. Note that images have versions in multiple languages like HTML.
Note: The inputlocale component in the JWC file is actually used by the Localization Application to implement localization. For details about the parameters, see the developer guide.
<Component id = "inputlocale" type = "propertyselection">
<Binding name = "value" property-Path = "Page. Engine. locale"/>
<Binding name = "model" property-Path = "localemodel"/>
</Component>
Tapestry also supports the creation of its own reusable components, with its own example: border. It also provides other examples: Inspector shows how to monitor your application. Vlib is a J2EE application using Tapestry as the presentation layer (using JBoss as the application server ).
The functions of tapestry are very powerful. This article only introduces a small part of it, and there are still many aspects not involved, such as the application of Javascript in tapestry. For details, refer to the document. I believe that if you use this framework, you will be deeply attracted to it. The document of tapestry is not complete, but after constant exploration, I believe you will soon master it.