上一篇以一個最常用的使用者登入註冊程式來講解Servlet+JSP+JavaBean開發模式,所以我們也初步了解了Servlet+JSP+JavaBean(MVC)模式。現在我們以一個網上購物時的購物車程式來重新回顧這個開發模式。
序號 |
套件名稱 | ##描述 | 所屬層次 |
1 | #cn.itcast.DB | 。存放代表資料庫的類別 |
|
2 | cn.itcast.domain | 存放系統的JavaBean類別(只包含簡單的屬性以及屬性對應的get和set方法,不包含特定的業務處理方法),提供給【資料存取層】、【業務邏輯層】、【Web層】來使用 | domain(域模型)層 |
3 | cn.itcast.dao | 存放存取資料庫的操作介面的實作類別 | 資料存取層 |
4 | cn.itcast.service | #存放處理系統業務介面的實作類別 | 業務邏輯層 |
5 | cn.itcast.web.controller | 存放作為系統控制器的Servlet(處理請求的servlet) | Web層(表現層) |
6 | cn.itcast.web.UI | 提供使用者介面給使用者。由於在嚴格的MVC模式下,jsp被保護起來,禁止外界直接訪問,如用戶要註冊,需要拿一個表單頁面,需要用一個servlet轉到jsp上面去,有一部分servlet專門給用戶提供用戶界面,也即是說在實際開發裡面有一部分servlet是用來處理請求,有一部分servlet專門用來接收請求之後轉到jsp,給用戶提供用戶界面 | Web層(表現層) |
7 | cn.itcast.utils | 存放系統的通用工具類,提供給【資料存取層】、【業務邏輯層】、【Web層】來使用 |
|
#以上就是根據此項目的實際情況創建的包,可能還需要創建其他的包,這個得根據項目的需要來定了。
建立代表資料庫的類別:
假設這是網路書城的項目,使用者購買的商品即為書,所以在資料庫中儲存的商品就是書。在cn.itcast.DB套件下建立一個DB類別。
DB類別具體程式碼如下:
public class DB { private static Map<String, Book> map = new LinkedHashMap<String, Book>();
static { map.put("1", new Book("1", "javaweb开发", "老张", 38, "一本好书")); map.put("2", new Book("2", "jdbc开发", "老黎", 18, "一本好书")); map.put("3", new Book("3", "ajax开发", "老佟", 328, "一本好书")); map.put("4", new Book("4", "jbpm开发", "老毕", 58, "一本好书")); map.put("5", new Book("5", "struts开发", "老方", 28, "一本好书")); map.put("6", new Book("6", "spring开发", "老方", 98, "一本好书"));
} public static Map<String, Book> getAll() { return map;
}
}1234567891011121314151617
登入後複製
註解:關於如何建立代表資料庫的類別-DB.java,可參考我的使用Cookie進行會話管理。
在WEB-INF目錄下建立一個jsp目錄,jsp目錄存放系統的一些受保護(不允許使用者直接透過URL位址存取)的jsp頁面,使用者要想存取這些受保護的jsp頁面,那麼只能透過cn.itcast.web.UI這個包裡面的Servlet。
建立好的專案架構如下圖所示:
分層架構的程式碼編寫
分層架構的程式碼也是依照【領域模型層(domain )】→【資料存取層(dao、dao.impl)】→【業務邏輯層(service、service.impl)】→【表現層(web.controller、web.UI、web.filter、web.listener)】 →【工具類別(util)】→【測試類別(junit.test)】的順序進行編寫的。
開發domain層
在cn.itcast.domain套件下建立一個Book類別。
Book類別具體程式碼如下:
public class Book { private String id; private String name; private String author; private double price; private String description; public Book() { super(); // TODO Auto-generated constructor stub
} public Book(String id, String name, String author, double price, String description) { super(); this.id = id; this.name = name; this.author = author; this.price = price; this.description = description;
} public String getId() { return id;
} public void setId(String id) { this.id = id;
} public String getName() { return name;
} public void setName(String name) { this.name = name;
} public String getAuthor() { return author;
} public void setAuthor(String author) { this.author = author;
} public double getPrice() { return price;
} public void setPrice(double price) { this.price = price;
} public String getDescription() { return description;
} public void setDescription(String description) { this.description = description;
}
}1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253
登入後複製
開發資料存取層(dao、dao.impl)
在cn.itcast.dao套件下建立一個UserDao類別。
UserDao類別具體程式碼如下:
public class BookDao { public Map<String, Book> getAll() { return DB.getAll();
} public Book find(String id) { return DB.getAll().get(id);
}
}1234567891011
登入後複製
開發service層(service層對web層提供所有的業務服務)
我們在第一次開發一個新專案的過程當中,並不清楚要開發的所有項目的功能,所以我們可以先開發出最容易想到的功能,然後將自己偽裝成一個用戶,在瀏覽網站頁面的過程中,看用戶需要什麼功能,那我們程式設計師就開發什麼功能,然後步步為營,將整個專案的功能完成。
例如,我第一次開發這個購物車功能模組的過程當中,首先想到的是要給用戶展示所有書籍,以及根據書的ID查詢書的資訊。其他的功能我沒想到,所以可以等這些功能完成之後,根據前端頁面來看需要什麼功能。
在cn.itcast.service套件下建立一個BusinessService類別。
先寫一個實作下列兩個業務服務的BusinessService類別。
具體程式碼如下:
// 业务类,统一对web层提供所有服务public class BusinessService { private BookDao dao = new BookDao(); public Map<String, Book> getAllBook() { return dao.getAll();
} public Book findBook(String id) { return dao.find(id);
}
}12345678910111213
登入後複製
開發Web層
開發給用戶展示所有書籍的功能
在cn.itcast.web.controller包下編寫用於處理給用戶展示所有書籍的ListBookServlet。
ListBookServlet類別的具體程式碼如下:
// 获取所有书public class ListBookServlet extends HttpServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
BusinessService service = new BusinessService();
Map<String, Book> map = service.getAllBook();
request.setAttribute("map", map);
request.getRequestDispatcher("/WEB-INF/jsp/listbook.jsp").forward(request, response);
} protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}12345678910111213141516171819
登入後複製
在/WEB-INF/jsp/目錄下撰寫給使用者展示所有書籍的jsp頁面listbook.jsp。
凡是位於WEB-INF目錄下的jsp頁面是無法直接透過URL位址直接存取的。在開發中如果專案中有一些敏感web資源不想被外界直接訪問,那麼可以考慮將這些敏感的web資源放到WEB-INF目錄下,這樣就可以禁止外界直接透過URL來訪問了。
listbook.jsp頁面的程式碼如下:
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%><%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %><!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"><html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><title>书籍列表页面</title></head><body style="text-align: center;"> <h1>书籍列表</h1> <table width="70%" border="1" align="center"> <tr> <td>书名</td> <td>作者</td> <td>售价</td> <td>描述</td> <td>操作</td> </tr> <c:forEach var="entry" items="${map }"> <tr> <td>${entry.value.name }</td> <td>${entry.value.author }</td> <td>${entry.value.price }</td> <td>${entry.value.description }</td> <td> <a href="${pageContext.request.contextPath }/BuyServlet?id=${entry.key }" target="_blank">购买</a> </td> </tr> </c:forEach> </table></body></html>12345678910111213141516171819202122232425262728293031323334
登入後複製
網站一般都有一個首頁,在該專案中我們的首頁index.jsp中,使用者點擊瀏覽書籍
超連結即可瀏覽網站所有書籍。
index.jsp頁面的程式碼如下:
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%><!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"><html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><title>网站首页</title></head><body> <a href="${pageContext.request.contextPath }/ListBookServlet">浏览书籍</a></body></html>123456789101112
登入後複製
至此,給使用者展示所有書籍的功能就算是開發完成了!下面測試一下開發好的該功能:
开发购买书籍的功能
在现实中购买商品时,用户都是将商品放到购物车中,所以我们应该按照现实中的情况设计一个代表用户购物车的类——Cart.java。
现在再来思考一个问题:在设计代表用户购物车的Cart类时,应该使用private Book book
字段(或属性)来代表用户所购买的商品吗?
答案显然不是。若是使用这样的字段,结果就是不可避免地在购物车中出现重复商品,即用户如果购买一本书多次,那么购物车中就出现一本书多次,显然在现实中这是不合理的。那么到底该怎么做呢?——为了避免在购物车里面出现重复商品,我们这时会设计一个专门的对象——CartItem(购物项,代表某个商品以及这个商品出现的次数)。
在cn.itcast.domain包下创建一个CartItem类,用于代表某个商品,以及商品出现的次数(购物项)。
CartItem类的具体代码如下:
// 用于代表某个商品,以及商品出现的次数(购物项)public class CartItem { private Book book; private int quantity; private double price; public Book getBook() { return book;
} public void setBook(Book book) { this.book = book;
} public int getQuantity() { return quantity;
} public void setQuantity(int quantity) { this.quantity = quantity; this.price = this.book.getPrice() * this.quantity;
} public double getPrice() { return price;
} public void setPrice(double price) { this.price = price;
}
}12345678910111213141516171819202122232425262728
登入後複製
在cn.itcast.domain包中创建一个代表用户购物车的Cart类。
Cart类的具体代码如下:
// 代表用户的购物车public class Cart { /*
* 为了避免在购物车里面出现重复商品,
* 我们这时会设计一个专门的对象——CartItem(购物项,代表某个商品以及这个商品出现的次数)
*/ private Map<String, CartItem> map = new LinkedHashMap<>(); private double price; // 记住购物车中的所有商品多少钱 public void add(Book book) { // 看购物车中有没有,要添加的书对应的购物项
CartItem item = map.get(book.getId()); if(item==null) {
item = new CartItem();
item.setBook(book);
item.setQuantity(1);
map.put(book.getId(), item);
} else {
item.setQuantity(item.getQuantity()+1);
}
} public Map<String, CartItem> getMap() { return map;
} public void setMap(Map<String, CartItem> map) { this.map = map;
} public double getPrice() { double totalprice = 0; for(Map.Entry<String, CartItem> entry : map.entrySet()) {
CartItem item = entry.getValue();
totalprice += item.getPrice();
} this.price = totalprice; return price;
} public void setPrice(double price) { this.price = price;
}
}12345678910111213141516171819202122232425262728293031323334353637383940414243
登入後複製
用户浏览网站首页时,会看到网站所有书籍,用户即可对自己感兴趣的书籍进行购买,点击购物超链接时,跳转到一个servlet对用户的请求进行处理。所以在cn.itcast.web.controller包中创建一个代表完成书籍购买的BuyServlet类。
BuyServlet类的具体代码如下:
// 完成书籍购买@WebServlet("/BuyServlet")public class BuyServlet extends HttpServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String id = request.getParameter("id");
BusinessService service = new BusinessService();
Book book = service.findBook(id); // 得到用户的购物车
Cart cart = (Cart) request.getSession().getAttribute("cart"); // 用户第一次购买,为用户创建购物车 if(cart==null) {
cart = new Cart();
request.getSession().setAttribute("cart", cart);
} // 把书加到用户的购物车中,完成购买
cart.add(book); /*
* 浏览器重新访问地址:/WEB-INF/jsp/listcart.jsp
* 但这个地址被保护起来,外面是无法直接访问的,
* 要实现的话,会比较麻烦,需要先跳到servlet,然后再转到jsp。
*/ // response.sendRedirect("/WEB-INF/jsp/listcart.jsp");
request.getRequestDispatcher("/WEB-INF/jsp/listcart.jsp").forward(request, response);
} protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}1234567891011121314151617181920212223242526272829303132333435363738
登入後複製
注意:显示购物车时,记住千万不要用请求转发,而应该使用重定向技术。若不是产生的后果可参考我的笔记Session——使用Session完成简单的购物功能。我上面的代码使用的是请求转发,这是不行的,读者要注意了啊!既然要使用重定向技术,下面这行代码可行吗?
response.sendRedirect("/WEB-INF/jsp/listcart.jsp");1
登入後複製
答案不言而喻,这是不行的。因为这是浏览器重新访问地址/WEB-INF/jsp/listcart.jsp
,listcart.jsp页面是被保护起来了,外界是无法直接访问的。如果一定要实现的话,会比较麻烦,还需要先跳到一个servlet,然后再跳转到listcart.jsp。所以正规的做法是:BuyServlet类中使用重定向技术,即添加如下代码:
response.sendRedirect(request.getContextPath()+"/ListCartUIServlet");1
登入後複製
然后在cn.itcast.web.UI包下创建一个ListCartUIServlet类,专门用来接收请求之后转到jsp,给用户提供用户界面。
ListCartUIServlet类的具体代码如下:
public class ListCartUIServlet extends HttpServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.getRequestDispatcher("/WEB-INF/jsp/listcart.jsp").forward(request, response);
} protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}12345678910111213
登入後複製
这毕竟不是一个真实项目,所以不想把其搞得这么复杂哈!所以就干脆用了请求转发,但是读者一定要知道这还是不行的,要知道用重定向技术,怎么使用我也已经写的很明白了!
购物车显示页面listcart.jsp代码如下:
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%><%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %><!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"><html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><title>购物车列表</title><script type="text/javascript"> function deleteitem(id) { var b = window.confirm("您确认删除吗?"); if(b) { // window代表当前浏览器窗口,location代表当前浏览器窗口的地址栏
window.location.href = "${pageContext.request.contextPath }/DeleteItemServlet?id="+id;
}
} function clearCart() { var b = window.confirm("您确认清空吗?"); if(b) {
window.location.href = "${pageContext.request.contextPath }/ClearCartServlet"
}
} function changeQuantity(input, id, oldValue) { var quantity = input.value; // 得到要修改的数量 /*
// 检查用户输入的数量是不是一个数字
if(isNaN(quantity)) {
alert("请输入数字!!!");
// 得到输入项原来的值
input.value = oldValue;
return;
}
*/ // 检查用户输入的数量是不是一个正整数 if(quantity<0 || quantity!=parseInt(quantity)) { // 1.1 != 1 parseInt("abc")返回NaN
alert("请输入一个正整数!!!");
input.value = oldValue; return;
} var b = window.confirm("您确定把书的数量修改为"+quantity+"吗?") if(b) {
window.location.href = "${pageContext.request.contextPath }/ChangeQuantityServlet?id="+id+"&quantity="+quantity;
}
}</script></head><body style="text-align: center;"> <h1>购物车列表</h1> <c:if test="${empty(cart.map) }"> <!-- cart.map.empty:map为空,没东西 el表达式的函数:empty()——检测map是否为null或"",若是则返回true -->
您没有购买任何商品!!! </c:if> <c:if test="${!empty(cart.map) }"> <table width="70%" border="1" align="center"> <tr> <td>书名</td> <td>作者</td> <td>单价</td> <td>数量</td> <td>小计</td> <td>操作</td> </tr> <c:forEach var="entry" items="${cart.map }"> <!-- entry<id, CartItem> --> <tr> <td>${entry.value.book.name }</td> <td>${entry.value.book.author }</td> <td>${entry.value.book.price }</td> <td> <!-- this代表input输入项 -->
<input type="text" name="quantity" value="${entry.value.quantity }" style="width: 35px" onchange="changeQuantity(this, ${entry.key }, ${entry.value.quantity })" /> </td> <td>${entry.value.price }</td> <td> <!-- javascript:void(0):去掉超链接的默认行为 --> <a href="javascript:void(0)" onclick="deleteitem(${entry.key })">删除</a> </td> </tr> </c:forEach> <tr> <td colspan="3">总价</td> <td colspan="2">${cart.price }元</td> <td colspan="1"> <a href="javascript:void(0)" onclick="clearCart()">清空购物车</a> </td> </tr> </table> </c:if></body></html>123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
登入後複製
至此,用户购买书籍的功能就算是开发完成了!下面测试一下开发好的该功能:
开发删除购物车中购物项的功能
编写实现如下业务服务的BusinessService类。
此时BusinessService类的具体代码如下:
// 业务类,统一对web层提供所有服务public class BusinessService { private BookDao dao = new BookDao(); public Map<String, Book> getAllBook() { return dao.getAll();
} public Book findBook(String id) { return dao.find(id);
} // 删除购物车中购物项 public void deleteCartItem(String id, Cart cart) {
cart.getMap().remove(id);
}
}12345678910111213141516171819
登入後複製
在cn.itcast.web.controller下创建一个DeleteItemServlet类。
DeleteItemServlet类的具体代码如下:
public class DeleteItemServlet extends HttpServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String id = request.getParameter("id");
Cart cart = (Cart) request.getSession().getAttribute("cart");
BusinessService service = new BusinessService();
service.deleteCartItem(id, cart); // 删除成功,还是跳转到listcart.jsp页面
request.getRequestDispatcher("/WEB-INF/jsp/listcart.jsp").forward(request, response);
} protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}123456789101112131415161718192021
登入後複製
注意:我上面的代码使用的是请求转发,这依然是不行的,读者要注意了啊!仍然要使用请求重定向,考虑到这毕竟不是一个真实项目,所以尽量不要搞得那么复杂,一切从简。
在购物车显示页面listcart.jsp中还要写入以下JavaScript代码:
<script type="text/javascript"> function deleteitem(id) { var b = window.confirm("您确认删除吗?"); if(b) { // window代表当前浏览器窗口,location代表当前浏览器窗口的地址栏
window.location.href = "${pageContext.request.contextPath }/DeleteItemServlet?id="+id;
}
}</script>123456789
登入後複製
不然的话,用户手贱,不小心删除了所选的购物项,辛辛苦苦购买的商品又要重新购买,用户的感受肯定巨不爽,所以在用户不小心删除了所选的购物项时,还要问用户是否确认删除。只有用户点击确认按钮才会删除,这样对用户来说,体验会更好。
至此,删除购物车中购物项的功能就算是开发完成了!下面测试一下开发好的该功能:
开发清空购物车的功能
编写实现如下业务服务的BusinessService类。
编写对应的清空购物车的方法时,由于代表用户购物车的Cart类存在session中,是不是可以像下面这样写呢?
public void clearCart(HttpSession session) { ... }123
登入後複製
答:不可以。业务逻辑层用到Web层对象——session,业务逻辑层和Web层牢牢绑定在一起了,业务逻辑层离开Web层就跑不起来了,如果这样写,若要对业务层进行测试,需要把Web服务器起起来,传一个session进去,所以在各层之间传递的只能是JavaBean,不能让Web层的特殊对象侵入到业务逻辑层,污染业务逻辑层。
此时BusinessService类的具体代码如下:
// 业务类,统一对web层提供所有服务public class BusinessService { private BookDao dao = new BookDao(); public Map<String, Book> getAllBook() { return dao.getAll();
} public Book findBook(String id) { return dao.find(id);
} // 删除购物车中购物项 public void deleteCartItem(String id, Cart cart) {
cart.getMap().remove(id);
} // 清空购物车 public void clearCart(Cart cart) {
cart.getMap().clear();
}
}123456789101112131415161718192021222324
登入後複製
在cn.itcast.web.controller包下创建一个ClearCartServlet类。
ClearCartServlet类的具体代码如下:
public class ClearCartServlet extends HttpServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
Cart cart = (Cart) request.getSession().getAttribute("cart");
BusinessService service = new BusinessService();
service.clearCart(cart);
request.getRequestDispatcher("/WEB-INF/jsp/listcart.jsp").forward(request, response);
} protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}12345678910111213141516171819
登入後複製
注意:我上面的代码使用的是请求转发,这依然是不行的,读者要注意了啊!仍然要使用请求重定向,考虑到这毕竟不是一个真实项目,所以尽量不要搞得那么复杂,一切从简。
在购物车显示页面listcart.jsp中还要写入以下JavaScript代码:
<script type="text/javascript"> function clearCart() { var b = window.confirm("您确认清空吗?"); if(b) {
window.location.href = "${pageContext.request.contextPath }/ClearCartServlet";
}
}</script>12345678
登入後複製
不然的话,用户手贱,不小心清空了购物车,辛辛苦苦购买的商品又要重新购买,用户的感受肯定巨不爽,所以在用户不小心清空了购物车时,还要问用户是否确认清空。只有用户点击确认按钮才会清空,这样对用户来说,体验会更好。
还有一点要注意:如果用户清空了购物车,那么购物车显示页面不能没有任何显示,这也是对用户体验的一种折磨,明智的做法应该是给用户显示您没有购买任何商品!!!,这样用户体验会更好。那怎样判断用户有没有购买商品呢?——可使用el表达式的函数:empty(object),检测object对象是否为null或”“,若是则返回true。这样购物车显示页面listcart.jsp页面中的关键代码如下:
<h1>购物车列表</h1><c:if test="${empty(cart.map) }"> <!-- cart.map.empty:map为空,没东西 el表达式的函数:empty()——检测map是否为null或"",若是则返回true -->
您没有购买任何商品!!!</c:if><c:if test="${!empty(cart.map) }">
...</c:if>12345678
登入後複製
至此,清空购物车的功能就算是开发完成了!下面测试一下开发好的该功能:
开发改变购物车某购物项数量的功能
在现实中的购物中,当用户购买一件商品时,发现还需要购买这件商品,比如数量为100,用户不可能点击这件商品100次,若是这样,那这样的购物网站倒闭1万亿遍了。所以一般来说用户只需要改变其数量即可,这时就需要用到<input>
控件,而且用户要输入的数量要是一个正整数,不能是其他乱七八糟的东西。
编写实现如下业务服务的BusinessService类。
此时BusinessService类的具体代码如下:
// 业务类,统一对web层提供所有服务public class BusinessService { private BookDao dao = new BookDao(); public Map<String, Book> getAllBook() { return dao.getAll();
} public Book findBook(String id) { return dao.find(id);
} // 删除购物车中购物项 public void deleteCartItem(String id, Cart cart) {
cart.getMap().remove(id);
} // 清空购物车 public void clearCart(Cart cart) {
cart.getMap().clear();
} // 改变购物车某购物项的数量 public void changeItemQuantity(String id, String quantity, Cart cart) {
CartItem item = cart.getMap().get(id);
item.setQuantity(Integer.parseInt(quantity));
}
}123456789101112131415161718192021222324252627282930
登入後複製
在cn.itcast.web.controller中创建ChangeQuantityServlet类。
ChangeQuantityServlet类的具体代码如下:
// 把购物车中的书修改为指定数量public class ChangeQuantityServlet extends HttpServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String id = request.getParameter("id");
String quantity = request.getParameter("quantity");
Cart cart = (Cart) request.getSession().getAttribute("cart");
BusinessService service = new BusinessService();
service.changeItemQuantity(id, quantity, cart);
request.getRequestDispatcher("/WEB-INF/jsp/listcart.jsp").forward(request, response);
} protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}1234567891011121314151617181920212223
登入後複製
注意:我上面的代码使用的是请求转发,这依然是不行的,读者要注意了啊!仍然要使用请求重定向,考虑到这毕竟不是一个真实项目,所以尽量不要搞得那么复杂,一切从简。
在购物车显示页面listcart.jsp中还要写入以下JavaScript代码:
<script type="text/javascript"> function changeQuantity(input, id, oldValue) { var quantity = input.value; // 得到要修改的数量 // 检查用户输入的数量是不是一个正整数 if(quantity<0 || quantity!=parseInt(quantity)) { // 1.1 != 1 parseInt("abc")返回NaN
alert("请输入一个正整数!!!");
input.value = oldValue; return;
} var b = window.confirm("您确定把书的数量修改为"+quantity+"吗?") if(b) {
window.location.href = "${pageContext.request.contextPath }/ChangeQuantityServlet?id="+id+"&quantity="+quantity;
}
}</script>1234567891011121314151617
登入後複製
完整的购物车显示页面listcart.jsp代码前面已经给出了,这里不再赘写。
至此,改变购物车某购物项数量的功能就算是开发完成了!下面测试一下开发好的该功能: