理解“音乐无国界” 
  
  “音乐无国界”的主界面是JSP页 Eshop.
jsp(见代码清单1)
。你会注意到
,这个页面几乎只作为专门的用户界面
,不承担任何处理任务――是一个最理想的JSP方案
。另外,请注意另一个JSP页Cart.
jsp(见代码清单2)被Eshop.jsp通过指令<jsp:include page="Cart.jsp" flush="true" />包含于其中。   
  
  代码清单 1:EShop.jsp   
  
  <%@ page session="true" %>   
  
  <html>   
  
  <head>   
  
   <title>Music Without Borders</title>   
  
  </head>   
  
  <body bgcolor="#33CCFF">   
  
   <font face="Times New Roman,Times" size="+3">   
  
   Music Without Borders   
  
   </font>   
  
   <hr><p>   
  
   <center>   
  
   <form name="shoppingForm"   
  
   action="/examples/servlet/ShoppingServlet"   
  
   method="POST">   
  
   <b>CD:</b>   
  
   <select name=CD>   
  
   <option>Yuan | The Guo Brothers | China | $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>   
  
  </html>   
  
  代码清单 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>   
  
  <% } %>   
  
  这里,Cart.jsp操纵着基于会话的购物车的表达,在MVC体系中,购物车就充当Model的角色。   
  
  观察Cart.jsp开头处的脚本片段:   
  
  <%   
  
   Vector buylist = (Vector) session.getValue("shopping.shoppingcart");   
  
   if (buylist != null && (buylist.size() > 0)) {   
  
  %>   
  
  这段脚本主要是从会话中取出购物车。如果购物车是空的或尚未创建,则它什么都不显示;因此,当用户第一次访问这个应用程序时,呈现给他的视图如图3所示:   
  
  
  图3:音乐无国界,主视图   
  
  图中按钮文字:放入购物车   
  
  如果购物车不为空,则选中的物品被依次从购物车中取出,如下面的脚本片段所示:   
  
  <%   
  
   for (int index=0; index < buylist.size(); index++) {   
  
  CD anOrder = (CD) buylist.elementAt(index);   
  
  %>   
  
  描述物品的变量一旦被创建,就会被用JSP表达式直接嵌入静态HTML模板中去。图4显示了当用户向购物车中放入一些物品后的视图。   
  
  
  图4:音乐无国界,购物车视图   
  
  图中文字:Music Without Borders:音乐无国界;Quantity:数量;ALBUM:唱片;ARTIST:演唱者;COUNTRY:国家;PRICE:价格;Delete:删除;Checkout:结帐。   
  
  这里需要注意的重要一点是,在Eshop.jsp和Cart.jsp中实现的对所有动作的处理都由一个servlet――ShoppingServlet.java控制,如代码清单3所示:   
  
  代码清单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")) {   
  
  //以前是否购买了同样的cd?   
  
  boolean match=false;   
  
  CD aCD = getCD(req);   
  
  if (buylist==null) {   
  
   //将第一张CD放入购物车   
  
   buylist = new Vector(); //第一份定单   
  
   buylist.addElement(aCD);   
  
  } else { // 不是第一次购买   
  
   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;   
  
  } //if name matches结束   
  
   } // 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) {   
  
  //想象一下如果这些都在一个脚本片段中会有多么难看   
  
  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;   
  
   }   
  
  }