A detailed analysis of the design example of the progress bar in JSP programming

Source: Internet
Author: User
Tags object end execution http request sql sleep version thread
js| Programming | Design Many Web applications, enterprise applications involving long operations, such as complex database queries or heavy XML processing, although these tasks are mainly done by the database system or middleware, but the results of the task execution still need to use JSP to send to the user. This paper introduces a way to improve the user's feeling and reduce the load of the server by improving the front-end performance layer.

When a JSP calls an operation that must run for a long time, and the result of the operation cannot be buffered (on the server side), the user must wait for a long time each time the page is requested. Many times, the user loses patience, then tries to click on the browser's refresh button and finally leaves with disappointment.

The technique described in this article is to isolate the heavy computing task and run it by a separate thread to solve the problem. When a user invokes a JSP page, the JSP page returns immediately, prompting the user that the task is started and executing; the JSP page automatically refreshes itself and reports the current progress of the heavy computing task running on the stand-alone thread until the task is complete.

   I. Simulation Tasks

First we design a Taskbean class that implements the Java.lang.Runnable interface, and its run () method runs in a separate thread that is started by the JSP page (start.jsp). Terminating the Run () method is performed by another JSP page stop.jsp. The Taskbean class also implements the Java.io.Serializable interface so that the JSP page can invoke it as a javabean: 

Package Test.barbean; Import java.io.Serializable; public class Taskbean implements Runnable, serializable{private int counter; private int sum; private Boolean started; PR Ivate Boolean running; private int sleep; Public Taskbean () {counter = 0; sum = 0; started = false; running = false; sleep = 100;}}



Taskbean contains a "heavy task" that calculates the value of 1+2+3...+100, but it does not calculate by 100* (100+1)/2=5050 formula, but by the run () method, which calls the work () method to complete the calculation 100 times. The code for the work () method is as follows, where Thread.Sleep () is invoked to ensure that the task takes about 10 seconds.

protected void work () {try{thread.sleep (sleep); counter++; sum = counter;} catch (Interruptedexception e) {setrunning (f Alse); } }



The status.jsp page obtains the completion status of a task by calling the following Getpercent () method:

  
       
        public synchronized int getpercent () {return counter;}


If the task is already started, the isstarted () method returns true:

  
       
        Public synchronized Boolean isstarted () {return started;}


If the task is completed, the IsCompleted () method returns true:

  
       
        Public synchronized Boolean iscompleted () {return counter = = 100;}


If the task is running, the IsRunning () method returns true:

  
       
        Public synchronized Boolean isrunning () {return running;}


The Setrunning () method is called by start.jsp or stop.jsp when the running parameter is true. The Setrunning () method also marks the task as "started." Calling Setrunning (False) indicates that the run () method is required to stop execution.

  
       
        Public synchronized void Setrunning (Boolean running) {this.running = running; if (running) started = true;}


When the task completes, the call to the GetResult () method returns the result of the calculation, or null if the task has not yet been executed:

  
       
        Public synchronized Object GetResult () {if (iscompleted ()) to return the new Integer (sum); else return null;}


When running is marked true and completed is marked false, the run () method calls work (). In practical applications, the run () method may perform complex SQL queries, parse large XML documents, or invoke an EJB method that consumes a lot of CPU time. Note that "heavy tasks" may be performed on a remote server. The JSP page that reports the results has two choices: either wait for the task to end, or use a progress bar.

  
       
        public void Run () {try {setrunning (true), while (IsRunning () &&!iscompleted ()) work ();} finally {setrunning (f Alse); } }


   second, start the task

Start.jsp is the Welcome page that is declared in the Web.xml deployment descriptor, and the Web.xml content is: Start.jsp starts a dedicated thread to run the "heavy task" and then passes the HTTP request to status.jsp.

<?xml version= "1.0" encoding= "GB2312"?> <! DOCTYPE Web-app Public "-//sun Microsystems, INC.//DTD Web Application 2.3//en" "Http://java.sun.com/dtd/web-app_2_3. DTD "> <web-app> <welcome-file-list> <welcome-file>start.jsp</welcome-file> </ Welcome-file-list> </web-app>



start.jsp Page Utilization -->Tag creates an instance of Taskbean, defining the scope property as session so that other pages can be extracted to the same Bean object for HTTP requests from the same browser. Start.jsp by calling Session.removeattribute ("task") to ensure thatCreates a new bean object instead of extracting an old object (for example, a bean object created by an earlier JSP page in the same user session).


Here is the code listing for the start.jsp page: 

          <% Session.removeattribute ("task"); %> <jsp:usebean id= "task" scope= "session" class= "Test.barBean.TaskBean"/> <% (True); %> <% New Thread (Task). Start (); %> <jsp:forward page= "status.jsp"/>



Start.jsp creates and sets the Taskbean object, then creates a thread and passes the Bean object as a runnable instance. Calling the start () method the newly created thread executes the Taskbean object's Run () method. 

now has two threads executing concurrently: The thread that executes the JSP page (called a "JSP thread"), the thread created by the JSP page (called the "Task Thread"). Next, Start.jsp uses the call status.jsp,status.jsp to show the progress bar and the execution of the task. Note that status.jsp and start.jsp are running in the same JSP thread.

Start.jsp Sets the Taskbean running tag to true before the thread is created, so that even when the JSP thread has started to perform the status.jsp and the task thread's Run () method has not been started, the user is assured of a " The status report of the task has started running.

Sets the running tag to true, the two lines of code that start a task thread can move into a taskbean form a new method, and then call the new method by the JSP page. In general, JSP pages should use less Java code, that is, we should put Java code into Java classes as much as possible. In this case, however, we do not follow this rule, putting the new thread (Task) directly into the start.jsp highlight that the JSP thread created and started the task thread.

manipulating multithreading in JSP pages must be cautious, noting that JSP threads and other threads are actually executed concurrently, as in a desktop application, we use one thread to handle GUI events, and one or more threads to handle background tasks.

However, in a JSP environment, the same JSP page may run concurrently in multiple threads, considering that multiple users are requesting a page at the same time, and sometimes the same user may issue multiple requests to the same page, although these requests are from the same user. They also cause the server to run multiple threads of a JSP page at the same time.



  Iii. Progress of the Mission

The status.jsp page uses an HTML progress bar to show the user how the task is performing. First, status.jsp usesthe tag to get the Bean object created by the start.jsp page:


      
         <jsp:usebean id= "Task" scope= "session" class= "Test.barBean.TaskBean"/>


In order to reflect the progress of task execution in time, status.jsp will refresh automatically. JavaScript code settimeout ("location=′status.jsp′", 1000) refreshes the page every 1000 milliseconds, requesting status.jsp again without user intervention.


       
          <HTML> <HEAD> <title>jsp progress bar </TITLE> <% if (task.isrunning ()) {%> <script language= " JavaScript "> settimeout (" location=′status.jsp′ ", 1000); </SCRIPT> <%}%> </HEAD> <BODY>


The progress bar is actually an HTML table that contains 10 units, each of which represents 10% progress for the overall task.


       
          <H1 align= "Center" >jsp progress bar </H1> 



Results:


       
          <%= Task.getresult ()%><br> <% int percent = task.getpercent ();%> <%= percent%>% </H2> < TABLE width= "60%" align= "CENTER" border=1 cellpadding=0 cellspacing=2> <TR> <% for (int i = i <= percen T  i + +) {%> <td width= "10%" bgcolor= "#000080" > </TD> <%}%> <% for (int i = i > percent; i = ten {%> <td width= "10%" > </TD> <%}%> </TR> </TABLE>


Task execution is divided into the following states: Executing, completed, not started, stopped:


       
          <table width= "100%" border=0 cellpadding=0 cellspacing=0> <TR> <td align= "CENTER" > <% if ( Task.isrunning ()) {%>


Being executed


       
          <%} else {%> <% if (task.iscompleted ()) {%>


Complete


       
          <%} else if (!task.isstarted ()) {%>


Not yet started


       
          <%} else {%>


Has stopped


       
          <%}%> <%}%> </TD> </TR>


The bottom of the page provides a button that users can use to stop or restart a task:


       
          <TR> <td align= "CENTER" > <BR> <% if (task.isrunning ()) {%> <form method= ' get ' action= ' stop.js P "> <input type=" SUBMIT "value=" Stop "> </FORM> <%} else {%> <form method=" Get "action=" start.jsp "& Gt <input type= "SUBMIT" value= "Start" > </FORM> <%}%> </TD> </TR> </TABLE> </body>& Lt;/html>


As long as you do not stop the task, about 10 seconds after the browser will display the calculation results 5050:

  iv. Cessation of tasks

The stop.jsp page sets the running tag to false to stop the current calculation task:


       
          <jsp:usebean id= "Task" scope= "session" class= "Test.barBean.TaskBean"/> <% (false); %> <jsp:forward page= "status.jsp"/>

Note that the earliest Java version provides the Thread.stop method, but the JDK has not been in favour of using the Thread.stop method since version 1.2, so we cannot call Thread.stop () directly.

The first time you run this program, you'll see a bit of a delay in the start of the task; Similarly, the first time you click the "Stop" button you can see that the task does not immediately stop running (especially if the machine configuration is lower, the latency is more pronounced), these delays are caused by compiling the JSP page. After compiling the JSP page, the response speed will be much faster.

   v. Practical Application

The progress bar not only makes the user interface more user-friendly, but also benefits the performance of the server, because the progress bar keeps telling the user the current execution progress, and the user does not stop and restart (refresh) the current task frequently. On the other hand, creating a separate thread to perform background tasks also consumes a lot of resources and, if necessary, allows for the reuse of thread objects through a thread pool. In addition, frequent refresh of the progress page also increases network communication overhead, so be sure to keep the progress page simple and short.

In practice, heavy tasks in the background may not be allowed to stop, or it cannot provide detailed execution progress data. For example, when you find or update a relational database, you are not allowed to stop during SQL command execution?? However, if the user indicates that he wants to stop or abort the task, the program can rollback the transaction after the SQL command has finished executing.

When parsing an XML document, we have no way of knowing the exact percentage of the parsed content. If you parse an XML document with the DOM, you will not get the entire document tree until the parse is complete; If you use sax, you can know what is currently being parsed, but it is often not certain how much of the content needs to be resolved. On these occasions, the progress of the task can only be estimated.

It is often difficult to estimate how much execution time a task requires, because it involves a number of factors, even if the actual test method does not get a reliable conclusion because the load of the server is constantly changing. An easy way is to measure the time required for each execution of a task, and then estimate it based on the average time of the last few executions.

If you want to improve the accuracy of the estimated time, you should consider implementing an application-specific algorithm that takes into account a variety of factors, such as the type of SQL statement to be executed, the complexity of the XML schema to parse, and so on.

Conclusion: This example shows that it is fairly easy to construct a progress bar with JSP, Java, HTML, and JavaScript, and it is really difficult to use it in practical applications, especially to get progress information for background tasks, but there is no general answer to this question. Each kind of backstage execution's task has its own characteristic, must according to the concrete situation concrete analysis.



Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.