Java Web基础入门第三十讲 基于Servlet+JSP+JavaBean开发模式的购物车

版权声明:本文为博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/yerenyuan_pku/article/details/52116564

前言:上一讲以一个最常用的用户登录注册程序来讲解Servlet+JSP+JavaBean开发模式,所以我们也初步了解了Servlet+JSP+JavaBean(MVC)这种开发模式。现在我们以一个网上购物时的购物车程序来重新回顾这种开发模式。

创建MVC架构的Web项目

在Eclipse中新创建一个day10项目,导入项目所需要的开发包(jar包),创建项目所需要的包,在Java开发中,架构的层次是以包的形式体现出来的。
在这里插入图片描述
温馨提示:不同于上一讲的用户登录注册程序,该购物车程序是创建一个类来代表数据库,所以不需要用到其他一些jar包,只需用到stl-1.2.jar就行。
在这里插入图片描述
以上就是根据此项目的实际情况创建的包,可能还需要创建其他的包,这个得根据项目的需求来定了。
紧接着,我们就来创建代表数据库的类。假设这是一个网上书城的项目,用户购买的商品即为书,所以在数据库中存储的商品就是书。于是,在cn.liayun.DB包下创建一个DB类,该类的具体代码如下:

package cn.liayun.DB;

import java.util.LinkedHashMap;
import java.util.Map;

import cn.liayun.domain.Book;

//代表数据库的类
public class DB {
	
	private static Map<String, Book> map = new LinkedHashMap<String, Book>();
	
	static {
		map.put("1", new Book("1", "Java Web开发", "老张", 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;
	}
}

温馨提示:关于怎样创建代表数据库的类,即DB.java,可参考我的这篇博客——《Java Web基础入门第十八讲 Servlet开发——使用Cookie进行会话管理》
然后,在WEB-INF目录下创建一个jsp目录,jsp目录存放系统的一些受保护(不允许用户直接通过URL地址进行访问)的jsp页面,用户要想访问这些受保护的jsp页面,那么只能通过cn.liayun.web.UI这个包里面的Servlet。最后,创建好的项目架构如下图所示:
在这里插入图片描述

分层架构的代码编写

分层架构的代码也是按照【域模型层(domain)】→【数据访问层(dao、dao.impl)】→【业务逻辑层(service、service.impl)】→【表现层(web.controller、web.UI、web.filter、web.listener)】→【工具类(util)】→【测试类(junit.test)】的顺序进行编写的。

开发domain层

在cn.liayun.domain包下创建一个Book类,该类的具体代码如下:

package cn.liayun.domain;

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;
	}
	
}

开发数据访问层(dao、dao.impl)

在cn.liayun.dao包下创建一个UserDao类,该类的具体代码如下:

package cn.liayun.dao;

import java.util.Map;

import cn.liayun.DB.DB;
import cn.liayun.domain.Book;

public class BookDao {

	public Map<String, Book> getAll() {
		return DB.getAll();
	}
	
	public Book find(String id) {
		return DB.getAll().get(id);
	}
	
}

开发service层(service层对web层提供所有的业务服务)

我们在第一次开发一个新项目的过程当中,并不清楚要开发的项目的所有功能,所以我们可以先开发出最容易想到的功能,然后将自己伪装成一个用户,在浏览网站页面的过程中,看用户需要什么功能,那我们程序员就开发什么功能,然后步步为营,将整个项目的功能完成。例如,我第一次开发这个购物车功能模块的过程当中,首先想到的是要给用户展示所有书籍,以及根据书的ID查询书的信息。其他的功能我没想到,所以可以等这些功能完成之后,根据前端页面来看需要什么功能。
在cn.liayun.service包下创建一个BusinessService类,先实现如下两个业务服务的功能:

  1. 给用户展示所有书籍;
  2. 根据书的ID查询书的信息。

这样,该类的具体代码如下:

package cn.liayun.service;

import java.util.Map;

import cn.liayun.dao.BookDao;
import cn.liayun.domain.Book;

//业务类,统一对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);
	}
	
}

开发web层

开发给用户展示所有书籍的功能

在cn.liayun.web.controller包中编写用于处理给用户展示所有书籍请求的ListBookServlet,该Servlet的具体代码如下:

package cn.liayun.web.controller;

import java.io.IOException;
import java.util.Map;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import cn.liayun.domain.Book;
import cn.liayun.service.BusinessService;

//获取所有书
@WebServlet("/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);
	}

}

接着,在WEB-INF/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="1px" 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>

网站一般都有一个首页,在该项目中我们的首页是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>

至此,给用户展示所有书籍的功能就算是开发完成了!下面测试一下开发好的该功能。
在这里插入图片描述

开发购买书籍的功能

