实现购物车功能

本篇博客所完成的购物车应用重点主要落在页面之间的转换和数据的传递,对于前端界面设计并不多加分析。属于初学 Web 编程阶段。

该购物车应用主要有四个功能:查看商品列表、查看商品详情、将商品加入购物车、显示购物车信息、将商品从购物车中移除。

 

目录

准备工作

设置映射即每个功能对应方法

查看商品列表

查看商品详情

将商品加入购物车

显示购物车信息

将商品从购物车中移除


准备工作

该购物车应用有两个主要对象,商品 和 购物车,所以需要构建 Product 类来存储商品的信息,构建 ShoppingItem 来存储购物车列表信息。

Product 类中包含商品的基本信息(如下),还有各个属性的 set 和 get 方法。

        private int id;//商品编号
	private String name;//商品名称
	private String description;//商品描述
	private float price;//商品价格

ShoppingItem 类存储购物车信息,所以该类中包含相应商品及其购买数量,同样不要忘记属性的 set 和 get 方法。

	private Product product;//商品信息
	private int quantity;//商品数量

在我们功能的实现中,会将 Product 和 ShoppingItem 都存储到 List 中(List<Product> products 和 List<ShoppingItem> cart),但是不同的的是,商品的信息是固定的,所以我们可以将存储商品的信息的 List 放在Servlet 中,然而,客户的购物车信息会在客户的活动中发生变化,因此每个客户需要有一个单独的对象将其的购物车信息进行存储,我们可以通过会话机制 HttpSession 实现。

当用户登陆购物网站时,Web 服务器会为客户创建一个 HttpSession 对象,实现购物车的 Servlet 使用该会话对象存储用户的购物车对象 cart ,购物车中存储着用户购买的商品列表,当客户向购物车中添加或删除商品时, Servlet 就更新该列表,当客户结账时, Servlet 就会从会话中检索购物车对象,从购物车中检索商品列表并计算总价格。一旦客户结算完成,容器就会关闭会话。如果客户再发送另一个请求,就会创建一个新的会话。

在我们的功能实现之前,我们还要初始化我们的商品列表 products 。创建一个 ShoppingCartServlet 类,我们的所有功能都会在这里实现,在 ShoppingCartServlet 的 init() 方法中初始化列表。

 
      private List<Product> products = new ArrayList<Product>();  // products 存放所有商品的List对象
      public void init() throws ServletException {
		products.add(new Product(1, "单反相机", "尼康性价比最高的单反相机", 4159.95F));
		products.add(new Product(2, "华为手机", "华为手机的最新手机P30", 3998.95F));
		products.add(new Product(3, "笔记本电脑", "Mac新一代产品", 15000.51F));
		products.add(new Product(4, "平板电脑", "苹果公司新产品", 12000F));
	}

设置映射即每个功能对应方法

ShoppingCartServlet 类时一个控制类,处理各种信息。我们刚刚已经在 init() 方法中初始化了商品列表,现在要在 web.xml 中设置映射和每个功能对应的方法了。

在 web.xml 中设置 ShoppingCartServlet 类 的映射

  <servlet-mapping>
    <servlet-name>ShoppingCartServlet</servlet-name>
    <url-pattern>/ShoppingCartServlet</url-pattern>       
    <url-pattern>/products</url-pattern>                 显示商品列表
    <url-pattern>/viewProductDetails</url-pattern>       显示商品详细内容
    <url-pattern>/viewCart</url-pattern>                 查看购物车
    <url-pattern>/deleteItem</url-pattern>               从购物车中移除商品
    <url-pattern>/addToCart</url-pattern>                向购物车中加入商品
  </servlet-mapping>

在 doGet() 方法中设置每个功能对应的方法,因为当我们按下 enter 键进行界面跳转的时候就会触发 doGet() 方法,在这个方法中就进行判断显然合情合理。

public void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {
	String uri = request.getRequestURI();// 得到当前界面的URI
	if (uri.endsWith("/products"))
		showProductList(response);
	else if (uri.endsWith("/viewProductDetails"))
		showProductDetails(request, response);
	else if (uri.endsWith("/viewCart"))
		showCart(request, response);
	else if (uri.endsWith("/deleteItem"))
		deleteItem(request, response);
	else
		showProductList(response);// 发送请求,调用get方法后首先显示商品列表信息
}

由于在这里触及了几个知识点,不禁想提出来,给大家思考回顾。

1. request 和 response 的区别。

2. URI 的结构、发展,以及URI 和 URL 、URN 的联系。(一篇比较详细的博客: URI 详解 )

查看商品列表

查看商品列表会看见以下页面(括号中的时商品价格)

 

主要步骤:

1. 设置response 中的内容类型和所使用的字符集,得到 PrintWriter 对象。

2. 遍历商品列表并将信息显示出来,其中 ”详细信息“ 采用超文本链接,并将商品的 id 号传过去。(注意,id=product.getId() 中,等号和product.getId() 之间不可以出现空格,否则读取 id 号时会出错  ,即 NumberFormatException 错误)

// 超链接到商品详情目录
out.println("(<a href = 'viewProductDetails?id=" + product.getId()+ "'>详细信息</a>)");

在显示 商品详细信息的方法中可以用以下语句得到传过去的 id 号

productId = Integer.parseInt(request.getParameter("id"));

3. 设置 查看购物车 链接。

out.println("<a href = 'viewCart'>查看购物车</a>");//查看购物车链接

具体代码如下:

	private void showProductList(HttpServletResponse response)throws IOException {
		response.setContentType("text/html;charset = UTF-8");//设置数据的内容类型和使用的字符集
		PrintWriter out = response.getWriter();
		out.println("<html><head><title>商品列表</title></head>");
		out.println("<body><p>商品列表</p>");
		out.println("<ul>");
		for (Product product : products) {
			// 显示商品名称和价格
			out.println("<li>" + product.getName() + "(" + product.getPrice()+ ")");
			// 超链接到商品详情目录
			out.println("(<a href = 'viewProductDetails?id=" + product.getId()+ "'>详细信息</a>)");
		}
		out.println("</ul>");
		out.println("<a href = 'viewCart'>查看购物车</a>");//查看购物车链接
		out.println("</body></html>");
	}

查看商品详情

查看商品详情的页面如下:

其中,让我们看看这个页面的URI 

其中我们在查看商品列表的方法中设置了”详细信息“ 链接的URI,即查看商品详情的URI 的 path 最后为 viewProductDetails ,并且把商品的 id 一并传了过来,由于我们按的是 ”单反相机“ ,所以显示的 id 号为 1。

主要步骤:

1.  得到传过来的 id 号。

	int productId = 0; // 商品的Id号,用来检索商品
	//得到传过来的 id 号
	try {
		productId = Integer.parseInt(request.getParameter("id"));
	} catch (NumberFormatException e) {
		e.printStackTrace();
	}

2. 根据 id 号检索 products 列表得到相应的商品。

	private Product getProduct(int id) {
		for (Product product : products) {
			if (product.getId() == id)
				return product;
		}
		return null;
	}

3. 显示商品的信息

4. 设置购买按钮

out.println("<td><input name = 'quantity'/></td>");  //输入商品数量
out.println("<td><input type = 'submit' value = '购买'/></td></tr>");

5. 设置商品列表链接

out.println("<tr><td colspan = '2'>"+ "<a href = 'products'>商品列表</a></td></tr>");

详细代码如下:

	private void showProductDetails(HttpServletRequest request,HttpServletResponse response) throws IOException {

		response.setContentType("text/html;charset = UTF-8");
		PrintWriter out = response.getWriter();
		int productId = 0; // 商品的Id号,用来检索商品
		//得到传过来的 id 号
		try {
			productId = Integer.parseInt(request.getParameter("id"));
		} catch (NumberFormatException e) {
			e.printStackTrace();
		}
		// 根据商品id返回商品对象
		Product product = getProduct(productId);

		if (product != null) {

			out.println("<html><head><title>商品详细信息</title></head>");
			out.println("<body><p>商品详细信息</p>");
			out.println("<form method = 'post' action = 'addToCart'>");
			// 这里使用隐藏表单域存储商品号信息
			out.println("<input type = 'hidden' name = 'id' value = '"
					+ productId + "'/>");
			out.println("<table>");
			out.println("<tr><td>商品名:</td><td>" + product.getName()
					+ "</td></tr>");
			out.println("<tr><td>说明:</td><td>" + product.getDescription()
					+ "</td></tr>");
			out.println("<tr><td>价格:</td><td>" + product.getPrice()
					+ "</td></tr>");
			out.println("<tr><tr>");
			out.println("<td><input name = 'quantity'/></td>");  //输入商品数量
			out.println("<td><input type = 'submit' value = '购买'/></td></tr>");
			out.println("<tr><td colspan = '2'>"+ "<a href = 'products'>商品列表</a></td></tr>");
			out.println("</table>");
			out.println("</form></body>");
		} else {
			out.println("No product found");
		}
	}

将商品加入购物车

当我们在商品的详细信息页面中输入商品数量并点击购买按钮时,我们会触发该 Servlet 的 doPost() 方法,因此,我们可以在doPost()方法中将商品加入购物车。

具体步骤如下:

1. 得到要加入购物车的商品的 id 和 数量

	int productId = 0;
	int quantity = 0;
	// 得到要加入购物车中的商品ID和数量
	try {
		productId = Integer.parseInt(request.getParameter("id"));
		quantity = Integer.parseInt(request.getParameter("quantity"));
	} catch (NumberFormatException e) {
		e.printStackTrace();
	}

2. 得到 id 对应的商品

Product product = getProduct(productId);

3. 得到会话对象,并在会话对象中查找购物车对象 cart 

// 在会话对象中查找购物车对象
HttpSession session = request.getSession();
List<ShoppingItem> cart = (ArrayList<ShoppingItem>) session.getAttribute("cart");

4. 检查该 cart 对象是否为 null ,若为null 则创建一个 cart 列表对象(ArrayList<ShoppingItem>)

if (cart == null) {
	// 若购物车为空,则创建购物车并将其加入到session中
	cart = new ArrayList<ShoppingItem>();
	session.setAttribute("cart", cart);
}

   若不为 null ,则检查购物车之前是否添加过同一种商品, 若有,将item中的quantity更新,并移除上一条信息

else {
	for (int i = 0; i < cart.size(); i++) {
		ShoppingItem subItem = cart.get(i);  //得到购物车列表消息
		int subProductId = subItem.getProduct().getId();  
		if(subProductId == productId){  //若购物车中以加入过该商品
			quantity += subItem.getQuantity();  //更新商品数量
			cart.remove(subItem);//移除上一条信息
			break;
		}		
	}
}

5.  建立购物车条目,并将其加入到 cart 对象中

ShoppingItem item = new ShoppingItem(product, quantity);
cart.add(item);

同样,这里也有很有意思的问题,在这里我们使用了 HttpSession ,虽然没有使用 Cookie ,但是,我认为大家可以同样思考清楚

HttpSession 和 Cookie 的具体功能分别是什么,有什么不同,两者有哪些优缺点。

6. 最后可以考虑跳回商品列表页面

具体代码如下:

	public void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {

		int productId = 0;
		int quantity = 0;
		// 得到要加入购物车中的商品ID和数量
		try {
			productId = Integer.parseInt(request.getParameter("id"));
			quantity = Integer.parseInt(request.getParameter("quantity"));
		} catch (NumberFormatException e) {
			e.printStackTrace();
		}
		// 得到该ID对应的商品
		Product product = getProduct(productId);
		if (product != null && quantity >= 0) {
			// 在会话对象中查找购物车对象
			HttpSession session = request.getSession();
			List<ShoppingItem> cart = (ArrayList<ShoppingItem>) session.getAttribute("cart");

			if (cart == null) {
				// 若购物车为空,则创建购物车并将其加入到session中
				cart = new ArrayList<ShoppingItem>();
				session.setAttribute("cart", cart);
			} else {
				// 不为空时,检查购物车之前是否添加过同一种商品
				// 若有,将item中的quantity更新,并移除上一条信息,退出循环
				// 若无,则直接加入
				for (int i = 0; i < cart.size(); i++) {
					ShoppingItem subItem = cart.get(i);  //得到购物车列表消息
					int subProductId = subItem.getProduct().getId();
					if(subProductId == productId){  //若购物车中以加入过该商品
						quantity += subItem.getQuantity();  //更新商品数量
						cart.remove(subItem);//移除上一条信息
						break;
					}
						
				}
			}
			// 建立购物车条目,并将其加入到 cart 对象中
			ShoppingItem item = new ShoppingItem(product, quantity);
			cart.add(item);
		}
		// 添加成功后返回商品列表
		showProductList(response);
	}

显示购物车信息

查看购物车页面内容如下:

具体步骤如下:

1. 得到 httpSession 对象和 cart 购物车对象

2. 设置商品列表链接

out.println("<body><a href = 'products'>商品列表</a>");

3. 设置第一行信息并设置列宽

out.println("<table>");
out.println("<tr><td style='width:50px'>数量</td>");
out.println("<td style='width:80px'>商品</td>");
out.println("<td style='width:80px'>价格</td>");
out.println("<td style='width:80px'>小计</td>");
out.println("<td style='width:80px'>是否删除</td></tr>");

4. 从购物车对象中得到商品信息并打印出来,还要计算其总价格 ( total )和 小计

    在设置删除链接时记的把要删除商品的 id 号传过去

out.println("<td><a href = 'deleteItem?id="+ product.getId() + "'>删除</a></td>");

具体代码如下:

	private void showCart(HttpServletRequest request,HttpServletResponse response) throws IOException {

		response.setContentType("text/html;charset = UTF-8");
		PrintWriter out = response.getWriter();
		HttpSession session = request.getSession();	// 得到会话对象
		List<ShoppingItem> cart = (ArrayList<ShoppingItem>) session.getAttribute("cart");//得到 cart
		//第一行的信息
		out.println("<html?<head><title>购物车</title></head>");
		out.println("<body><a href = 'products'>商品列表</a>");
		out.println("<table>");
		out.println("<tr><td style='width:50px'>数量</td>");
		out.println("<td style='width:80px'>商品</td>");
		out.println("<td style='width:80px'>价格</td>");
		out.println("<td style='width:80px'>小计</td>");
		out.println("<td style='width:80px'>是否删除</td></tr>");
		// 从购物车对象中得到商品信息并打印出来
		if (cart != null) {
			double total = 0.0;
			for (int i = 0; i < cart.size(); i++) {
				ShoppingItem item = cart.get(i);
				Product product = item.getProduct();
				int quantity = item.getQuantity();
				if (quantity != 0) {
					out.println("<tr><td>" + quantity + "</td>");
					out.println("<td>" + product.getName() + "</td>");
					out.println("<td>" + product.getPrice() + "</td>");
					double subtotal = product.getPrice() * quantity;// 得到该商品的价格小计
					out.println("<td>" + subtotal + "</td>");
					out.println("<td><a href = 'deleteItem?id="+ product.getId() + "'>删除</a></td>");
					out.println("</tr>");
					total += subtotal;
				}
			}

			out.println("<tr><td colspan='4' style='text-align:right'>总计:"+ total + "</td></tr>");
			out.println("</table>");
		}
		out.println("</table></body></html>");
	}

将商品从购物车中移除

这个功能的实现较为简单

1. 得到 会话对象,再得到 cart 购物车列表对象

2. 得到传过来的商品 id 

3. 遍历购物车中的商品,找到与删除商品id号相同的购物车商品信息,并将之移除出购物车

具体代码如下:

	private void deleteItem(HttpServletRequest request,HttpServletResponse response) throws IOException {
		// 得到会话对象
		HttpSession session = request.getSession();
		// 得到购物车对象
		List<ShoppingItem> cart = (ArrayList<ShoppingItem>)session.getAttribute("cart");
		// 得到删除商品的id号
		int productId = Integer.parseInt(request.getParameter("id"));
		// 遍历购物车中的商品,找到与删除商品id号相同的购物车商品信息,并将之移除出购物车
		for (int i = 0; i < cart.size(); i++) {
			ShoppingItem item = cart.get(i);
			Product product = item.getProduct();
			int subProductId = product.getId();
			if (subProductId == productId) {
				cart.remove(item);
				break;
			}
		}
		showCart(request, response);
	}
  • 到这里,这个购物车应用的基本功能就实现了,当然,这个应用还非常的粗糙,但是千里之行始于足下,一步步学习终会越来越好。如果各位发现什么问题或者有什么可以一起交流欢迎留言。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值