js| Architecture | Design Summary: By developing a familiar web-based shopping store, you'll learn how to tool MVC design patterns and really isolate content and performance when using JSP. Govind Seshadri will show you how easy it is (2000 words (original number)).
Despite the relatively recent introduction, JSP technology is well on its way to becoming an excellent Java technology for creating applications that provide dynamic Web content. Java developers love JSP for many different reasons. Some people like it brings the fact that interactive Web pages are "written, run everywhere," and others appreciate that it's easy to learn and help people use Java as a server-side script. But it's universally acknowledged that the biggest advantage of using JSP is the ability to effectively separate content from performance. In this article, I'll provide an in-depth view of how to use the JSP Schema 2 architecture to get the best content and performance separation. This pattern can also be seen as the implementation of the popular MVC design pattern on the server side. Please note that you should be familiar with JSP and servlet programming before you begin, because I will not discuss grammar issues in this article.
So what's wrong with the servlet?
Now that the JSP is used to provide dynamic Web content and is good for separating content from the presentation layer, some people may wonder why the servlet has to be detached from the JSP and tied to it. The servlet function is fine. It works well for server-side processing and, because of its important installed base, is appropriate for this. In fact, structurally, you can think of JSP as an extended servlet advanced abstraction that implements the Servlet 2.1 API. The servlet should still be used without distinction, and it may not apply to everyone. For example, although page designers can easily write JSP pages using regular HTML or XML tools, and servlet is usually better suited for background developers, they typically use some kind of ide--process that typically requires high-level programming expertise. When the servlet is released, even developers must be aware and confirm that there is no tight coupling between content and performance. Typically, you can do this by adding a third party HTML package such as Htmlkona. Even if you do, there are some simple scalability changes to the screen that still can't protect you from the changes in the presentation format itself. For example, if your presentation changes from HTML to DHTML, you will still need to verify that your package is compatible with this new format. In the worst case scenario, if the package is not available, you may end up hard-coded representations within the dynamic content. So, what is the solution? As you'll see, one way will be to use both the JSP and the servlet to create the application system.
Philosophy of Difference
The early JSP specification advocates two philosophical approaches to creating applications using JSP technology. These two ideas, in terms of JSP mode 1 and Mode 2, essentially differ in the place where most requests are processed. In the schema 1 architecture, as shown in Figure 1, JSP pages are independently responsible for processing requests and sending feedback to clients. There is still a separation of content and performance, because all data access is done using beans. Although the schema 1 architecture should be ideal for simple applications, it is undesirable for complex implementations. The arbitrary use of this structure often results in a large number of scripts and Java code embedded in the JSP page, especially if there is a large number of requests to be processed. While this may not be a big problem for Java developers, it is certainly a problem if your JSP pages are created and maintained by the designer-often in large projects. Ultimately, this problem can even lead to confusion in the definition of roles and allocation of responsibilities, causing problems with project management that can easily be avoided.
Figure 1:jsp Mode 1 structure
The schema 2 architecture, as shown in Figure 2, is a hybrid scenario for dynamic content services because it uses both servlet and JSP. It leverages the advantages of two technologies, using JSP to generate the presentation layer and the servlet responsible for performing sensitive tasks. Here, the servlet plays the role of the Controller, responsible for requesting processing and generating the beans and objects to be used by the JSP, and deciding which JSP page to forward next to according to the customer's actions. It is important to note that there is no processing logic inside the JSP page, it is simply responsible for obtaining objects and beans that may have been created beforehand by Servelet, and for inserting dynamic content from the servlet in the static template. My point of view is that this approach generally forms the most clean and thorough separation of content and the roles and responsibilities of developers and page designers in your development team. In fact, the more complex your application, the more benefits you will get from using mode 2.
Figure 2:jsp Mode 2 structure
To figure out the concept behind mode 2, let's look at a detailed implementation: A sample of an online music store called Music without boundaries.
Learn about music without boundaries
The main view, or the presentation layer, for our music is unbounded by the JSP page eshop.jsp (see Listing 1). You'll notice that this page is almost just dealing with the main user interface of the application and not doing any work--an optimal JSP script. Also notice another JSP page, cart.jsp (see Listing 2), with instructions <jsp:include page= "cart.jsp" flush= "true"/> contained within eshop.jsp.
Listing 1 eshop.jsp |
<%@ page session= "true"%> <title>music without borders</title> <body bgcolor= "#33CCFF" > <font face= "Times New roman,times" size= "+3" > Music without Borders </font> <center> <form name= "Shoppingform" action= "/examples/servlet/shoppingservlet" method= "POST" > <b>CD:</b> <select name=cd> <option>yuan | The Guo Brothers | Our | $14.95</option> <option>drums of Passion | Babatunde Olatunji | Nigeria | $16.95</option> <option>kaira | Tounami diabate| Mali | $16.95</option> <option>the Lion is Loose | Eliades Ochoa | Cuba | $13.95</option> <option>dance the Devil Away | Outback | Australia | $14.95</option> <option>record of Changes | Samulnori | Korea | $12.95</option> <option>djelika | Tounami Diabate | Mali | $14.95</option> <option>rapture | Nusrat Fateh Ali Khan | Pakistan | $12.95</option> <option>cesaria Evora | Cesaria Evora | Cape Verde | $16.95</option> <option>ibuki | Kodo | Japan | $13.95</option> </select> <b>quantity: </b><input type= "text" Name= "qty" size= "3" value=1> <input type= "hidden" name= "action" value= "ADD" > <input type= "Submit" name= "Submit" value= "Add to Cart" > </form> </center> <p> <jsp:include page= "cart.jsp" flush= "true"/> </body> |
Listing 2 cart.jsp |
<%@ page session= "true" import= "java.util.*, shopping. CD "%> <% Vector buylist = (vector) session.getvalue ("Shopping.shoppingcart"); if (buylist!= null && (buylist.size () > 0)) { %> <center> <table border= "0" cellpadding= "0" width= "100%" bgcolor= "#FFFFFF" > <tr> <td><b>ALBUM</b></td> <td><b>ARTIST</b></td> <td><b>COUNTRY</b></td> <td><b>PRICE</b></td> <td><b>QUANTITY</b></td> <td></td> </tr> <% for (int index=0; index < buylist.size (); index++) { cd Anorder = (CD) buylist.elementat (index); %> <tr> <td><b><%= anorder.getalbum ()%></b></td> <td><b><%= anorder.getartist ()%></b></td> <td><b><%= anorder.getcountry ()%></b></td> <td><b><%= Anorder.getprice ()%></b></td> <td><b><%= anorder.getquantity ()%></b></td> <td> <form name= "Deleteform" action= "/examples/servlet/shoppingservlet" method= "POST" > <input type= "Submit" value= "Delete" > <input type= "hidden" name= "Delindex" value= ' <%= index%> ' > <input type= "hidden" name= "action" value= "DELETE" > </form> </td> </tr> <%}%> </table> <p> <form name= "Checkoutform" action= "/examples/servlet/shoppingservlet" method= "POST" > <input type= "hidden" name= "action" value= "CHECKOUT" > <input type= "Submit" Name= "Checkout" value= "Checkout" > </form> </center> <%}%> |
Here, cart.jsp deals with the presentation of the session based shopping cart, which specifies the model in our MVC structure. Observe the script at the beginning of cart.jsp:
<%
Vector buylist = (vector) session.getvalue ("Shopping.shoppingcart");
if (buylist!= null && (buylist.size () > 0)) {
%>
Basically, this script presents the shopping cart from the session. If the cart is empty or has not been created, it will not show anything; therefore, when the user first visits, he sees the page as shown in Figure 3.
Figure 3: Music unbounded, main view
If the cart is not empty, the selected items are presented from the cart one at a time, as demonstrated in the following script:
<%
for (int index=0; index < buylist.size (); index++) {
cd Anorder = (CD) buylist.elementat (index);
%>
Once the variables describing the items have been created, they are simply inserted into the static HTML template by the JSP expression. Figure 4 shows the situation where the user has put something in the shopping cart.
Figure 4: Music no bounds, shopping cart view
The important thing to note here is that the processing of all actions does not occur either in eshop.jsp or cart.jsp, but by the controller Servlet,shoppingservlet.java, as shown in Listing 3:
Listing 3 Shoppingservlet.java |
Import java.util.*; Import java.io.*; Import javax.servlet.*; Import javax.servlet.http.*; Import shopping. CD; public class Shoppingservlet extends HttpServlet { public void init (ServletConfig conf) throws Servletexception { Super.init (conf); } public void DoPost (HttpServletRequest req, httpservletresponse Res) Throws Servletexception, IOException { HttpSession session = Req.getsession (false); if (session = null) { Res.sendredirect ("http://localhost:8080/error.html"); } Vector buylist= (Vector) Session.getvalue ("Shopping.shoppingcart"); String action = req.getparameter ("action"); if (!action.equals ("CHECKOUT")) { if (Action.equals ("DELETE")) { String del = req.getparameter ("Delindex"); int d = (new Integer (Del)). Intvalue (); Buylist.removeelementat (d); else if (action.equals ("ADD")) { Any previous buys of same CD? Boolean match=false; CD ACD = GETCD (req); if (buylist==null) { Add a CD to the cart Buylist = new Vector (); The Order of the Buylist.addelement (ACD); else {//not? for (int i=0; i< buylist.size (); i++) { cd cd = (CD) buylist.elementat (i); if (Cd.getalbum (). Equals (Acd.getalbum ())) { Cd.setquantity (Cd.getquantity () +acd.getquantity ()); Buylist.setelementat (Cd,i); Match = true; }//end of If name matches }//End of of if (!match) Buylist.addelement (ACD); } } Session.putvalue ("Shopping.shoppingcart", buylist); String url= "/jsp/shopping/eshop.jsp"; ServletContext sc = Getservletcontext (); RequestDispatcher rd = sc.getrequestdispatcher (URL); Rd.forward (req, res); else if (action.equals ("CHECKOUT")) { float total = 0; for (int i=0; i< buylist.size (); i++) { cd Anorder = (CD) buylist.elementat (i); Float price= anorder.getprice (); int qty = anorder.getquantity (); Total + = (Price * qty); } Total = 0.005; String amount = new Float (total). toString (); int n = amount.indexof ('. '); Amount = amount.substring (0,n+3); Req.setattribute ("Amount", amount); String url= "/jsp/shopping/checkout.jsp"; ServletContext sc = Getservletcontext (); RequestDispatcher rd = sc.getrequestdispatcher (URL); Rd.forward (Req,res); } } Private CD Getcd (HttpServletRequest req) { Imagine if all is in a scriptlet...ugly, eh? String MYCD = Req.getparameter ("CD"); String qty = req.getparameter ("qty"); StringTokenizer t = new StringTokenizer (MYCD, "|"); String album= T.nexttoken (); String artist = T.nexttoken (); String country = T.nexttoken (); String Price = T.nexttoken (); Price = Price.replace (' $ ', '). Trim (); cd cd = new CD (); Cd.setalbum (album); Cd.setartist (artist); Cd.setcountry (country); Cd.setprice (New Float (Price). Floatvalue ()); Cd.setquantity (New Integer (qty)). Intvalue ()); return CD; } } |
Each time a user adds an item to the eshop.jsp, the request is sent to the controller servlet. It determines the appropriate action in turn, and then processes the request parameters of the item to be added accordingly. It instantiates a new CD bean (see listing 4) that represents the selected item, and then processes the cart update before putting the bean in session.
Listing 4 Cd.java |
Package shopping; public class CD { String album; String artist; String Country; float price; int quantity; Public CD () { Album= ""; Artist= ""; Country= ""; price=0; quantity=0; } public void Setalbum (String title) { Album=title; } Public String Getalbum () { Return album; } public void Setartist (String group) { Artist=group; } Public String getartist () { return artist; } public void Setcountry (String cty) { Country=cty; } Public String Getcountry () { return country; } public void Setprice (float p) { Price=p; } public float GetPrice () { return price; } public void setquantity (int q) { quantity=q; } public int getquantity () { return quantity; } } |
Note that we also include additional intelligence in this servlet, so that it knows that if you choose a CD that is already in your shopping cart, you should simply increase the count of the CD beans in the session. It also handles actions triggered from cart.jsp, such as deleting items from a shopping cart or continuing to checkout at the checkout counter. Note that the controller always has full control over which resources should be tuned to generate feedback for specific actions. For example, changes to the status of a shopping cart, such as additions and deletions, will cause the controller to process the request and send it to the eshop.jsp page. This causes the page to display the main view again, in turn, according to the updated shopping cart. If the user decides to checkout, the request is processed and forwarded to checkout.jsp (see Listing 5), through a subsequent request allocator, as shown below:
String url= "/jsp/shopping/checkout.jsp";
ServletContext sc = Getservletcontext ();
RequestDispatcher rd = sc.getrequestdispatcher (URL);
Rd.forward (Req,res);
Listing 5 checkout.jsp |
<%@ page session= "true" import= "java.util.*, shopping. CD "%> <title>music without Borders checkout</title> <body bgcolor= "#33CCFF" > <font face= "Times New roman,times" size=+3> Music without Borders Checkout </font> <center> <table border= "0" cellpadding= "0" width= "100%" bgcolor= "#FFFFFF" > <tr> <td><b>ALBUM</b></td> <td><b>ARTIST</b></td> <td><b>COUNTRY</b></td> <td><b>PRICE</b></td> <td><b>QUANTITY</b></td> <td></td> </tr> <% Vector buylist = (vector) session.getvalue ("Shopping.shoppingcart"); String amount = (string) request.getattribute ("Amount"); for (int i=0 i < buylist.size (); i++) { cd Anorder = (CD) buylist.elementat (i); %> <tr> <td><b><%= anorder.getalbum ()%></b></td> <td><b><%= anorder.getartist ()%></b></td> <td><b><%= anorder.getcountry ()%></b></td> <td><b><%= Anorder.getprice ()%></b></td> <td><b><%= anorder.getquantity ()%></b></td> </tr> <% } Session.invalidate (); %> <tr> <td> </td> <td> </td> <td><b>TOTAL</b></td> <td><b>$<%= Amount%></b></td> <td> </td> </tr> </table> <p> <a href= "/examples/jsp/shopping/eshop.jsp" >shop some more!</a> </center> </body> |
Checkout.jsp only presents the cart from the session and extracts the total amount for this request, then displays the selected items and their total price. Figure 5 shows the user view at the time of checkout. Once the user goes to checkout, deleting the session object is equally important. This is done by the Session.invalidate () call at the end of the page. There are two reasons why this must be done. First, if the session is not invalidated, the user's shopping cart will not be reinitialized, and if the user tries to start a new round of purchases after checkout, her shopping cart will continue to keep the items that have been paid. Second, if the user simply leaves the site after checkout, the session object is not recycled by the garbage collection mechanism but continues to occupy valuable system resources until the lease expires. Because the default session lease time is approximately 30 minutes, this can quickly lead to system memory exhaustion on a large capacity system. Of course, we all know what happens to an application that runs out of system memory.
Figure 5: Checkout View
Note that all resources in this application are session-related because the pattern is stored in the session. Therefore, you must ensure that users do not directly access the controller for some reason or even because of errors. You can avoid this by having the client automatically turn to an error page (see listing 6) When the controller detects a lack of a valid session.
List 6 Error.html |
<body> Sorry, there was a unrecoverable error! <br> Please try <a href= "/examples/jsp/shopping/eshop.jsp" >AGAIN</A>. </body> |
Deploy music without boundaries
I assume you are using the latest version of JavaServer Web Development Kit (JSWDK) from Sun to run this example. If not, refer to the Resources section to see where to get it. Assuming that the server is installed in \jswdk-1.0.1, this is the default path under Microsoft Windows system, you can deploy music-unbounded applications as follows:
Create Shopping directory under \jswdk-1.0.1\examples\jsp
Copy eshop.jsp to \jswdk-1.0.1\examples\jsp\shopping Br>copy cart.jsp to \jswdk-1.0.1\examples\jsp\shopping
Copy checkout.jsp to \jswdk-1.0.1\examples\jsp\shopping
Compile the. java files by typing javac *.java
Copy shoppingservlet.class to \jswdk-1.0.1\webpages\web-inf\servle TS
Create Shopping directory under \jswdk-1.0.1\examples\web-inf\jsp\beans
Copy Cd.class to \jswdk-1.0.1\ Examples\web-inf\jsp\beans\shopping
Copy error.html to \jswdk-1.0.1\webpages
Once Your server has been started, Y OU should be able to access the application using http://localhost:8080/examples/jsp/shopping/EShop.jsp as the URL
as soon as your server starts, you should be able to access the application using the URL http://localhost:8080/examples/jsp/shopping/EShop.jsp .
use JSP and servlet
In this example, we examine in detail the level of control and the flexibility provided by the schema 2 architecture. In fact, we've seen how the best feature of the servlet and JSP pages is how to develop the maximum content and performance stripping. As long as it is applied correctly, the schema 2 architecture centralizes all the processing logic into the controller servlet, and the JSP page is responsible only for the view or the performance layer. However, the resistance to using pattern 2 structures lies in its complexity. Therefore, it is acceptable to use mode 1 for simple applications.