Replace JSP new technology - Tapestry

xiaoxiao2021-03-06  15

In today's Web development, Java-based applications are increasing. In this, servlet played a very important role. This series of articles is to introduce some of the tools for servlet development, and there are a variety of technologies to choose from when developing. Servlet technology is undoubtedly an excellent technology, and the Java server-side technology is mostly based on servlet technology. However, this technique also has its own insufficient, for example, indicating that the layer (HTML code) is mixed with the code, and the reusability is not high. SUN then proposed JSP technology, JSP is also a technology-based technology, using it you can embed Java code in HTML. JSP moves a big step on the basis of servlet, but simple JSP has the shortcomings of the servlet mentioned above. However, using JSP JavaBean Taglib This development mode can solve the shortcomings mentioned above. But JSP itself has some other shortcomings, and details will be referred to the article of Problems with JSP. So people have developed some other servlet-based technologies. Let's first introduce TapeStry.

Introduction Tapestry is an open source-based servlet-based application framework that uses component object models to create dynamic, interactive web applications. One component is any HTML tag with JWCID attribute. Where JWC means Java Web Component. Tapestry makes Java code to completely separated from HTML, using this framework to develop large applications becomes lighter. And the application developed is easy to maintain and upgrade. TapeStry supports localization, and its error report is also very detailed. Tapestry is mainly developed by JavaBean and XML technology. The first application introduces TapeStry installation before introducing the first application. After downloading its latest version from SourceForge, place the JAR file in the lib directory in the classpath, put the WAR file in the Tomcat's WebApp directory. The TUTORIAL application can then be accessed by http: // localhost: 8080 / tutorial. One of the following components in TapeStry, we use their own HelloWorld program as an example: servlet: This is the main part of an app: servlet class, this class must be the subclass of ApplicationServlet, and must implement GetApplicationSpecificationPath ()method. Examples are as follows: import com.primix.tapestry *; public class HelloWorldServlet extends ApplicationServlet {protected String getApplicationSpecificationPath () {return "/tutorial/hello/HelloWorld.application";}} /tutorial/hello/HelloWorld.application an application. description file. Application Specification: It is actually describing an XML file for this app. There are many parameters in this app to set, Engine-Class will introduce, the name attribute in the page specifies the HTML file name, specification-pats specifies the description of this page. file. There are many Page in an app, but you must have a page of Name as "HOME", because when you access your app, the first display is this Page.

