Understanding JavaServer Pages Model 2 architecture part1

来源:百度文库 编辑:神马文学网 时间:2024/04/28 07:53:49
Understanding JavaServer Pages Model 2 architecture
Exploring the MVC design pattern
By Govind Seshadri, JavaWorld.com, 12/29/99
Despite its relatively recent introduction, JavaServer Pages (JSP)technology is well on its way to becoming the preeminent Javatechnology for building applications that serve dynamic Web content.Java developers love JSP for myriad reasons. Some like the fact that itbrings the "write once, run anywhere" paradigm to interactive Webpages; others appreciate the fact that it is fairly simple to learn andlets them wield Java as a server-side scripting language. But mostconcur on one thing -- the biggest advantage of using JSP is that ithelps effectively separate presentation from content. In this article,I provide an in-depth look at how you can gain optimal separation ofpresentation from content by using the JSP Model 2 architecture. Thismodel can also be seen as a server-side implementation of the popularModel-View-Controller (MVC) design pattern. Please note that you shouldbe familiar with the basics of JSP and servlet programming beforecontinuing on, as I do not address any syntax issues in this article.
Server-Side Java: Read the whole series!
Welcome to the server-side Java series
Create forward-compatible beans in EJB, Part 1
Understanding JavaServer Pages Model 2 Architecture
So, what‘s wrong with servlets?
WhileJSP may be great for serving up dynamic Web content and separatingcontent from presentation, some may still wonder why servlets should becast aside for JSP. The utility of servlets is not in question. Theyare excellent for server-side processing, and, with their significantinstalled base, are here to stay. In fact, architecturally speaking,you can view JSP as a high-level abstraction of servlets that isimplemented as an extension of the Servlet 2.1 API. Still, youshouldn‘t use servlets indiscriminately; they may not be appropriatefor everyone. For instance, while page designers can easily write a JSPpage using conventional HTML or XML tools, servlets are more suited forback-end developers because they are often written using an IDE -- aprocess that generally requires a higher level of programmingexpertise. When deploying servlets, even developers have to be carefuland ensure that there is no tight coupling between presentation andcontent. You can usually do this by adding a third-party HTML wrapperpackage like htmlKonato the mix. But even this approach, though providing some flexibilitywith simple screen changes, still does not shield you from a change inthe presentation format itself. For example, if your presentationchanged from HTML to DHTML, you would still need to ensure that wrapperpackages were compliant with the new format. In a worst-case scenario,if a wrapper package is not available, you may end up hardcoding thepresentation within the dynamic content. So, what is the solution? Asyou shall soon see, one approach would be to use both JSP and servlettechnologies for building application systems.
Differing philosophies
Theearly JSP specifications advocated two philosophical approaches forbuilding applications using JSP technology. These approaches, termedthe JSP Model 1 and Model 2 architectures, differ essentially in thelocation at which the bulk of the request processing was performed. Inthe Model 1 architecture, shown in Figure 1, the JSP page alone isresponsible for processing the incoming request and replying back tothe client. There is still separation of presentation from content,because all data access is performed using beans. Although the Model 1architecture should be perfectly suitable for simple applications, itmay not be desirable for complex implementations. Indiscriminate usageof this architecture usually leads to a significant amount ofscriptlets or Java code embedded within the JSP page, especially ifthere is a significant amount of request processing to be performed.While this may not seem to be much of a problem for Java developers, itis certainly an issue if your JSP pages are created and maintained bydesigners -- which is usually the norm on large projects. Ultimately,it may even lead to an unclear definition of roles and allocation ofresponsibilities, causing easily avoidable project-management headaches.

Figure 1: JSP Model 1 architecture
TheModel 2 architecture, shown in Figure 2, is a hybrid approach forserving dynamic content, since it combines the use of both servlets andJSP. It takes advantage of the predominant strengths of bothtechnologies, using JSP to generate the presentation layer and servletsto perform process-intensive tasks. Here, the servlet acts as the controllerand is in charge of the request processing and the creation of anybeans or objects used by the JSP, as well as deciding, depending on theuser‘s actions, which JSP page to forward the request to. Noteparticularly that there is no processing logic within the JSP pageitself; it is simply responsible for retrieving any objects or beansthat may have been previously created by the servlet, and extractingthe dynamic content from that servlet for insertion within statictemplates. In my opinion, this approach typically results in thecleanest separation of presentation from content, leading to cleardelineation of the roles and responsibilities of the developers andpage designers on your programming team. In fact, the more complex yourapplication, the greater the benefits of using the Model 2 architectureshould be.

Figure 2: JSP Model 2 architecture
In order to clarify the concepts behind the Model 2 architecture, let‘s walk through a detailed implementation of it: a sampleonline music store called Music Without Borders.
SUBHEAD_BREAK: Understanding Music Without Borders The main view, or presentation, for our Music Without Borders online store is facilitated by the JSP page EShop.jsp(shown in Listing 1). You will notice that the page deals almostexclusively with presenting the main user interface of the applicationto the client, and performs no processing whatsoever -- an optimal JSPscenario. Also, notice that another JSP page, Cart.jsp (shown in Listing 2), is included within EShop.jsp via the directive .
Listing 1:
EShop.jsp
<%@ page session="true" %> Music Without Borders Music Without Borders

CD: Quantity:


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)) { %>

<% for (int index=0; index < buylist.size();index++) { CD anOrder = (CD) buylist.elementAt(index); %> <% } %>
ALBUM ARTIST COUNTRY PRICE QUANTITY
<%= anOrder.getAlbum() %> <%= anOrder.getArtist() %> <%= anOrder.getCountry() %> <%= anOrder.getPrice() %> <%= anOrder.getQuantity() %>
‘>

<% } %>
Here, Cart.jsp handles the presentation of the session-based shopping cart, which constitutes the model in our MVC architecture. Observe the scriptlet at the beginning of Cart.jsp:
<%Vector buylist = (Vector) session.getValue("shopping.shoppingcart");if (buylist != null && (buylist.size() > 0)) {%>
Basically, thescriptlet extracts the shopping cart from the session. If the cart isempty or not yet created, it displays nothing; thus, the first time auser accesses the application, she is presented with the view shown inFigure 3.

Figure 3: Music Without Borders, main view
If the shopping cart is not empty, then the selected items are extracted from the cart one at a time, as demonstrated by thefollowing scriptlet:
<%for (int index=0; index < buylist.size(); index++) {CD anOrder = (CD) buylist.elementAt(index);%>
Once the variablesdescribing an item have been created, they are then simply insertedinto the static HTML template using JSP expressions. Figure 4 shows theapplication view after the user has placed some items in the shoppingcart.

Figure 4: Music Without Borders, shopping cart view
The important thing to observe here is that the processing for all actions carried out within either Eshop.jsp or Cart.jsp is handled by the controller servlet, ShoppingServlet.java, which is 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 first cd to the cart buylist = new Vector(); //first order buylist.addElement(aCD); } else { // not first buy 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 for 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 this was 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; } }
Every time the user adds an item within EShop.jsp,the request is posted to the controller servlet. The servlet in turndetermines the appropriate action, and then processes the requestparameters for the item to be added. It then instantiates a new CD bean(shown in Listing 4) representing the selection, and goes aboutupdating the shopping cart object before placing it back within thesession.