购物车【JavaWeb项目、简单版】(java购物车的实现原理)
lipiwang 2025-07-03 16:54 4 浏览 0 评论
①构建开发环境免费学习资料获取方式
导入需要用到的开发包
建立程序开发包
②设计实体
书籍实体
public class Book {
private String id;
private String name;
private String author;
private String description;
private double price;
public Book() {
}
public Book(String id, String name, String author, String description, double price) {
this.id = id;
this.name = name;
this.author = author;
this.description = description;
this.price = price;
}
//...各种setter和getter
}
购物车与购物项实体
可能我们会这样设计购物车
/*该类代表的是购物车*/
public class Cart {
//关键字是书籍的id,值是书
private Map<String, Book> bookMap = new LinkedHashMap<>();
}
上面的做法是不合适的,试想一下:如果我要购买两本相同的书,购物车的页面上就出现了两本书,而不是书2。买三本相同的书就在购物页面上出现三本书,而不是书3.
因此,Map集合的值不能是Book对象,那我们怎么才能解决上面所说的问题呢?我们最常用的就是,再写一个实体CartItem(代表购物项)
- 好的,我们先来写购物项实体吧,等会再写购物车!
/*购物项代表的是当前书,并表示该书出现了几次*/
public class CartItem {
private Book book;
private int quantity;
//该购物项(书--不一定只有一本)的价钱应该等于书的数量*价格
private double price;
//书的价钱*数量
public double getPrice() {
return book.getPrice() * this.quantity;
}
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;
}
public void setPrice(double price) {
this.price = price;
}
}
- 购物车实体
/*该类代表的是购物车*/
public class Cart {
//关键字是书籍的id,值是书
private Map<String, CartItem> bookMap = new LinkedHashMap<>();
//代表着购物车的总价
private double price;
//把购物项(用户传递进来的书籍)加入到购物车里边去,也应该是购物车的功能
public void addBook(Book book) {
//获取得到购物项
CartItem cartItem = bookMap.get(book.getId());
//判断购物车是否存在该购物项,如果不存在
if (cartItem == null) {
//创建这个购物项对象
cartItem = new CartItem();
//将用户传递过来的书籍作为购物项
cartItem.setBook(book);
//把该购物项的数量设置为1
cartItem.setQuantity(1);
//把购物项加入到购物车去
bookMap.put(book.getId(), cartItem);
} else {
//如果存在该购物项,将购物项的数量+1
cartItem.setQuantity(cartItem.getQuantity() + 1);
}
}
//购物车的总价就是所有购物项的价格加起来
public double getPrice() {
double totalPrice = 0;
for (Map.Entry<String, CartItem> me : bookMap.entrySet()) {
//得到每个购物项
CartItem cartItem = me.getValue();
//将每个购物项的钱加起来,就是购物车的总价了!
totalPrice += cartItem.getPrice();
}
return totalPrice;
}
public Map<String, CartItem> getBookMap() {
return bookMap;
}
public void setBookMap(Map<String, CartItem> bookMap) {
this.bookMap = bookMap;
}
public void setPrice(double price) {
this.price = price;
}
}
③数据库
这里就直接用集合模拟数据库了,简单的domo而已。
//既然是购物车案例,应该会有增删的操作,通过关键字查询书籍,所以使用LinkedHashMap集合
private static Map<String, Book> map = new LinkedHashMap<>();
static {
map.put("1",new Book("1", "java", "zhongfucheng", "好书", 99));
map.put("2",new Book("2", "javaweb", "ouzicheng", "不好的书", 44));
map.put("3",new Book("3", "ajax", "xiaoming", "一般般", 66));
map.put("4",new Book("4", "spring", "xiaohong", "还行", 77));
}
public static Map<String, Book> getAll() {
return map;
}
④开发dao
dao层应该至少提供获取所有的书籍和根据关键字获取得到书籍
public class BookDao {
//获取存放着书籍的Map集合
public Map getAll() {
return BookDB.getAll();
}
//根据关键字获取某本书籍
public Book find(String id) {
return BookDB.getAll().get(id);
}
}
⑤开发service#
service层就是对DAO层的一个封装
public class BusinessService {
BookDao bookDao = new BookDao();
/*列出所有的书*/
public Map getAll() {
return bookDao.getAll();
}
/*根据书的id获取书*/
public Book findBook(String id) {
return bookDao.find(id);
}
//...待会还有其他的功能再从这里补充!
}
⑥开发web
列出所有的书
开发提供JSP页面的Servlet
//调用service层的方法,获取得到存放书籍的Map集合
BusinessService businessService = new BusinessService();
Map books = businessService.getAll();
//存放在request域对象中,交给jsp页面显示
request.setAttribute("books", books);
//跳转到jsp页面中
request.getRequestDispatcher("/WEB-INF/listBook.jsp").forward(request, response);
开发显示所有书籍的jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
<title>显示所有的书籍</title>
</head>
<body>
<%--Servlet传递过来的是一个Map对象,要显示所有的书籍,就需要遍历Map集合(EL表达式和JSTL标签合用)--%>
<table border="1px">
<tr>
<td>书籍编号</td>
<td>名称</td>
<td>作者</td>
<td>详细信息</td>
<td>价格</td>
</tr>
<c:forEach items="${books}" var="me">
<tr>
<td>${me.key}</td>
<td>${me.value.name}</td>
<td>${me.value.author}</td>
<td>${me.value.description}</td>
<td>${me.value.price}</td>
</tr>
</c:forEach>
</table>
</body>
</html>
购买操作
作为购物车的案例,怎么能没有购买的操作呢?于是乎就增加购买的操作!
开发处理购买的Servlet
//获取得到传递过来的id
String id = request.getParameter("bookid");
//把用户想要买的书放到购物车上
//用户不单单只有一个,要让购物车上只为当前的用户服务,就需要用到会话跟踪技术了
Cart cart = (Cart) request.getSession().getAttribute("cart");
//如果当前用户还没有点击过购买的商品,那么是用户的购物车是空的
if (cart == null) {
cart = new Cart();
request.getSession().setAttribute("cart", cart);
}
//调用BussinessService的方法,实现购买功能!
BusinessService businessService = new BusinessService();
businessService.buyBook(id, cart);
//跳转到购物车显示的页面上
request.getRequestDispatcher("/listCart.jsp").forward(request, response);
- 在我们前面开发BusinessService时,是没有buyBook()这个方法的!下面更新了BusinessService的代码:
/*
* 在购买书籍的时候,我们发现需要将书籍添加到购物车上
* 如果我们直接在Servlet上使用Cart实体对象的addBook()和BookDao对象的find()方法,是可以完成功能的
*
* 但是,这样web层的程序就跟Dao层的耦合了,为了代码性的健壮性和解耦,我们在BusinessService中对他俩进行封装
*
* 于是有了buyBook()这个方法!
* */
/*把用户想买的书籍添加到当前用户的购物车上*/
public void buyBook(String id, Cart cart) {
Book book = bookDao.find(id);
cart.addBook(book);
}
购物车的页面
- 初步把购物项的信息显示出来
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
<title>购物车显示页面</title>
</head>
<body>
<h1>购物车显示页面</h1>
<%--empty函数是判断集合中有没有元素--%>
<%--如果购物车是没有任何购物项的--%>
<c:if test="${empty(cart.bookMap)}">
<h1>您还没有购买过任何的书籍呀!</h1>
</c:if>
<%--如果购物车有购物项,就应该把购物项的信息显示给用户--%>
<c:if test="${!empty(cart.bookMap)}">
<table border="1px">
<tr>
<td>书籍编号</td>
<td>名称</td>
<td>数量</td>
<td>小计</td>
<td>操作</td>
</tr>
<c:forEach items="${cart.bookMap}" var="me">
<tr>
<td>${me.key}</td>
<td>${me.value.book.name}</td>
<td>${me.value.quantity}</td>
<td>${me.value.price}</td>
<td><a href="#">删除</a></td>
</tr>
</c:forEach>
<tr>
<td colspan="2"><a href="#">清空购物车</a></td>
<td colspan="2">合计:</td>
<td>${cart.price}</td>
</tr>
</table>
</c:if>
</table>
</body>
</html>
- 效果是这样子的:
删除购物车商品
想要删除购物车中的商品,也很简单,把删除操作挂在超链接上,超链接指向DeleteCartServlet,并将想要删除的书本的id带过去(不将id带过去,服务器哪知道你要删除的是哪个)!
<td><a href="${pageContext.request.contextPath}/DeleteCartBook?bookid=${me.key}">删除</a></td>
开发DeleteCartBook的Servlet
//获取得到用户想要删除哪个书本的id
String id = request.getParameter("bookid");
//获取该用户相对应的购物车对象
Cart cart = (Cart) request.getSession().getAttribute("cart");
try {
//删除购物车的商品,也应该是在BusinessService中有的功能,于是乎又回到BusinessService中写代码
BusinessService businessService = new BusinessService();
businessService.deleteBook(id, cart);
//删除购物车的商品后,也应该直接跳转回去购物车的显示页面中
request.getRequestDispatcher("/WEB-INF/listCart.jsp").forward(request, response);
} catch (CartNotFoundException e) {
request.setAttribute("message", "购物车空了!");
request.getRequestDispatcher("/message.jsp").forward(request, response);
} catch (Exception e) {
e.printStackTrace();
request.setAttribute("message", "删除中出现了异常~待会再试试呗!");
request.getRequestDispatcher("/message.jsp").forward(request, response);
}
- BusinessService又多了一个功能:
/*用户要在购物车中删除某个购物项*/
public void deleteBook(String id, Cart cart) throws CartNotFoundException {
//如果用户是直接访问DeleteCartBook的Servlet的,在session中是没有cart这个属性的!
//告诉用户购物车是空的
if (cart == null) {
throw new CartNotFoundException("购物车为空");
}
//把购物项移除出去集合就行了!
cart.getBookMap().remove(id);
}
效果:
多本一起购买
从上面的gif我们就可以发现,如果我重复买一本书,需要一本一本地点!这样会非常麻烦!
我们要怎么实现:用户想要买多少本,购物车的数量就修改为多少本呢?
在购物车上,数量的值改成是输入框
<td><input type="text" name="quantity" value="${me.value.quantity}"></td>
效果:
好的,现在我们已经能够把数量随自己想要多少本,就改成是多少了。现在主要的问题就是,怎么在改的同时,数据也及时地更新?
写javascript代码,让输入框的信息提交给服务器
我们写javascript的代码,监控着输入框的变动,如果有变动,就响应事件,将变动的数据传递给服务器,更新数据!
<script type="text/javascript">
/*
* @input 将输入框本身填入(这样可以获取得到输入框的值)
* @id 将书本的id传递进来,告诉服务器是修改哪一个购物项(书)
* @oldValue 原本的值,如果用户不想修改了,就修改为原本的值(下面会询问用户是否确定修改)
* */
function update(input,id,oldValue) {
//获取得到输入框的数据
var quantity = input.value;
//询问用户是否真的修改
var b = window.confirm("你确定修改吗?");
//如果确定修改,就跳转到修改的Servlet上
if(b) {
window.location.href = "${pageContext.request.contextPath}/UpdateQuantity?bookid=" + id + "&quantity=" + quantity + "";
}else {
//如果不确定修改,把输入框的数据改成是原来的
input.value = oldValue;
}
}
</script>
编写UpdateQuantity的Servlet
//获取得到用户想要修改哪一本书的id和相对应的数量
String id = request.getParameter("bookid");
String quantity = request.getParameter("quantity");
//得到当前用户的购物车
Cart cart = (Cart) request.getSession().getAttribute("cart");
try {
//调用BusinessService的方法去修改对应的数据
BusinessService businessService = new BusinessService();
businessService.updateQuantity(id, cart, quantity);
//修改完再跳转回去购物车的页面中
request.getRequestDispatcher("/WEB-INF/listCart.jsp").forward(request, response);
} catch (CartNotFoundException e) {
e.printStackTrace();
request.setAttribute("message", "购物车是空的!");
request.getRequestDispatcher("message.jsp").forward(request, response);
}
BusinessService增添了updateQuantity()方法
public void updateQuantity(String id, Cart cart, String quantity) throws CartNotFoundException {
//如果用户是直接访问DeleteCartBook的Servlet的,在session中是没有cart这个属性的!
//告诉用户购物车是空的
if (cart == null) {
throw new CartNotFoundException("购物车为空");
}
//通过书的id获取得到购物车的购物项,再修改购物项的数量即可!(因为书的id和获取购物项的关键字是一致的!)
cart.getBookMap().get(id).setQuantity(Integer.parseInt(quantity));
}
- 效果如下gif
清空购物车
清空购物车的做法和上面是类似的!也是首先通过javaScript代码询问用户是否要清空,如果要清空就跳转到相对应的Servlet中把购物车的数据清空了!
在清空购物车的链接上绑定事件
<td colspan="2">
<a href="${pageContext.request.contextPath}/ClearCart" onclick=" return clearCart()" >清空购物车</a>
</td>
javaScript代码做逻辑判断
function clearCart() {
var b = window.confirm("你确定要清空购物车吗?");
//如果用户确定,就跳转到相对应的Servlet上
if(b) {
return true;
}else {
return false;
}
}
编写ClearCart代码
//得到用户相对应的购物车
Cart cart = (Cart) request.getSession().getAttribute("cart");
//调用相对应BusinessService的方法
BusinessService businessService = new BusinessService();
try {
//清空购物车【实际上就是清空购物车的Map集合中的元素】
businessService.clearCart(cart);
//返回给购物车显示页面
request.getRequestDispatcher("/WEB-INF/listCart.jsp").forward(request, response);
} catch (CartNotFoundException e) {
e.printStackTrace();
request.setAttribute("message", "购物车是空的!");
request.getRequestDispatcher("/message.jsp").forward(request, response);
}
在BusinessService中添加清空购物车功能
public void clearCart(Cart cart) throws CartNotFoundException {
//如果用户是直接访问DeleteCartBook的Servlet的,在session中是没有cart这个属性的!
//告诉用户购物车是空的
if (cart == null) {
throw new CartNotFoundException("购物车为空");
}
//清空所有的购物项
cart.getBookMap().clear();
}
- 总结
- 购物车的应该是一个以id作为key,以购物项作为value的一个Map集合。这样设计的话,我们在显示商品的时候,就不会重复显示同一种类型的商品了。
- 购物项代表着该商品,并且应该给予购物项 数量和价钱的属性。购物项的价钱应该是数量*单价
- 购物车应该提供把商品添加到购物车的功能。当然啦,购物项代表着商品,所以首先要判断该购物车是否有同类的商品,如果有,直接在购物项的数量上+1即可的。如果没有,就设置该购物项的属性,并把购物项添加到购物车中
- 购物车的总价就是所有购物项的总价
- 无论是增删改查购物车的数据,其实就是操作这个集合
- 如果文章有错的地方欢迎指正,大家互相交流。
- 免费学习资料获取方式
相关推荐
- Nat. Synthesis: 重大突破,电化学形成C-S键
-
第一作者:JunnanLi,HasanAl-Mahayni通讯作者:AliSeifitokaldani,NikolayKornienko通讯单位:蒙特利尔大学,麦吉尔大学【研究亮点】形成C-...
- 网络安全与应用(二)(网络安全理论与应用)
-
1、应用层安全协议SHTTP和HTTPS:SHTTP:SecHTTP,安全超文本传输协议,是HTTP扩展,使用TCP的80端口。HTTPS:HTTP+SSL,使用TCP的443端口。大部分web应用...
- TN-C、TN-S、TT、IT供电系统详解及对比
-
TN-C、TN-S、TT、IT供电系统是低压配电系统中常见的四种接地方式,它们各自有不同的特点和适用场景。一、系统介绍TN-C供电系统①定义:整个系统中,工作零线(N线)与保护零线(PE线)是合一的,...
- 网络应用服务器(三)(网络应用程序服务器)
-
#头条创作挑战赛#1、DNS协议:域名解析协议,用于把主机域名解析为对应的IP地址。是一个分布式数据库,C/S工作方式。主要基于UDP协议,少数使用TCP,端口号都是53。常用域名如下2、DNS协议...
- 腾讯发布混元Turbo S:业界首次无损应用Mamba架构
-
21世纪经济报道记者白杨北京报道2月27日,腾讯正式发布新一代基座模型——混元TurboS。据腾讯混元团队介绍,混元TurboS在架构方面创新性地采用了Hybrid-Mamba-Transfor...
- 【收藏】低压配电系统中TT IT TN-S/TN-C/TN-C-S 的区别?
-
低压配电系统的接地型式选择是电气安全设计的核心环节,TT、IT、TN-S、TN-C、TN-C-S这五种主要接地型式因其结构、保护原理和故障特性的显著差异,在工程应用中有不同的适用范围和限制条件。如若发...
- 金万维公有云平台如何实现C/S架构软件快速SaaS化
-
金万维作为国内领先的企业信息化垂直B2B平台运营商,拥有超过5000家管理软件合作伙伴,掌握管理软件一线的发展动态,因此深知传统管理软件近年来面对的困境和问题。而SaaS却在软件行业内发展迅猛势如燎原...
- 随时随地做翻译:B/S架构的传奇时代到来
-
随着新兴技术的发展和大数据时代的到来,翻译作为连接各国语言和文化的工具,更是具有前所未有的拓展空间。传统的在计算机辅助翻译软件(CAT)上进行翻译的模式,受到时间和空间的限制,导致翻译过程中面临层层障...
- BS和CS 架构的介绍(一篇就够了)(cs和bs架构的含义)
-
简介C/S又称Client/Server或客户/服务器模式。服务器通常采用高性能的PC、工作站或小型机,并采用大型数据库系统,如Oracle、Sybase、Informix或SQLServer。...
- 物管王(包租婆)软件架构与B/S和C/S架构的优点和缺点比较
-
一、B/S系统架构的优点和缺点优点:1)客户端无需安装,有Web浏览器即可。2)BS架构可以直接放在广域网上,通过一定的权限控制实现多客户访问的目的,交互性较强。3)BS架构无需升级多个客户端,升级服...
- 监听器入门看这篇就够了(怎么检查车上有没有被别人安装监听器)
-
什么是监听器监听器就是一个实现特定接口的普通java程序,这个程序专门用于监听另一个java对象的方法调用或属性改变,当被监听对象发生上述事件后,监听器某个方法将立即被执行。。为什么我们要使用监听器?...
- 购物车【JavaWeb项目、简单版】(java购物车的实现原理)
-
①构建开发环境免费学习资料获取方式导入需要用到的开发包建立程序开发包②设计实体书籍实体publicclassBook{privateStringid;privat...
- 基础篇-SpringBoot监听器Listener的使用
-
1.监听器Listener简介1.1监听器Listener介绍Listener是JavaWeb的三大组件(Servlet、Filter、Listener)之一,JavaWeb中的监听器主要用...
- 你在 Spring Boot3 整合 JWT 实现 RESTful 接口鉴权时是否遇到难题?
-
各位后端开发小伙伴们!在日常使用SpringBoot3搭建项目时,RESTful接口的鉴权至关重要。而JWT技术,作为一种简洁且高效的鉴权方式,被广泛应用。但大家是不是在整合过程中遇到过各...
- javaWeb RSA加密使用(rsa加密java代码)
-
加密算法在各个网站运用很平常,今天整理代码的时候看到了我们项目中运用了RSA加密,就了解了一下。先简单说一下RSA加密算法原理,RSA算法基于一个十分简单的数论事实:将两个大质数相乘十分容易,但是想要...
你 发表评论:
欢迎- 一周热门
- 最近发表
- 标签列表
-
- maven镜像 (69)
- undefined reference to (60)
- zip格式 (63)
- oracle over (62)
- date_format函数用法 (67)
- 在线代理服务器 (60)
- shell 字符串比较 (74)
- x509证书 (61)
- localhost (65)
- java.awt.headless (66)
- syn_sent (64)
- settings.xml (59)
- 弹出窗口 (56)
- applicationcontextaware (72)
- my.cnf (73)
- httpsession (62)
- pkcs7 (62)
- session cookie (63)
- java 生成uuid (58)
- could not initialize class (58)
- beanpropertyrowmapper (58)
- word空格下划线不显示 (73)
- jar文件 (60)
- jsp内置对象 (58)
- makefile编写规则 (58)