购物车实现逻辑详解
想要实现这样的效果:
1、首先要定义其模型
2、分析页面操作
3、实现其功能函数(在fun包下新建)
Cart.java /** * 购物车 * @author Administrator * */ Public class Cart { private int totalCount ; //购书数量 private float totalPrice ; //购书总价 private Map<Integer, CartItem> map= new HashMap<>();//定义一个集合来存放购物项//得到书的数量,怎么得?→bookId public int getTotalCount() { int totalCount=0; for(Integer bookId:map .keySet()){ totalCount+= map.get(bookId).getCount(); } return totalCount; } /*API:public Set<K> keySet()返回此映射中所包含的键的 set 视图。 for(Integer bookId:map.keySet()) ,这里面定义了一个和map集合键同类型的变量bookId map.keySet()表示当前map集合中的所有的键的一个视图 分解:map.get( bookid).getCount(); map.get( bookid);→ 根据键获取值(CartItem)→(CartItem)对象调用getCount(); */
//得到书的总价?怎么得→bookId public float getTotalPrice() { float totalPrice=0; for(Integer bookId:map .keySet()){ totalPrice+= map.get(bookId).getItemPrice(); } return totalPrice; }
public Map<Integer, CartItem> getMap() { return map ; } public void setMap(Map<Integer, CartItem> map) { this.map = map; }
@Override public String toString() { return "Cart [totalCount=" + totalCount + ", totalPrice=" + totalPrice + ", map=" + map + "]" ; } }
CartItem.java文件
/** * 购物项类 * @author Administrator * */ public class CartItem {
private Book book; //图书 private int count ; //当前购物项的图书数量 public CartItem() { super(); }
public CartItem(Book book, int count) { super(); 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; }
// 得到小计 public float getItemPrice() { return book .getPrice() * count; } @Override public String toString() { return "CartItem [book=" + book + ", count=" + count + "]" ; } }
4、编写逻辑处理类CartServlet
大体思路: ①接收请求参数 ②处理请求(谁来处理请求) ③转发请求 先定义好CartServlet然后依次写出待实现的空方法public class CartServlet extends BaseServlet { private static final long serialVersionUID = 1L; CartService cartService=new CartServiceImpl(); BookService bookService=new BookServiceImpl(); protected void add(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { System. out.println("add...." ); String bookid = request.getParameter( "bookid"); Book book = bookService.getBookById(bookid); Cart cart = WebUtils. getCart(request); cartService.add(book, cart);
WebUtils. myForward(request, response, "/client/BookClientServlet?method=getPageInCondition" );
} protected void delete(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { System. out.println("delete..." ); String bookid = request.getParameter( "bookid"); Cart cart = WebUtils. getCart(request); cartService.deleteItem(Integer.parseInt(bookid), cart); WebUtils. myForward(request, response, "/client/book/cart.jsp" ); } protected void update(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { System. out.println("update...." ); String count = request.getParameter( "count"); String bookId = request.getParameter( "bookId"); cartService.updateCount(Integer.parseInt(bookId), Integer. parseInt(count), WebUtils.getCart(request)); WebUtils. myForward(request, response, "/client/book/cart.jsp" ); } protected void clear(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { System. out.println("clear....." ); cartService.clear(WebUtils.getCart(request)); WebUtils. myForward(request, response, "/client/book/cart.jsp" ); }
}
5、编写业务处理类接口
/** * 处理购物车相关业务的接口 * @author Administrator * */public interface CartService { //向购物车中添加书,书→book 购物车→cart public void add(Book book ,Cart cart); //删除一个购物项 ,在购物车中找到要删除的购物项的bookId public void deleteItem(Integer BookId,Cart cart); //更新购物车中书的数量 public void updateCount(int BookId,int count,Cart cart); //清空购物车 public void clear(Cart cart); }
6、编写业务处理接口的实现类
/** * 处理购物车相关业务的实现类 * @author Administrator * */public class CartServiceImpl implements CartService {/** * 包含购物车中有书和没有书两种情况 */ @Override public void add(Book book, Cart cart) { Integer bookId = book.getBookId(); CartItem cartItem = cart.getMap().get(bookId); if(cartItem==null){//如果购物车为空的话 cartItem = new CartItem(book,1);//创建一个购物项 cart.getMap().put(bookId, cartItem); } else{// 不为空的话 cartItem.setCount(cartItem.getCount()+1); }
}
@Override public void deleteItem(Integer BookId, Cart cart) { cart.getMap().remove(BookId);
}
@Override public void updateCount(int BookId, int count, Cart cart) { cart.getMap().get(BookId).setCount(count);
}
@Override public void clear(Cart cart) { cart.getMap().clear();
}
}
6、页面访问(bookList.jsp)
数据来源:bookid=${book.bookId} &bookName= ${book.bookName}
以上来自于:< li>书名: <a href="client/BookClientServlet?method=getBook ★返回的是一个book对象,EL表达式可以获取book对象里面的属性.比如${book.bookId}
分析页面: ★页面上会显示三种状态: ●当没有书的时候:显示→购物车中暂时还没有一本书 ●当点击其他分类的时候:显示→您的购物车中有1本书, 查看购物车 ●当添加一本书的时候:显示→将android添加到了购物车, 购物车中有1本书, 查看购物车 如何实现呢??
< tr> < td class= "centerTd" colspan = "2"> < c:choose> < c:when test= " ${empty CART || empty CART.map}" > 购物车中暂时还没有一本书 </ c:when>
< c:when test= " ${empty param.bookName} "> 您的购物车中有${CART.totalCount}本书, < a href ="client/book/cart.jsp?1=1" >查看购物车 </ a> </ c:when>
< c:otherwise> 将 < font color ="red" >${param.bookName } </ font> 添加到了购物车, 购物车中有${CART.totalCount}本书, < a href ="client/book/cart.jsp?1=1" >查看购物车 </ a> </ c:otherwise> </ c:choose> </ td> </ tr>
★详细解答页面显示的三种状态★
◆判断购物车为空和判断购物车集合为空有什么区别? <c:when test="${empty CART || empty CART.map } ">
解答:这是两种情况,要分别写上 <!-- CART==null CART.map.size()==0 -->
◆第二个和第三个条件类似都是查看购物车有几本书,那么如何区分呢? 解:区分标准就是看有没有点击链接(图书信息中的“加入购物车”) ◇那么,点没点击链接到底有什么区别嗯? 解:看第二个条件有一个显示效果,将 android 添加到了购物车 , 购物车中有 1本书, 查看购物车 ◇那么,如何动态的显示添加的书名呢? 解:★妙招:将 <li><a href="client/CartServlet?method=add&bookid= ${book.bookId}"> 加入购物车</a></li> 该链接的后面加上 &bookName=${book.bookName} ,也即是: <li><a href="client/CartServlet?method=add&bookid= ${book.bookId}&bookName=${book.bookName} ">加入购物车 </a></li> 好处:只要点击该链接就会携带该参数,既可以用以显示书名,还可以用于标识到底该执行哪个条件(第二个、第三个) ◇那么,★在第二个条件中 <a href="client/book/cart.jsp?1=1" > 1=1是什么作用?? 如果不加的话:会报一个路径错误 /BookStore/client/book/cart.jsp&cateId=&minPrice=&maxPrice= 设想:要让所有的连接至少携带一个参数,这样才能保证是一个正确的路径 解:设置一个没有用的参数,此时请求地址发送变化 http://localhost:8989/BookStore/client/book/cart.jsp?1=1&cateId=&minPrice=&maxPrice= 这个时候就能正常访问了 ◇那么,如何理解 ${CART.totalCount}?
我的理解:CART 是存在于session 中的代表Cart 的对象,因此可以调用 getTotalCount()方法,在 EL表达式中要将 T转为小写
◆点击:加入购物车 后··· < li><a href="client/CartServlet?method=add&bookid=${book.bookId} &bookName= ${book.bookName}"> 加入购物车 </a></ li>
◇分析:${empty CART || empty CART.map} →数据来源于session,那么session中是什么时候设置进去呢? 在webUtils.java 中 /** * 从请求的session中获取购物车对象 * @param request * @return */ public static Cart getCart(HttpServletRequest request) { HttpSession session = request.getSession(); //从session中获取cart对象,不一定有,当为空的时候在创建 Cart cart = (Cart) session.getAttribute( "CART"); if(cart==null ){//如果获取不到就新 创建 cart = new Cart();//新建一个购物车 session.setAttribute( "CART",cart);//将购物车设置进session中 } return cart; }
什么时候用它的呢?
◇CartServlet中 protected void add(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { System. out.println("add...." ); String bookid = request.getParameter( "bookid"); Book book = bookService.getBookById(bookid); Cart cart = WebUtils.getCart(request);//从session中获取购物车对象 cartService.add(book, cart); //将书添加到购物车中国
WebUtils. myForward(request, response, "/client/BookClientServlet?method=getPageInCondition" ); }
7、显示页面Cart.jsp
◇点击 →将android添加到了购物车, 购物车中有1本书, 查看购物车 →Cart.jsp
◆进入我的购物车之后有两种可能:购物车中有书、没有书 ◇没有书:则显示没有书并跳转到购书页面(需要经过BookClientServlet)
<c:when test="${empty CART || empty CART.map}"> 购物车中没有一本书, 立即去 <a href="client/BookClientServlet?method=getPageInCondition" >购物 </a> </c:when>
◇有书则显示列表
<body>
<center>
<h2>我的购物车</h2>
<c:choose>
<c:when test="${empty CART || empty CART.map}">
购物车中没有一本书, 立即去<a href="client/BookClientServlet?method=getPageInCondition">购物</a>
</c:when>
<c:otherwise>
<table border="1" cellpadding="10" cellspacing="0">
<tr>
<td>书名</td>
<td>单价</td>
<td>数量</td>
<td>小计</td>
<td>操作</td>
</tr>
<!-- (bookid, CartItem) -->
<c:forEach items="${CART.map}" var="entry">
<tr>
<td>${entry.value.book.bookName}</td>
<td>${entry.value.book.price}</td>
<td>
<button class="decrease" ${entry.value.count<=1 ? 'disabled="false"' : ''}>-</button>
<input id="${entry.key}" class="count" type="text" value="${entry.value.count}" style="width: 30px;"/>
<button class="increase">+</button>
</td>
<td>${entry.value.itemPrice}</td>
<td><a class="delete" href="client/CartServlet?method=delete&bookid=${entry.key}">删除</a></td>
</tr>
</c:forEach>
<tr>
<td><a id="clear" href="client/CartServlet?method=clear" >清空购物车</a></td>
<td><a
href="client/BookClientServlet?method=getPageInCondition">继续购物</a></td>
<td>共${CART.totalCount}本书</td>
<td>总价:${CART.totalPrice}元</td>
<td><a href="#">去结算</a></td>
</tr>
</table>
</c:otherwise>
</c:choose>
</center>
</body>
8、清空购物车
点击: < td>< a id = "clear" href ="client/CartServlet?method=clear" >清空购物车 </ a></ td >
进入CartServlet protected void clear(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { System. out.println("clear...." ); cartService.clear(WebUtils.getCart(request)); WebUtils. myForward(request, response, "/client/book/cart.jsp" ); }
9、给所有删除链接添加点击事件
<script type= "text/javascript"> $(function(){ //给所有删除链接添加点击事件 $( ".delete").click(function (){ if(!window.confirm("你确认删除吗?" )) { return false ;//不让链接提交请求 } }); });</script>10、给所有显示书的数量的输入框添加失去焦点的事件
就是这个:<input id="${entry.key}" class="count" type="text" value="${entry.value.count}" style="width: 30px;"/>$(".count").blur( function(){ //得到输入框的值 var count = this .value; if(isNaN(count)) { count = 1; } count = count*1; //转为number类型 if(count<=0) { count = 1; } //书的id var bookId = this.id; //请求 window.location.href = "${pageContext.request.contextPath}/client/CartServlet?method=update&count=" +count+"&bookId=" +bookId; });
11、给<button>+</button>添加点击事件
$(".increase").click( function(){ //得到数量 var $countEle = $(this).parent().find("input" ); var count = $countEle.val();//链式调用 count = count*1+1; alert(count); //书的id var bookId = $countEle.attr("id" ); //请求 window.location.href = "${pageContext.request.contextPath}/client/CartServlet?method=update&count=" +count+"&bookId=" +bookId; });
12、给<button>-</button>添加点击事件
$(".decrease").click( function(){ //得到数量 var $countEle = $(this).parent().find("input" ); var count = $countEle.val();//链式调用 count = count*1-1; alert(count); //书的id var bookId = $countEle.attr("id" ); //请求 window.location.href = "${pageContext.request.contextPath}/client/CartServlet?method=update&count=" +count+"&bookId=" +bookId; });