JSP programming progress bar Design

Source: Internet
Author: User

Many Web applications and enterprise applications involve long-time operations, such as complex database queries or heavy XML processing. Although these tasks are mainly completed by the database system or middleware, however, the results of task execution can still be sent to the user through JSP. This article introduces a method to improve user perception and reduce server load by improving the front-end presentation layer.

When 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 when requesting the page. Most of the time, the user will lose patience, and then try to click the refresh button of the browser, and finally leave with disappointment.

The technology introduced in this article is to separate heavy computing tasks and run them in an independent thread to solve the above problems. When a user calls a JSP page, the JSP page returns immediately and prompts that the user task has been started and is being executed. The JSP page automatically refreshes itself, report the current progress of a heavy computing task running in an independent thread until the task is completed.

I. simulate a task

First, we design a taskbean class that implements the java. Lang. runnable interface. Its run () method runs in an independent thread started by the JSP page (start. jsp. The execution of the run () method is the responsibility of stop. jsp on another JSP page. The taskbean class also implements the java. Io. serializable interface, so that the JSP page can call 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;
Private Boolean running;
Private int sleep;
Public taskbean (){
Counter = 0;
Sum = 0;
Started = false;
Running = false;
Sleep = 100;
}
}
Taskbean's "heavy task" is computing 1 + 2 + 3... The value of + 100 is calculated by calling the work () method 100 times instead of the formula 100*(5050 + 1)/2 = 100. The code for the work () method is as follows, in which thread. Sleep () is called to ensure that the total task time is about 10 seconds.
Protected void work (){
Try {
Thread. Sleep (sleep );
Counter ++;
Sum + = counter;
} Catch (interruptedexception e ){
Setrunning (false );
}
}
The status. jsp page obtains the task completion status by calling the following getpercent () method:
Public synchronized int getpercent (){
Return counter;
}
If the task has been started, the isstarted () method returns true:
Public synchronized Boolean isstarted (){
Return started;
}
If the task has been 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;
}

After the task is completed, call the getresult () method to return the calculation result. If the task has not been completed, it returns NULL: Public synchronized object getresult (){
If (iscompleted ())
Return new INTEGER (SUM );
Else
Return NULL;
}

When running is marked as true and completed is marked as false, the run () method calls work (). In practical applications, the run () method may need to execute complicated SQL queries, parse large XML documents, or call the EJB method that consumes a lot of CPU time. Note that "heavy tasks" may be executed on remote servers. The JSP page of the report result has two options: Wait for the task to end, or use a progress bar.

Public void run (){
Try {
Setrunning (true );
While (isrunning ()&&! Iscompleted ())
Work ();
} Finally {
Setrunning (false );
}
}

Ii. Start the task

Start. jsp is the welcome page stated in the web. xml deployment descriptor. The content of web. XML is:
<? 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 starts a dedicated thread to run "heavy tasks", and then passes the HTTP request to status. jsp.
Start. the JSP page uses the <JSP: usebean> tag to create a taskbean instance and defines the scope attribute as a session so that other pages can be extracted to the same bean object for HTTP requests from the same browser. Start. JSP calls the session. removeattribute ("task") ensures that <JSP: usebean> creates a new bean object instead of extracting an old object (for example, the bean object created on the JSP page earlier in the same user session ).

The following is a list of codes on the start. jsp page:

<% Session. removeattribute ("task"); %>
<JSP: usebean id = "task" Scope = "session"
Class = "test. barbean. taskbean"/>
<% Task. setrunning (true); %>
<% New thread (task). Start (); %>
<JSP: Forward page = "status. jsp"/>

After start. jsp creates and sets the taskbean object, it creates a thread and passes in the bean object as a runnable instance. When the START () method is called, the newly created thread executes the run () method of the taskbean object.

Now there are two threads running concurrently: the thread that executes the JSP page (called the "JSP thread"), the thread created by the JSP page (called the "task thread "). Next, start. jsp uses the call status. jsp and status. jsp to display the progress bar and task execution status. Note that status. jsp and start. jsp run in the same JSP thread.
Start. before creating a thread, JSP sets the running mark of taskbean to true, even if the JSP thread has started to execute status. JSP and the run () method of the task thread has not been started. It can also ensure that the user will receive the status report "The task has started running.

Set the running flag to true and start the task thread. These two lines of code can be moved into taskbean to form a new method, which is then called on the JSP page. Generally, JSP pages should use Java code as little as possible, that is, we should put Java code into Java classes as much as possible. However, in this example, we do not follow this rule and put new thread (task). Start () directly into start. jsp to highlight that the JSP thread has created and started the task thread.

Be cautious when operating multithreading on JSP pages. Note that JSP threads and other threads are actually executed concurrently, just as in a desktop application, we use a thread to process GUI events, in addition, one or more threads are used to process Background tasks. However, in the JSP environment, considering that multiple users request a page at the same time, the same JSP page may run simultaneously in multiple threads. In addition, sometimes the same user may send multiple requests to the same page. Although these requests come from the same user, they also cause the server to run multiple threads on one JSP page at the same time.