Application Engine: When the customer is connected to the Tapestry app, TapeStry will create an Engine object (similar to session). Usually Application Engine in our program is generally an instance of the SimpleEngine class, of course, the subclass of this class can also be. Page Spectation: Similar to the application, the page will also be an XML description file: Because this application is static, use com.primix.tapestry .Basepage, if it is a dynamic application, you need to define some Component in this file, of course, using BasePage to be classified as the base class. HTML page: This application's HTML page is very simple: Hello World </ title> </ head> <body> <b> HelloWorld </ b> </ body> </ html> Note The various files mentioned above must be placed in the WAR-INF / CLASES directory.</p> <p>A complex application In this application, we introduce TapeStry common functions as an easy student management system. We have to achieve students' increase and display, so we need two HTML pages. As for the StudentServlet class and student.application, we will not describe, defined in Student.Application, two Page: Home and EditStudent, see attachments. Student Data is stored in the database, we use the Student class to indicate a record in the data, use the StudentFactory class to search for student data, these two classes use a JDBC wrapper, about this JDBC wrapper can see my other article < <Extension and application of a simple JDBC wrapper >>. First look at 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> study number </ td> <TD> Name </ TD> <TD> Gender </ TD> <TD> Class </ TD> <TD> <span jwcid = "liststudent> <Tr> <TD> <span jwcid =" id "> 20012400 </ Span> </ td> <td> <span jwcid = "sname"> Zongfeng </ span> </ td> <td> <span jwcid = "gender"> male </ span> </ td> <TD> <span jwcid = "department"> computer research one </ span> </ td> </ tr> <limited $ "> <td> 20011389 </ td> <td> Sang Yishan </ td> <TD> Male </ TD> <TD> Computer Research 1 </ TD> </ TR> </ Table> <a jwcid="add"> Add Student </a </ body> </ html > Different from the simple application of the previous, we define seven components in this page. Let's take a look at some home.jwc files, we will explain how to describe these components.</p> <p><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" protrudent.id "/> </ component> <component id =" Add "Type =" page "> <static-binding name =" page "> editstudent </ static-binding> </ component> </ specification> Here, our Specification's class attribute value is no longer BasePage, but it Derive class liststudent. For each component, the id attribute specifies a unique identifier, this value corresponds to the JWCID value in the HTML file, TYPE specifies the component name, the binding specifies how the component gets the data, and Property-path is a collection of attributes, which is generally Define in the JavaBean, such as the above Property-path = "student", there should be a function GetStudent in the corresponding JavaBean class listStudent. ListStudent is a Foreach component, which is actually a for loop, which is read from the Source to the value specified by the value of the value parameter. ID, Name, Gnder, Department, the four is the INSERT component, this component is used to insert text data, the parameter value specifies the value to be inserted, and the Property-Path specifies how these values ​​are obtained, and Eachstudent.id is equivalent to calling JavaBean getStudent (). GetId (). Add is a PAGE component, and the page property specifies the page name (defined in the Application file), static-binding indicates that the data to be bound is unmodified. $ REMOVE $ component is not described in this file because this component is automatically deleted because TapeStry runtime.</p> <p>Look ListStudent following categories: package test; import com.primix.tapestry *; import sun.jdbc.odbc.JdbcOdbcDriver; / ** * returns each student data * * / 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, where the DETACH function is the action that is performed when the page is placed in the buffer pool, and the getStudent function returns all student records, which is assigned to the Source parameter of the Liststudent component in the JWC file, getEachstudent gives this component The value parameter assignment, because Source is an array, each loop needs to be taken from the record assignment to EachStudent, so there is a function to setEachstudent, you will notice this function is simple, actually TapeStry helps you do most of the work.</p> <p>At this point, it shows that the student's part has been completed, look at EditStudent.html <html> <head> <title> Add Student </ Title> <meta http-equiv = "content-type" content = "text / html; charset = GB2312 "> </ head> <body> <p> Student management system </ p> <form jwcid =" form "> <span jwcid =" iferror "> <font size = 2 color = red> <span jwcid = "InsertErterror" /> </ font> </ span> <p> student number: <input jwcid = "id" /> </ p> <p> Name: <input jwcid = "name" /> </ p> <span jwcid = "gender"> <p> Gender: <input jwcid = "male" /> male <input jwcid = "female" /> female </ p> </ span> <p> class: <input jwcid = "Department" /> </ p> <p> <input type = "submit" value = "OK"> </ p> </ form> </ body> </ html> In this file, I have used some Common components, first look at the description of these components in EditStudent.jWC: <specification class = "test.editstudent"> <component id = "form" type = "form"> <binding name = "listener" Property-Path = "listeners.formMit" /> </ 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"> <</p> <p>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 that Submit This function is handled. IfError is a Conditional component, this component specifies that it will only be displayed when Condition is satisfied, in this case, if Error is not empty, then Condition is satisfied. In this component, there are components nested in the INSERT type to display errors. This is how often the handling errors often used in Tapestry. Gender is a Radiogroup component that binds the gender attribute in javabean, and the Selected parameter specifies that Radio is selected. In this component, two Radio components are nested, which are used to represent men, women. Radio's Value parameter specifies that when the user selects this RADIO, the attribute value of the RadioGroup bound 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 whose parameter value is bound to the ID attribute in JavaBean.</p> <p>Here is the corresponding EditStudent categories: 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 gamegender ()} 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; FireObser Vedchange ("Department", value);} public void formsubmit (IREQUESTCY CYCLE) {// Determined whether the user has finished all data IF (Gnder == 0 || ID == Null || ID.Equals (") || Sname == null || Sname.Equals ("") || Department == null || Department.equals (")) {Error =" Please fill all the options "; return;} // Save the student Try { Student Student = new student (); student.setId (ID); student.setname (sname); if (Gnder == 1) Student.setgender ("Men"); Else Student.SetGender ("Female"); Student. SetDepartment; student.save (null);} catch (exception e) {E.PrintStackTrace ();} // Clear the current attributes, so as not to enter this page again,</p> <p>Each attribute still retains the original value setsname (null); setDepartment (null); setid (null); setgender (0); // redirect to home page cycle.setpage ("home);}}) Setting the FireObserveDchange function in the function of the setting property, this function excites a changing event, notifying the value of the current attribute has changed. Other Applications in Workbench in Tapestry Demo how to use localization, you only need to create HTML templates for different languages, as well as other HTMLs, other HTMLs, such as graphics. For example, create a French version of EditStudent.html, the corresponding HTML file is called EditStudent_fr.html, while the description of the components defined in the JWC does not have multiple versions. Here you will introduce a concept that TapeStry is often used in localization: assets. Assets is some resources used in Web applications, such as images, videos. There are three kinds of Assets: External, Internal and Private. The EXTERNAL type ASSETS is derived from any URL. The INTERNAL type Assets comes from the URL of the Tapestry to the same server. The Private type assets allows deployment in the WAR's web-inf / class directory (like the above HTML template, JWC files), this directory is invisible for the web server. Look at the piece of localization.jwc file in the localization.jwc file in Workbench: <component id = "changebutton" type = "imageSubmit"> <binding name = "image" proty = "assets.change-button" /> </ Component> <private-asset name = "Change-button" resource-path = "/ tutorial / workbench / localization / change.gif" /> use private assets in the ChangeButton component, and these image files are in WAR Under Web-INF / CLASSES, pay attention to the image as a version of multiple languages ​​as HTML. Note that the INPUTLOCALE in the JWC file is actually localized by this component. Please see its developer guide for specific parameters. <component id = "infutlocale" type = "protyselection"> <binding name = "value" property-path = "Page.Engine.locale" /> <binding name = "model" property-path = "localemodel" /> < / Component> TapeStry also supports creating its own reusable components, with one such example: border. At the same time, there are other examples: Inspector shows how to monitor your app. VLIB is a J2EE application (using JBoss as an application server) with TapeStry.</p></div><div class="text-center mt-3 text-grey"> 转载请注明原文地址:https://www.9cbs.com/read-44938.html</div><div class="plugin d-flex justify-content-center mt-3"></div><hr><div class="row"><div class="col-lg-12 text-muted mt-2"><i class="icon-tags mr-2"></i><span class="badge border border-secondary mr-2"><h2 class="h6 mb-0 small"><a class="text-secondary" href="tag-2.html">9cbs</a></h2></span></div></div></div></div><div class="card card-postlist border-white shadow"><div class="card-body"><div class="card-title"><div class="d-flex justify-content-between"><div><b>New Post</b>(<span class="posts">0</span>) </div><div></div></div></div><ul class="postlist list-unstyled"> </ul></div></div><div class="d-none threadlist"><input type="checkbox" name="modtid" value="44938" checked /></div></div></div></div></div><footer class="text-muted small bg-dark py-4 mt-3" id="footer"><div class="container"><div class="row"><div class="col">CopyRight © 2020 All Rights Reserved </div><div class="col text-right">Processed: <b>0.028</b>, SQL: <b>9</b></div></div></div></footer><script src="./lang/en-us/lang.js?2.2.0"></script><script src="view/js/jquery.min.js?2.2.0"></script><script src="view/js/popper.min.js?2.2.0"></script><script src="view/js/bootstrap.min.js?2.2.0"></script><script src="view/js/xiuno.js?2.2.0"></script><script src="view/js/bootstrap-plugin.js?2.2.0"></script><script src="view/js/async.min.js?2.2.0"></script><script src="view/js/form.js?2.2.0"></script><script> var debug = DEBUG = 0; var url_rewrite_on = 1; var url_path = './'; var forumarr = {"1":"Tech"}; var fid = 1; var uid = 0; var gid = 0; xn.options.water_image_url = 'view/img/water-small.png'; </script><script src="view/js/wellcms.js?2.2.0"></script><a class="scroll-to-top rounded" href="javascript:void(0);"><i class="icon-angle-up"></i></a><a class="scroll-to-bottom rounded" href="javascript:void(0);" style="display: inline;"><i class="icon-angle-down"></i></a></body></html><script> var forum_url = 'list-1.html'; var safe_token = 'RWYFQhBv08N1L4O4LMCjr7N5DRzylJ20t6goxkLfHRys5HASHx_2FbgyfuzyBkYcDTImF_2FvLfSor7Oi6djTG8Vkw_3D_3D'; var body = $('body'); body.on('submit', '#form', function() { var jthis = $(this); var jsubmit = jthis.find('#submit'); jthis.reset(); jsubmit.button('loading'); var postdata = jthis.serializeObject(); $.xpost(jthis.attr('action'), postdata, function(code, message) { if(code == 0) { location.reload(); } else { $.alert(message); jsubmit.button('reset'); } }); return false; }); function resize_image() { var jmessagelist = $('div.message'); var first_width = jmessagelist.width(); jmessagelist.each(function() { var jdiv = $(this); var maxwidth = jdiv.attr('isfirst') ? first_width : jdiv.width(); var jmessage_width = Math.min(jdiv.width(), maxwidth); jdiv.find('img, embed, iframe, video').each(function() { var jimg = $(this); var img_width = this.org_width; var img_height = this.org_height; if(!img_width) { var img_width = jimg.attr('width'); var img_height = jimg.attr('height'); this.org_width = img_width; this.org_height = img_height; } if(img_width > jmessage_width) { if(this.tagName == 'IMG') { jimg.width(jmessage_width); jimg.css('height', 'auto'); jimg.css('cursor', 'pointer'); jimg.on('click', function() { }); } else { jimg.width(jmessage_width); var height = (img_height / img_width) * jimg.width(); jimg.height(height); } } }); }); } function resize_table() { $('div.message').each(function() { var jdiv = $(this); jdiv.find('table').addClass('table').wrap('<div class="table-responsive"></div>'); }); } $(function() { resize_image(); resize_table(); $(window).on('resize', resize_image); }); var jmessage = $('#message'); jmessage.on('focus', function() {if(jmessage.t) { clearTimeout(jmessage.t); jmessage.t = null; } jmessage.css('height', '6rem'); }); jmessage.on('blur', function() {jmessage.t = setTimeout(function() { jmessage.css('height', '2.5rem');}, 1000); }); $('#nav li[data-active="fid-1"]').addClass('active'); </script>