任务一应用 JSP+Servlet+JavaBean 实现购物车 添加
对于刚刚开始工作的小刘, 要先从简单一点的功能 上手 应用 JSP+Servlet+JavaBean 实现购物车 添加
购物车主要有添加商品 删除商品 修改数量 等主要功能, 本任务将通过 JSP+Servlet+JavaBean 模型实现购物车的添加功能, 购物车添加的具体步骤为 : 查看商品详细信息 加入购物车 显示将购物车中的商品列表, 添加购物车的页面效果如图所示
知识目标 : 了解 JSP+Servlet+JavaBean 开发模型 掌握在 Servlet 中使用内置对象的方法 掌握 JSP 页面与 Servlet 间参数传递的方法 掌握集合类 ArrayList 的使用
技能目标 : 能在 Servlet 中灵活正确使用内置对象 能够在 Servlet 中重写 dopost() 与 doget() 方法, 实现处理购物车添加的业务逻辑
所谓 JSP+Servlet+JavaBeans 开发模型, 使用 JSP 技术来表现页面, 使用 Servlet 技术完成大量的事务处理, 使用 Bean 来存储数据 Servlet 用来处理请求的事务, 充当一个控制者的角色, 创建 JSP 需要的 Bean 和对象, 然后根据用户请求的行为, 决定将哪个 JSP 页面发送给客户 JSP+Servlet+JavaBeans 开发模型示意图如图所示 器览浏 1 request (Controller) Servlet 2 3 5 response (View) JSP 4 (Model) JavaBean 应用服务器
本任务采用 JSP+Servlet+JavaBean 模型实现 添加购物车 功能,JSP Servlet JavaBean 这三部分的分析如下 : JSP 部分 : 涉及到两个 JSP 页面 : 查看商品详情页面 (product_detail.jsp, 在任务 5.4 中实现 ) 和 购物车商品列表页面 (list_cart.jsp) Servlet 部分 : 任务 6.1 中, 我们创建了一个购物车 Servlet CartServlet, 在本任务中, 结合购物车添加功能, 我们将继续完善 CartServlet JavaBean 部分 : 本任务将创建一个 JavaBean 购物车实体类 Cart 实现思路 :product_detail.jsp 页面中将表单提交给 CartServlet,CartServlet 接收 处理表单数据并将数据存放在 session 对象中, 并将页面跳转至 list_cart.jsp, 在 list_cart.jsp 页面中读取 session 数据, 形成列表并显示
创建购物车实体类 Cart 在 digitalweb 项目的 com.digitalweb.model 包中创建 Cart 实体类, 它的类结构如图所示
编辑前台 JSP 页面 product_detail.jsp 在任务 5.4 中完成 查看商品详情 功能基础上, 打开 product_detail.jsp 页面, 将表单 addcartform 的 action 属性为../CartServlet?type=add,../ 表示返回上一级目录, 若 CartServlet 与当前页面处于同级目录, 则可直接设置为 action=cartservlet 表单的 method 属性设置为 post, 这表明表单 addcartform 将采用 POST 方式提交给 CartServlet 进行处理 此外,book_detail.jsp 页面中必须含有相关的隐藏域与 Cart 对象的属性一一对应, 表单的 HTML 代码如下所示 1.<form action="../cartservlet?type=add" method="post" name="addcartform"> 2. <h1><%=p.getname()%></h1> 3. <input type="hidden" name="id" value="<%=p.getid()%>" /> 4. <input type="hidden" name="code" value="<%=p.getcode()%>" /> 5. <input type="hidden" name="name" value="<%=p.getname()%>" /> 6. <input type="hidden" name="price" value="<%=p.getprice()%>" /> 7. <input type="hidden" name="sale" value="<%=p.getsale()%>" /> 8. <input type="hidden" name="pic" value="<%=p.getpic()%>" />
1.<ul> 2. <li style="list-style: none;" class="bt"></li> 3. <li style="list-style: none;" class="text"> 商品编号 :<%=p.getcode()%></li> 4. <li style="list-style: none;" class="text"> 价格 : <%=p.getprice()%></li> 5. <li style="list-style: none;" class="text"> 促销信息 : 直降 <%=p.getsale()%></li> 6. <li style="list-style: none;" class="bt"> 库存 :<%=p.getnum()%></li> 7. <listyle="list-style: none; font-size: 13px; font-family: 黑体 ; color: red;"> 我要买 : 8. <input type="text" name="num" id="num" size="3"> 件 9. </li> 10. </ul> 11. <img hspace="50" src="../images/gwc.png" onclick="javascript:checkaddcartform();" > 12.</form>
由上述代码可见, 表单将通过点击图 6-2-1 中的 加入购物车 图片提交 在提交表单时, 使用 JavaScript 方法 checkaddcartform() 对商品购买数量进行验证 JavaScript 代码如下 : 1.function checkaddcartform() { 2. if (document.getelementbyid("num").value.length <= 0) 3. alert(" 请输入购买数量!"); 4. else 5. document.addcarform.submit(); 6.} 这里的 JavaScript 代码仅仅验证了用户是否输入购买数量, 读者可以进一步添加其他验证, 如数据格式以及数值的正确性等
编写 CartServlet 逻辑处理代码 任务 6.1 中创建的 CartServlet 的主要职责是接收页面请求并进行逻辑处理,CartServlet 将根据接收到的表单参数 type 的值而进行 添加 修改 或 删除 购物车的操作, 如图所示 当 type 值为开始 add 时,CartServlet 执行添加操作 接收参数 type type 为 add 判断 type 的值 type 为 update type 为 delete 接收购物车相关参数接收购物车相关参数接收购物车相关参数 添加购物车 修改购物车 删除购物车 页面跳转至 list_cart.jsp 结束
... 添加购物车操作的流程如图所示 : 商品 ID:id 商品名称 :name 商品价格 :price 商品数量 :num 商品图片路径 :image type 为 add 接收购物车相关参数 将接收到的参数信息封装为 Cart 对象 判断 clist 是否为空 初始化 clist 遍历 clist 判断是否已经有该商品 将 Cart 对象加入到 clist 中 将 clist 中对象的数量设置为原数量 + 刚接收的数量 将 clist 放回至 session 页面跳转至 list_cart.jsp
在 CartServlet 的 dopost() 方法中编写代码, 实现购物车添加 在 doget() 方法中, 调用 dopost() 方法, 如此一来, 不管页面以何种方式提交表单, 都可以进行相同的处理 dopost() 方法中的代码如下 : 1. public void dopost(httpservletrequest request, HttpServletResponse response) throws ServletException, IOException { 2. String nextpage = "product/list_cart.jsp"; 3. HttpSession session = request.getsession(); // 获取 session 对象 4. // 接收购物车参数 5. HashMap<String,String[]> map = (HashMap<String,String[]>) request.getparametermap(); 6. ArrayList<Cart> cartlist = (ArrayList<Cart>)session.getAttribute("cartList"); 7. if(map.get("type")[0].equals("add")){
8. // 封装 Cart 对象 9. Cart cart = new Cart(); 10. cart.setid(integer.parseint(map.get("id")[0])); 11. cart.setname(map.get("name")[0]); 12. cart.setsale(double.parsedouble(map.get("sale")[0])); 13. cart.setprice(double.parsedouble(map.get("price")[0])); 14. cart.setpic(map.get("pic")[0]); 15. cart.setnum(integer.parseint(map.get("num")[0])); 16. if(cartlist == null){ 17. cartlist = new ArrayList<Cart>(); 18. session.setattribute("cartlist",cartlist); 19. }
20. // 判断 cartlist 中是否有同样的商品 21. boolean hascart = false; 22. for(cart c : cartlist){ 23. if(c.getid() == cart.getid()){ 24. c.setnum(c.getnum()+cart.getnum()); 25. hascart = true; 26. break; 27. } 28. } 29. if(!hascart) 30. cartlist.add(cart); 31. } 32. response.sendredirect(nextpage); // 页面跳转 }
程序说明 第 3 行 : 通过 request 对象的 getsession() 方法创建 session 第 5 行 : 批量接收 product_detail.jsp 页面传递的所有参数, 放在一个 HashMap 对象 map 中, 详见本任务技术要点 第 6 行 : 从 session 中获取当前的购物车列表 第 7 行 : 判断参数 type 的值是否为 add 第 9~15 行 : 封装 Cart 对象 第 16~19 行 : 若购物车为空 ( 即第一次添加购物车 ), 则实例化购物车列表 cartlist 对象, 并保存在 session 中 第 21~31 行 : 判断 cartlist 中是否有同样的商品, 有则直接修改购物车中数量 第 32 行 : 跳转到购物车列表页面 cart_list.jsp
在购物车列表页面 cart_list.jsp 中显示购物车信息 在 cart_list.jsp 页面中, 使用表格来显示购物车列表, 如图所示
页面对应的 HTML 代码如下所示 : <div id="shoppingcart"> <p><img src="images/buycar_logo.gif" alt=" 购物车 " /></p> <table> <tr> <th width="6%" > 选项 </th> <th width="15%"> 商品图片 </th> <th width="20%"> 商品名称 </th> <th width="8%"> 商品单价 </th> <th width="28%"> 数量 </th> <th width="11%"> 单价优惠 </th> <th width="6%"> 小计 </th> <th width="6%"> 删除 </th> </tr> <tr> <td><input type="checkbox" name="chkbox" value="checkbox" /></td> <td> 此处显示商品图片 </td> <td> 此处显示商品名称 </td> <td> 此处显示商品价格 </td> <td> 此处显示商品数量 </td> <td> 此处显示商品促销价 </td> <td> 此处显示商品金额小计 </td> <td><a href=" "> 删除 </a></td> </tr> <tr> <td colspan="6"> 总价 :</td> </tr> </table> </div>
在页面中加入 java 代码, 从 session 对象中读取购物车列表中的数据, 并通过循环在页面相应位置显示 商品小计和商品总价通过计算得到, 具体代码如下 : 1. <div id="shoppingcart"> 2. <p><img src="images/buycar_logo.gif" alt=" 购物车 " /></p> 3. <table> 4. <tr> 5. <th width="6%" > 选项 </th> 6. <th width="15%"> 商品图片 </th> 7. 8. </tr> 9. <% 10. double sum = 0.0; // 商品总价 11. ArrayList<Cart> cartlist = (ArrayList<Cart>)session.getAttribute("cartList"); 12. if(cartlist!=null){ 13. for(cart c : cartlist) { 14.%>
15. <tr> 16. <td><input type="checkbox" name="chkbox" value="checkbox" /></td> 17. <td> <a href="product_detail.jsp?id=<%=c.getid() %>"> 18. <img src="<%=c.getpic() %>" width="75" height="50" /></a> 19. </td> 20. <td><a href="product_detail.jsp?id=<%=c.getid() %>"> 21. <%=(c.getname()).substring(0,12) %></a> 22. </td> 23. <td> <%=c.getprice() %></td> 24. <td><a>-</a> 25. <input type="text" size="2" name="num" id="num" value="<%=c.getnum() %>" /> 26. <a>+</a> 27. </td> 28. <td> <%=c.getsale() %></td> 29. <td> <%=c.getprice()*c.getnum() %></td> 30. <td><a href=" "> 删除 </a></td> 31. </tr>
32. <% 33. sum += c.getprice()*c.getnum(); 34. } 35. }%> 36.<tr> 37. <td colspan="6"> 总价 :<%=sum %></td> 38. <td> 39. <input type="button" name="totalprice" value=" 返回 " class="picbut" onclick="history.back(-1)" /> 40. </td> 41. <td> 42. <input type="button" name="totalprice" value=" 结算 " class="picbut" onclick=" javascript:window.location.href='checkout.jsp'" /> 43. </td> 44. </tr> 45. </table> 46.</div>
47.<% 48. sum += c.getprice()*c.getnum(); 49. } 50. }%> 51.<tr> 52. <td colspan="6"> 总价 :<%=sum %></td> 53. <td> 54. <input type="button" name="totalprice" value=" 返回 " class="picbut" onclick="history.back(-1)" /> 55. </td> 56. <td> 57. <input type="button" name="totalprice" value=" 结算 " class="picbut" onclick=" javascript:window.location.href='checkout.jsp'" /> 58. </td> 59. </tr> 60. </table> 61.</div> 至此, 购物车添加功能已完成, 启动 Tomcat, 在浏览器中打开 list_product.jsp 页面, 查看图书信息并进行添加至 购物车的操作, 页面效果如任务描述中的图所示
1. 在 Servlet 中内置对象的使用众所周知, 在 JSP 页面上可直接通过 session.setattribute(name,object) 来设置内置对象 session, 十分方便, 可如果要在 servlet 使用 session, 就和 JSP 页面也中有点区别了 在 Servlet 中不能直接使用 session,servlet 的 dopost() 和 doget() 方法中, 只提供 request 和 response 两个参数对象, 因此, 要想取得 session 对象, 要通过调用 request 对象的方法来实现 通过 HttpSession session=request.getsession(); 得到一个 session 对象 ( 准确来说, 得到的应该是一个 HttpSession 对象 ), 然后, 就可以像在 JSP 页面中直接使用它了 其实,JSP 中的 session 和 servlet 中的 HttpSession 其实根本没有区别,JSP 页面在编译时会通过 Jsp container 将 session 对象变换为 javax.servlet.http.httpsession 对象 同样的,JSP 中的其他内置对象, 常用的如 out 对象 application 对象, 也要通过相应的方法获取 通过 response 参数对象的 getwriter() 方法获取 out 对象, 例如 : 1.public void doget(httpservletrequest request,httpservletresponse response) 2.throws IOException,ServletException { 3. 4.PrintWriter out=response.getwriter(); 5.out.print("HelloWorld!"); 6.out.close(); }
在 Servlet 中, 取得 application 有两种方法 : 可以通过无参初始化方法, 直接取得 ; 也可以通过有参初始化方法, 必须使用 config 对象取得, 前者较为常用, 例如 : public void dopost(httpservletrequest request,httpservletresponse response) throws IOException,ServletException{ // 取得 Application 对象 ServletContext application=this.getservletcontext(); // 设置 Application 属性 application.setattribute("name", "Magci"); // 跳转到接收页面 response.sendredirect("application.jsp"); }
2. JSP 页面与 Servlet 之间的参数传递在 Java Web 开发中, 常常需要在 JSP 页面与 Servlet 之间的进行传值, 包括从 JSP 页面传值给 servlet 和从 servlet 传值给 JSP 页面 (1)JSP 页面向 Servlet 传值表单传值 URL 是 JSP 页面向 Servlet 传值最常用的方法 例如下面的 HTML 代码 : 1.<!-- JSP page --> 2. 3.<a href="jspservlet? action=toservlet ">click me</a> 4.<form action="jspservlet? action=toservlet " method="post" name="form"> 5.<input name="username" value="test" /> 6.<input name="password" value="abc" /> 7.<input type="submit" value="submit"> 8.</form> 9.
对于 JSP 页面 form 表单的内容, 如 <input> 标签, 在 Servlet 中可用 request.getparameter(" 参数名 ") 方式获取 String uname= request.getparameter("username"); // 获取表单中 username 参数值 test String pwd= request.getparameter("password"); // 获取表单中 password 参数值 abc 这里 <a> 标签中的 href 属性与 <form> 标签的 action 属性的值 JspServlet?action=toServlet, 这里,? 表示 URL 中带有参数,? 后面的表达式 action=toservlet 表示提交给 Servlet 时传递参数 action, 参数值为 toservlet, 在 Servlet 中也用 request.getparameter("action") 获取 若在 URL 中要设置多个参数, 可以用下面的形式 : URL 地址? 参数 1= 参数值 1& 参数 2= 参数值 2& 例如,<form action= "CartServlet?id=1&type=delete" method= "post" >, 表单提交时同时传递两个参数 id 和 type
在本任务中, 商品详细信息页面 (product_detail.jsp) 中分别通过表单传值和 URL 两种方式向 CartServlet 传递参数, 在参数数量比较多的情况下, 可以通过 HttpServletRequest 参数对象 request 的 getparametermap() 方法获得 JSP 页面元素的集合 例如 : HashMap<String,String[]> map = (HashMap<String,String[]>) request.getparametermap(); request.getparametermap() 方法的返回类型是 Map 类型的对象, 记录着所提交的请求中请求参数和参数值的映射关系 另外,request.getParameterMap() 返回值使用泛型时为 Map<String,String[]> 形式, 因为有时像 checkbox 这样的组件会出现一个 name 对应多个 value 的情况, 所以该 Map 中键值对是 String >String[] 的实现 正因为如此, 从 Map 中读取元素时, 使用 map.get(" 参数名 ")[0] 这样的形式 例如, 在前面例子中的 JSP 页面中的参数在 Servlet 中可以通过以下代码获取 : 1. 2. HashMap<String,String[]> map = (HashMap<String,String[]>) request.getparametermap(); 3. String uname=map.get( username )[0]; // 获取表单中 username 参数值 test 4. String pwd= request.getparameter("password"); // 获取表单中 password 参数值 abc 5.String action=request.getparameter( action ); // 获取 URL 中参数 action 的值 toservlet
(2)Servlet 向 JSP 页面传值从 JSP 页面传值给 Servlet 可以使用表单或 URL, 若要从 Servlet 传值给 JSP 页面, 也有两种方法 第一种方法, 在 Servlet 中将数据保存在 session 中, 使用 response 参数对象的 sendredirect() 方法跳转到 JSP 页面, 然后在 JSP 页面中获取 session 中的数据, 例如 : //1.Servlet 中存储数据于 session 并跳转页面 1. 2. String uname= tom ; 3. HttpSession session=request.getsession(); 4. session.setattribute( username,uname); 5. response.sendredirect( userinfo.jsp ); 6. //2.JSP 页面中获取 session 中的值 1. 2. <td><%=session.getattribute( username )%></td> 3.
本任务也采用了上述方法 第二种方法, 也是将数据保存在 session 中, 使用 response 参数对象的 getrequestdispatcher() 方法跳转页面, 最后在 JSP 页面中获取 session 中的数据, 例如 : //1.Servlet 中存储数据于 session 并跳转页面 1. 2. String uname= tom ; 3. HttpSession session=request.getsession(); 4. session.setattribute( username,uname); 5. RequestDispacher rd=request.getrequestdispacher( userinfo.jsp ); 6. rd.forward(request, response); 7. //2.JSP 页面中获取 session 中的值 1. 2. <td><%=session.getattribute( username )%></td> 3.
参照本任务购物车添加的实现方法, 应用 JSP+Servlet+JavaBean 实现购物车删除功能, 页面效果如图所示 删除前 删除后