Iii. Task progress

The status. jsp page displays the execution status of the task to the user using an HTML progress bar. First, status. jsp uses the <JSP: usebean> tag to obtain the bean object created on the start. jsp page:

<JSP: usebean id = "task" Scope = "session"
Class = "test. barbean. taskbean"/>

To timely reflect the task execution progress, status. jsp will be automatically refreshed. The javascript code setTimeout ("location = 'status. jsp '", 1000) refresh the page every 1000 milliseconds and Request 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>

The progress bar is actually an HTML table containing 10 units-each representing the overall 10% progress of the task.
<H1 align = "center"> JSP progress bar <H2 align = "center">
Result: <% = task. getresult () %> <br>
<% Int percent = task. getpercent (); %>
<% = Percent %> %
</H2>
<Table width = "60%" align = "center"
Border = 1 cellpadding = 0 cellspacing = 2>
<Tr>
<% For (INT I = 10; I <= percent; I ++ = 10) {%>
<TD width = "10%" bgcolor = "#000080"> </TD>
<% }%>
<% For (INT I = 100; I> percent; I-= 10) {%>
<TD width = "10%"> </TD>
<% }%>
</Tr>
</Table>

Task execution is in the following statuses: Execution in progress, completed, not started, and stopped:

<Table width = "100%" border = 0 cellpadding = 0 cellspacing = 0>
<Tr>
<TD align = "center">
<% IF (task. isrunning () {%>
Executing
<%} Else {%>
<% IF (task. iscompleted () {%>
Complete
<%} Else if (! Task. isstarted () {%>
Not started
<%} Else {%>
Stopped
<% }%>
<% }%>
</TD>
</Tr>
A button is provided at the bottom of the page, which can be used to stop or restart a task:

<Tr>
<TD align = "center">
<Br>
<% IF (task. isrunning () {%>
<Form method = "get" Action = "Stop. jsp">
<Input type = "Submit" value = "stop">
</Form>
<%} Else {%>
<Form method = "get" Action = "start. jsp">
<Input type = "Submit" value = "start">
</Form>
<% }%>
</TD>
</Tr>
</Table>
</Body>

As long as the task is not stopped, the browser will display the computing result 5050 in about 10 seconds:

4. Stop a task
On the stop. jsp page, set the running flag to false to stop the current computing task:
<JSP: usebean id = "task" Scope = "session"
Class = "test. barbean. taskbean"/>
<% Task. setrunning (false); %>
<JSP: Forward page = "status. jsp"/>

Note that the thread. Stop method is provided in the earliest Java version, but JDK does not approve of using the thread. Stop method since version 1.2, so we cannot directly call thread. Stop ().

When you run the program in this article for the first time, you will see a delay in starting the task. Similarly, when you click "stop" for the first time, you can also see that the task is not stopped immediately (especially if the machine configuration is low, the latency is more obvious ), these latencies are caused by compiling JSP pages. After the JSP page is compiled, the response speed is much faster.
V. Practical Application
The progress bar not only makes the user interface more friendly, but also improves the performance of the server, because the progress bar constantly tells the user the current execution progress, the user will no longer stop and restart (refresh) the current task frequently. On the other hand, creating a separate thread to execute background tasks also consumes a lot of resources. If necessary, you can use a thread pool to reuse thread objects. In addition, refreshing the progress page frequently increases the network communication overhead, so make sure that the progress page is concise and short.

In practical applications, heavy tasks executed in the background may not be stopped, or they cannot provide detailed execution progress data. For example, when you search for or update a relational database, you cannot stop the SQL command during execution. However, if the user indicates that he wants to stop or stop the task, the program can roll back the transaction after the SQL command is executed.

When parsing XML documents, we cannot know the precise percentage of parsed content. If you use Dom to parse an XML document, the entire document tree will not be obtained until the parsing is complete. If you use SAX, although you can know the content to be parsed, you cannot determine the amount of content to be parsed. In these cases, the task execution progress can only be estimated.
  

It is usually difficult to estimate how much execution time a task needs, because it involves many factors, that is, the method of using actual tests cannot be reliably concluded, because the server load is changing at any time. A simple method is to measure the time required for each task execution, and then estimate the average time of the last few executions. If you want to improve the accuracy of the estimated time, you should consider implementing an algorithm based on the characteristics of the application, taking into account a variety of factors, for example, the type of SQL statement to be executed, the complexity of the XML mode to be parsed, and so on.

Conclusion: The example in this article shows that it is quite easy to construct a progress bar using JSP, Java, HTML, and Javascript. What is really difficult is how to apply it to practical applications, in particular, the progress information of background tasks is obtained, but there is no general answer to this question. Each background task has its own characteristics and must be analyzed according to the specific situation.

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.