将商品添加到购物车
我希望最后实现的界面是如下的界面: 其中购买数量中的两个按钮(变化值为1,点击’-‘,是减1,如果点击’+',那么是加1),可以修改中间文本框的购买数量,然后同时将小计进行修改。与此同时,如果我们直接来修改中间的文本框的数量,那么也会更新小计。所以关键是怎么处理这个呢?
- 首先,我们定义了一个Cart类,表示我们的购买商品,其中在这个类中,存在着购买的商品Book,以及购买的数量count。对应的代码为:
package entity;
public class Cart {
private Book book;
private int count;
public Cart() {
}
public Cart(Book book, int count){
this.book = book;
this.count = count;
}
public Book getBook() {
return book;
}
public void setBook(Book book) {
this.book = book;
}
public int getCount() {
return count;
}
public void setCount(int count) {
this.count = count;
}
@Override
public String toString() {
return "Cart{" +
"book=" + book +
", count=" + count +
'}';
}
public double getTotal(){
if(this.book == null){
throw new RuntimeException("没有购买图书");
}
return this.book.getPrice() * this.count;
}
}
- 其次,我们定义一个CartList类,表示我们的购物车,其中在这个类中,定义了一个哈希表,表示我们的Cart,但是由于HashMap是无序的,即添加的顺序和在哈希表中的顺序是不一致的,因此为了维持两者的一致,那么我们需要使用的是LinkedHashMap.然后再这个类中,我们需要定义添加购物商品的数量,减少购物商品数量等方法。
package dao;
import entity.Cart;
import java.util.Collection;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
public class CartList {
private HashMap<Integer,Cart> cartItems = new LinkedHashMap<>();
public HashMap<Integer,Cart> getCartItems(){
return cartItems;
}
public void addItem(int id,int count){
Cart old_cart = cartItems.get(id);
old_cart.setCount(old_cart.getCount() + count);
}
public void addItem(int id,Cart cart){
cartItems.put(id,cart);
}
public void subItem(int id,int num){
if(cartItems.containsKey(id)){
Cart old_cart = cartItems.get(id);
int count = old_cart.getCount();
if(count > num){
count -= num;
old_cart.setCount(count);
cartItems.put(id,old_cart);
}else{
throw new RuntimeException("购买的商品数量小于等于减少数量,无法减少商品");
}
}else{
throw new RuntimeException("没有购买这个商品,无法减少该商品购买数量");
}
}
public void clearItems(){
cartItems.clear();
}
public double getTotla(){
double total = 0;
for(Cart cartItem : cartItems.values()){
total += cartItem.getTotal();
}
return total;
}
public int getSize(){
return cartItems.size();
}
public void setItem(int id,int count){
if(cartItems.containsKey(id)){
Cart old_cart = cartItems.get(id);
old_cart.setCount(count);
}else{
throw new RuntimeException("购物车中不存在这个商品,无法修改商品数量");
}
}
}
- 我们定义一个CartServlet,用于和前台的交互,对应的代码
package web.servlets;
import dao.CartList;
import entity.Book;
import entity.Cart;
import service.BookService;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.sql.SQLException;
import java.util.HashMap;
public class CartServlet extends BaseServlet {
private BookService service = new BookService();
public String addItem(HttpServletRequest request, HttpServletResponse response){
CartList cartList = (CartList)(request.getSession().getAttribute("cartList"));
String value = request.getParameter("id");
if(value == null){
throw new RuntimeException("添加商品到购物车时没有传递参数id");
}
int id = Integer.parseInt(value);
value = request.getParameter("count");
int count = 1;
if(value != null){
count = Integer.parseInt(request.getParameter("count"));
}
HashMap<Integer, Cart> cartItems = cartList.getCartItems();
if(cartItems.containsKey(id)){
cartList.addItem(id,count);
}else{
try {
Book book = service.queryById(id);
cartList.addItem(id,new Cart(book,count));
} catch (IOException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}
}
return "d:/jsps/cart.jsp";
}
public String subItem(HttpServletRequest request, HttpServletResponse response){
CartList cartList = (CartList)(request.getSession().getAttribute("cartList"));
String value = request.getParameter("id");
if(value == null){
throw new RuntimeException("减少商品时没有传递参数id");
}
int id = Integer.parseInt(value);
value = request.getParameter("count");
int count = 1;
if(value != null){
count = Integer.parseInt(request.getParameter("count"));
}
cartList.subItem(id,count);
return "d:/jsps/cart.jsp";
}
public String changeItem(HttpServletRequest request,HttpServletResponse response){
CartList cartList = (CartList)(request.getSession().getAttribute("cartList"));
String value = request.getParameter("id");
if(value == null){
throw new RuntimeException("减少商品时没有传递参数id");
}
int id = Integer.parseInt(value);
value = request.getParameter("count");
int count = 1;
if(value != null){
count = Integer.parseInt(request.getParameter("count"));
}
System.out.println("changeItem ------------" + id + ", " + count);
cartList.setItem(id,count);
return "d:/jsps/cart.jsp";
}
}
html代码
<div id="right">
<c:if test="${not empty sessionScope.cartList and sessionScope.cartList.size > 0}">
<table>
<thead>
<td>商品照片</td>
<td>商品名称</td>
<td>商品分类</td>
<td>商品单价</td>
<td>购买数量</td>
<td>小计</td>
</thead>
<c:forEach items="${sessionScope.cartList.cartItems.values()}" var="cart" varStatus="vs">
<tr>
<td><img src="<c:url value='/images/${cart.book.name}.png'></c:url>"></td>
<td>${cart.book.name}</td>
<td>${cart.book.catagory_name}</td>
<td>¥ ${cart.book.price} 元</td>
<td>
<input type="button" id="sub_${vs.index}" onclick="subItem(${cart.book.id},${cart.book.price},${vs.index})" value="-">
<input type="text" id="count_${vs.index}" onchange="changeText(${cart.book.id},${cart.book.price},${vs.index})" value="${cart.count}" style="width: 50px;">
<input type="button" id="add_${vs.index}" onclick="addItem(${cart.book.id},${cart.book.price},${vs.index})" value="+">
</td>
<td>¥ <span id="subtotal_${vs.index}">${cart.total}</span> 元</td>
</tr>
</c:forEach>
</table>
</c:if>
</div>
js代码:
<script type="text/javascript" src="<c:url value="/ajax.js"></c:url>"></script>
<script type="text/javascript">
window.onload = function(){
request({
method: "POST",
resource: "/CatagoryServlet",
params: "method=queryCatagories",
returnType: "json",
callback: function (data) {
var left = document.getElementById("left");
left.innerHTML = "";
var li = document.createElement("li");
var a = document.createElement("a");
var text = document.createTextNode("全部分类");
a.appendChild(text);
a.href = "/BookServlet?method=queryAll";
li.appendChild(a);
left.appendChild(li);
for(var i = 0; i < data.length; ++i){
var li = document.createElement("li");
var a = document.createElement("a");
var text = document.createTextNode(data[i].name);
a.appendChild(text);
a.href = "/BookServlet?method=queryByCatagoryId&id="+data[i].id;
li.appendChild(a);
left.appendChild(li);
}
}
})
}
function getSubTotal(index,money) {
var span = document.getElementById("subtotal_" + index);
span.innerHTML = money;
}
function addItem(id,price,index) {
var count_text = document.getElementById("count_" + index);
var num = parseInt(count_text.value) + 1;
count_text.value = num;
request({
method: "POST",
resource: "/CartServlet",
params: "method=addItem&id=" + id + "&count=1"
})
getSubTotal(index,price * num);
}
function subItem(id,price,index){
var count_text = document.getElementById("count_" + index);
var num = parseInt(count_text.value);
if(num > 1){
num = num - 1;
count_text.value = num;
request({
method: "POST",
resource: "/CartServlet",
params: "method=subItem&id=" + id + "&count=1"
})
getSubTotal(index,price * num);
}
}
function changeText(id,price,index){
var count_text = document.getElementById("count_" + index);
var num = parseInt(count_text.value);
request({
method: "POST",
resource: "/CartServlet",
params: "method=changeItem&id=" + id + "&count=" + num
})
getSubTotal(index,price * num);
}
</script>
前端代码中关键的地方:
- 首先,因为我们需要每一个表格中都存在‘-’,‘+’这两个按钮,所以我们不可以将button的id为add之类的,所以为了保证维持每一个button的id是唯一的,我们需要利用<c:forEach>标签中的varStatus,这样就可以利用这个属性中的index,来获取遍历元素当前的下标,这样只要在id的后面添加这个index后缀,就可以保证每一个button的id是唯一的。
- 在上面之后,我们的js代码中,如何保证点击的是哪一个button呢?这时候我们就需要给点击事件中传递vs.index,这样就可以保证了我们点击的是哪一个按钮,这样就可以触发对应按钮的点击事件。
- 点击完毕之后,就需要利用ajax来局部更新html,然后再调用getSubTotalb方法,来更新对应的小计
- 但是需要注意的是,我们需要保证我们定义的方法addItem,subItem,changeItem方法不是定义再window.onload的方法里面,否则就会发生报错,提示诸如:
ReferenceError: addItem is not defined at HTMLInputElement.onclick 的错误。 - 点击中间文本框的时候,我们需要触发事件,那么我们就需要给这个文本框添加change事件,从而实现实时监听,当我们修改完毕之后,点击除了文本框的任意位置,就会触发事件了,我们可以通过alert来进行验证这个触发事件。
- CartServlet中利用cartList来实现对商品的操作的时候,注意的是,cartList是通过session来取得的,而不是我们直接再CartServlet中直接新建得到的。如果是我们再CartServlet中新建CartList的话,那么就会导致我们并不是在当前的session的购物车中进行操作的,那么重定向之后,再来点击购物车的时候,就会发现购物车的商品一直是0,所以不会显示数据。因此我们需要保证每次操作都是在session中的cartList操作的,那么就需要每次都需要从session中获取cartList。
|