在现实中购买商品时,用户都是将商品放到购物车中,所以我们应该按照现实中的情况设计一个代表用户购物车的类,即Cart.java。
现在再来思考一个问题:在设计代表用户购物车的Cart类时,应该使用private Book book字段(或属性)来代表用户所购买的商品吗?答案显然不是。若是使用这样的字段,结果就是不可避免地在购物车中出现重复商品,即用户如果购买一本书多次,那么购物车中就出现一本书多次,显然在现实中这是不合理的。那么到底该怎么做呢?为了避免在购物车里面出现重复商品,我们这时会设计一个专门的对象,即CartItem(购物项,代表某个商品以及这个商品出现的次数)。于是,我们在cn.liayun.domain包中创建一个CartItem类,用于代表某个商品,以及商品出现的次数(购物项),该类的具体代码如下:

package cn.liayun.domain;

//用于代表某个商品,以及商品出现的次数(购物项)
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;
	}
	
}

紧接着,在cn.liayun.domain包中创建一个代表用户购物车的Cart类,该类的具体代码如下:

package cn.liayun.domain;

import java.util.LinkedHashMap;
import java.util.Map;

//代表用户的购物车
public class Cart {
	
	/*
	 * 为了避免在购物车里面出现重复商品,
	 * 我们这时会设计一个专门的CartItem对象(购物项,代表某个商品以及这个商品出现的次数)
	 */
	private Map<String, CartItem> map = new LinkedHashMap<String, CartItem>();
	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;
	}
	
}

用户浏览网站首页时,会看到网站所有书籍,用户即可对自己感兴趣的书籍进行购买,点击购买超链接时,跳转到一个Servlet对用户的请求进行处理。所以在cn.liayun.web.controller包中创建一个用于处理书籍购买请求的BuyServlet,该Servlet的具体代码如下:

package cn.liayun.web.controller;

import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import cn.liayun.domain.Book;
import cn.liayun.domain.Cart;
import cn.liayun.service.BusinessService;

//完成书籍购买
@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,然后再转到listcart.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);
	}

}

温馨提示:显示购物车时,记住千万不要用请求转发,而应该使用重定向技术。若不是,产生的后果可参考我的这篇博客——《Java Web基础入门第十九讲 Servlet开发——Session》。我上面的代码使用的是请求转发,这是不行的,读者要注意了啊!既然要使用重定向技术,下面这行代码可行吗?

response.sendRedirect("/WEB-INF/jsp/listcart.jsp");

答案不言而喻,这是不行的。因为这是浏览器重新访问地址/WEB-INF/jsp/listcart.jsp,listcart.jsp页面是被保护起来的,外界是无法直接访问的。如果一定要实现的话,会比较麻烦,还需要先跳到一个Servlet,然后再跳转到listcart.jsp页面。所以正规的做法是:BuyServlet类中使用重定向技术,即添加如下代码:

response.sendRedirect(request.getContextPath() + "/ListCartUIServlet");

然后在cn.liayun.web.UI包下创建一个ListCartUIServlet类,专门用来接收请求之后转到listcart.jsp页面,给用户提供用户界面。

package cn.liayun.web.UI;

import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebServlet("/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 {
		// TODO Auto-generated method stub
		doGet(request, response);
	}

}

这毕竟不是一个真实项目,所以不想把其搞得这么复杂哈!所以就干脆用了请求转发,但是读者一定要知道这还是不行的,要知道用重定向技术,怎么使用我也已经写的很明白了!
最后,给出购物车显示页面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) }">	<!-- el表达式中的empty()函数:检测map是否为null或"",若是则返回true -->
		您没有购买任何商品!!!
	</c:if>
	
	<c:if test="${!empty(cart.map) }">
		<table width="70%" border="1px" align="center">
			<tr>
				<td>书名</td>
				<td>作者</td>
				<td>单价</td>
				<td>数量</td>
				<td>小计</td>
				<td>操作</td>
			</tr>
			
			<c:forEach var="entry" items="${cart.map }">
				<tr>
					<td>${entry.value.book.name }</td>
					<td>${entry.value.book.author }</td>
					<td>${entry.value.book.price }</td>
					<td>
						<input type="text" name="quantity" value="${entry.value.quantity }" style="width: 25px" 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>

至此,用户购买书籍的功能就算是开发完成了!下面测试一下开发好的该功能。
在这里插入图片描述

开发删除购物车中购物项的功能

在BusinessService类中实现如下业务服务的功能:

  • 删除购物车中购物项

此时BusinessService类的具体代码如下:

package cn.liayun.service;

import java.util.Map;

import cn.liayun.dao.BookDao;
import cn.liayun.domain.Book;
import cn.liayun.domain.Cart;

//业务类,统一对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);
	}

}

接着在cn.liayun.web.controller包中创建一个DeleteItemServlet,该Servlet的具体代码如下:

package cn.liayun.web.controller;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import cn.liayun.domain.Cart;
import cn.liayun.service.BusinessService;

//删除指定的购物项
@WebServlet("/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);
	}

}

注意:我上面的代码使用的是请求转发,这依然是不行的,读者要注意了啊!仍然要使用请求重定向,考虑到这毕竟不是一个真实项目,所以尽量不要搞得那么复杂,一切从简。
最后,在购物车显示页面listcart.jsp中还要写入以下JavaScript代码:
在这里插入图片描述
不然的话,用户手贱,不小心删除了所选的购物项,辛辛苦苦购买的商品又要重新购买,用户的感受肯定巨不爽,所以在用户不小心删除了所选的购物项时,还要问用户是否确认删除。只有用户点击确认按钮才会删除,这样对用户来说,体验会更好。
至此,删除购物车中购物项的功能就算是开发完成了!下面测试一下开发好的该功能。
在这里插入图片描述

开发清空购物车的功能

在BusinessService类中实现如下业务服务的功能:

  • 清空购物车

编写对应的清空购物车的方法时,由于代表用户购物车的Cart类存在session中,是不是可以像下面这样写呢?
在这里插入图片描述
答案是不可以。业务逻辑层用到了Web层的session对象,于是业务逻辑层和Web层牢牢绑定在一起了,业务逻辑层离开Web层就跑不起来,如果这样写,若要对业务层进行测试,需要把Web服务器起起来,传一个session对象进去,所以在各层之间传递的只能是JavaBean,不能让Web层的特殊对象侵入到业务逻辑层,污染业务逻辑层
此时,BusinessService类的具体代码如下:

package cn.liayun.service;

import java.util.Map;

import cn.liayun.dao.BookDao;
import cn.liayun.domain.Book;
import cn.liayun.domain.Cart;

//业务类,统一对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();
	}

}

接着,在cn.liayun.web.controller包中创建一个ClearCartServlet,该Servlet的具体代码如下:

package cn.liayun.web.controller;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import cn.liayun.domain.Cart;
import cn.liayun.service.BusinessService;

//清空购物车
@WebServlet("/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);
	}

}

注意:我上面的代码使用的是请求转发,这依然是不行的,读者要注意了啊!仍然要使用请求重定向,考虑到这毕竟不是一个真实项目,所以尽量不要搞得那么复杂,一切从简。
最后,在购物车显示页面listcart.jsp中还要写入以下JavaScript代码:
在这里插入图片描述
不然的话,用户手贱,不小心清空了购物车,辛辛苦苦购买的商品又要重新购买,用户的感受肯定巨不爽,所以在用户不小心清空了购物车时,还要询问用户是否确认清空。只有用户点击确认按钮才会清空,这样对用户来说,体验会更好。
还有一点要注意:如果用户清空了购物车,那么购物车显示页面不能没有任何显示,这也是对用户体验的一种折磨,明智的做法应该是给用户显示您没有购买任何商品!!!,这样用户体验会更好。那怎样判断用户有没有购买商品呢?可使用el表达式中的empty(object)函数:检测object对象是否为null或”“,若是则返回true。这样,购物车显示页面listcart.jsp中的关键代码如下:
在这里插入图片描述
至此,清空购物车的功能就算是开发完成了!下面测试一下开发好的该功能。
在这里插入图片描述

开发改变购物车某购物项数量的功能

在现实中的购物中,当用户购买一件商品时,发现还需要购买这件商品,比如数量为100,用户不可能点击这件商品100次,若是这样,那这样的购物网站倒闭1万亿遍了。所以一般来说用户只需要改变其数量即可,这时就需要用到<input>控件,而且用户要输入的数量要是一个正整数,不能是其他乱七八糟的东西。
在BusinessService类中实现如下业务服务的功能:

  • 改变购物车某购物项的数量

此时,BusinessService类的具体代码如下:

package cn.liayun.service;

import java.util.Map;

import cn.liayun.dao.BookDao;
import cn.liayun.domain.Book;
import cn.liayun.domain.Cart;
import cn.liayun.domain.CartItem;

//业务类,统一对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));
	}
	
}

接着,在cn.liayun.web.controller中创建一个ChangeQuantityServlet,该Servlet的具体代码如下:

package cn.liayun.web.controller;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import cn.liayun.domain.Cart;
import cn.liayun.service.BusinessService;

//把购物车中的某本书修改为指定的数量
@WebServlet("/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 {
		// TODO Auto-generated method stub
		doGet(request, response);
	}

}

注意:我上面的代码使用的是请求转发,这依然是不行的,读者要注意了啊!仍然要使用请求重定向,考虑到这毕竟不是一个真实项目,所以尽量不要搞得那么复杂,一切从简。
最后,在购物车显示页面listcart.jsp中还要写入以下JavaScript代码:
在这里插入图片描述
完整的购物车显示页面listcart.jsp前面已经给出了,这里不再赘写。
至此,改变购物车某购物项数量的功能就算是开发完成了!下面测试一下开发好的该功能。
在这里插入图片描述

附录(附下载链接)

百度网盘链接:https://pan.baidu.com/s/19wz_2t7FT9ZSxzykwfmzeA,提取码:tj5y。

展开阅读全文

没有更多推荐了,返回首页