JavaWeb书城项目(三)

  • 7、购物车
  • 7.1、购物车模块分析
  • 7.2、购物车模型编写
  • 7.3、加入购物车功能的实现
  • 7.4、购物车的展示
  • 7.5、删除购物车商品项
  • 7.6、清空购物车
  • 7.7、修改购物车商品数量
  • 7.8、 首页,购物车数据回显
  • 8、订单
  • 8.1、订单模块的分析
  • 8.2、创建订单模块的数据库表
  • 8.3、创建订单模块的数据模型
  • 8.4、编写订单模块的 Dao 程序
  • 8.5、编写订单模块的 Service
  • 8.6、编写订单模块的 web 层和页面联调


7、购物车

7.1、购物车模块分析

注意: 本模块中讲解的是将购物车信息保存到 session 域中,不涉及到数据库,也就没有 DAO 层、Service 层)

购物车模型可以参考分页的时候的 Page 模型

首先要有一个 购物车对象 Cart ,包含以下部分:

  • totalCount:总商品数量
  • totalPrice:购物车商品总金额
  • items:购物车的商品,是一个集合,里面包含商品项对象 CartItem

但是对于 items 这里和分页模型有些许不同,分页里面只需要把具体的商品对象列出来即可,但是购物车这里要显示商品的订购数量

所以还要有一个购物车商品项对象 CartItem ,包含如下内容:

  • id:商品编号
  • name:商品名称
  • count:商品数量
  • price:商品单价
  • totalPrice:单类商品总价

购物车部分类似于分页部分,可以被应用到各个地方

springboot购物车功能 javaweb购物车_jquery


分析购物车的功能 web 层:

  1. 加入购物车
    addItem()
  2. 删除商品项,删除整个类别的商品
    deleteItem()
  3. 清空购物车
    clear()
  4. 修改购物车中商品数量
    updateCount()

由于本模块没有 Service 层、DAO 层,所以上面的方法声明在 购物车对象 Cart 里面

  • addItem( CartItem ) 添加商品项
  • deleteItem( id ) 删除商品项
  • clear() 清空购物车
  • updateCount( id ,count ) 修改商品数量

结账的功能一般属于订单模块,因为要生成订单列表

每个模块都有自己的 servlet 程序,所以这里要新建 CartServlet ,继承于 BaseServlet

7.2、购物车模型编写

购物车商品项对象 CartItem

public class CartItem {
    private Integer id;
    private String name;
    private Integer count;
    private BigDecimal price;
    private BigDecimal totalPrice;
}

购物车对象 Cart

注意:此类中不需要生成构造器,因为后面不会被使用,只需要生成 get、set、toString() 方法

还要注意,对于 totalCount、totalPrice 这两个属性不应该被赋值,应该是从 items 的所有商品的总金额、总数量累加得来,所以注意这两个属性只可以有 get() 方法,没有 set() 方法

注意要更改toString()方法,不然无法无法更新到这两个值

而在get()方法里面,需要先给一个初始值,不然调用的时候会报空指针异常

既然在方法里面给了初始值,不防就不显式的定义这两个属性,直接只提供两个 get() 方法

public class Cart {
    //private Integer totalCount;
    //private BigDecimal totalPrice;
    //private List<CartItem> items = new ArrayList<>();
    //为方便确认集合里面的购物车商品项对象是否已经存在,items 可以设置为 Map 键值对式
    //key 为 CartItem 的 id 商品编号,value 为 CartItem 对象
    private Map<Integer,CartItem> items = new LinkedHashMap<>();
    
    public Integer getTotalCount() {
        //要先初始化值,不然会有空指针异常
        Integer totalCount = 0;
        for (CartItem cartItem : items.values()) {
            totalCount += cartItem.getCount();
        }
        return totalCount;
    }
    public BigDecimal getTotalPrice() {
        //要先初始化值,不然会有空指针异常
        BigDecimal totalPrice = new BigDecimal(0);
        for (CartItem cartItem : items.values()) {
            totalPrice = totalPrice.add(cartItem.getTotalPrice());
        }
        return totalPrice;
    }
   
    @Override
    public String toString() {
        return "Cart{" +
                "totalCount=" + getTotalCount() +
                ", totalPrice=" + getTotalPrice() +
                ", items=" + items +
                '}';
    } 
}

在购物车对象 Cart 中声明方法,完成增删改清空的操作

1、addItem( CartItem ) 添加商品项

注意在添加购物车的时候,要先查看购物车中是否已经添加过此商品
如果已添加,那就只需要让数量累加、总金额更新;
如果没添加过,才在集合中添加元素

而为了更好地在 items 里面根据 CartItem 的 id 判断是否已经存在,items 就定义为 Map 键值对式,key 为 CartItem 的 id ,value 为 CartItem 对象

如果 items 定义为 List 类型,那么判断是否存在还需要对集合进行遍历

public class Cart {
    //添加商品项
    public void addItem(CartItem cartItem){
        //查看购物车中是否已经存在此商品
        CartItem ci = items.get(cartItem.getId());
        if(ci == null){
            //之前没有添加过
            items.put(cartItem.getId(),cartItem);
        }else{
            //已经添加过的情况,购物车中商品项对象的数量、总金额需要变化
            ci.setCount(ci.getCount() + 1);
            //总金额 = 新的数量 * 单价
            //涉及到财务数据,使用 BigDecimal 中的 multiply 乘法,里面需要传入BigDecimal类型
            ci.setTotalPrice(ci.getPrice().multiply(new BigDecimal(ci.getCount())));
        }
    }
}

2、deleteItem( id) 删除商品项

public class Cart {
    //删除商品项
    public void deleteItem(Integer id){
        items.remove(id);
    }
}

3、clear() 清空购物车

public class Cart {
    //清空购物车
    public void clear(){
        items.clear();
    }
}

4、updateCount( id ,count ) 修改商品数量

先查看购物车中是否已经存在此商品,如果有,就修改商品数量,更新总金额

public class Cart {
    //修改商品数量
    public void updateCount(Integer id,Integer count){
        //查看购物车中是否已经存在此商品
        CartItem cartItem = items.get(id);
        if(cartItem != null){
            //已经存在此商品,修改商品项的数量、总金额
            cartItem.setCount(count);  //修改商品数量
            cartItem.setTotalPrice(cartItem.getPrice().multiply(new BigDecimal(cartItem.getCount())));   //修改商品总金额
        }
    }
}

7.3、加入购物车功能的实现

因为添加商品进购物车,需要用到商品编号

在按钮部分,将当前操作的图书的编号封装进自定义属性

springboot购物车功能 javaweb购物车_java_02


在单击事件中获取到商品的编号,使用 jQuery 的方法 attr(),传入一个参数是获取属性值,传入两个参数就是设置属性的值

注意,这里获取 id 值的时候,一定是 ${this}的对象来获取的,在事件响应的 function 函数 中,有一个 this 对象,这个 this 对象,是当前正在响应事件的 dom 对象

$(function () {
	//加入购物车按钮,绑定单击事件
	$("button.addToCart").click(function () {
		//在单击事件中获取到商品的编号
		// 使用 attr(),传入一个参数是获取属性值,传入两个参数就是设置属性的值
		//在事件响应的 function 函数 中,有一个 this 对象,这个 this 对象,是当前正在响应事件的 dom 对象
		var bid = $(this).attr("bbid");
		//basePath 是动态base标签部分定义的变量,在分页中 跳转到指定页数 也用到过
		location.href = "${basePath}cartServlet?methodName=addItem&id=" + bid;
	})
})

如果是像下图一样,使用 class 属性来定位 按钮标签

springboot购物车功能 javaweb购物车_java_03

那么获取到的编号 id 永远是 1

springboot购物车功能 javaweb购物车_java_04

CartServlet 程序中的步骤:

  1. 获取请求的参数:商品编号
  2. 调用 BookServiceImpl.queryBookById() ,得到图书信息
  3. 根据图书信息,生成购物车商品项对象 CartItem
  4. 调用 Cart.addItem(cartItem) ,添加商品项
    注意,这里需要创建 Cart 对象,但若是每次点击 “ 加入购物车 ”都会重建新的 Cart 对象的话,那么购物车的东西永远都多不起来,所以需要判断
    本项目是将购物车信息保存到 session 域中
  5. 请求重定向回到商品列表
    回到商品列表的时候需要回到当时点击按钮的那一页
    此时第一反应是想得到按钮所在的当前页对象,并将其作为请求参数发给 CartServlet 程序
    在 HTTP 协议中有个请求头 Referer ,它会在请求发起的时候(点击按钮的时候),将浏览器的地址发送给服务器,那么我们只需要拿到这个地址,然后请求重定向回到这个地址即可

springboot购物车功能 javaweb购物车_springboot购物车功能_05

public class CartServlet extends BaseServlet {
    private BookServiceImpl bookService = new BookServiceImpl();
    //加入购物车
    public void addItem(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //获取请求的参数:商品编号,本项目中也就是图书编号
        int id = WebUtils.parseInt(request.getParameter("id"), 0);
        //调用 BookServiceImpl.queryBookById() ,得到图书信息
        Book book = bookService.queryBookById(id);
        //根据图书信息,生成购物车商品项对象 CartItem
        CartItem cartItem = new CartItem(book.getId(), book.getName(), 1, book.getPrice(), book.getPrice());
        //调用 Cart.addItem(cartItem) ,添加商品项
        //注意这里,每次都创建新的购物车的话,里面的内容就没法都保存下来
//        Cart cart = new Cart();
        //本项目讲解的是将购物车信息保存到 session 域中
        //保证每次使用的都是一个购物车,不是每次请求添加就都是新的购物车
        Cart cart = (Cart) request.getSession().getAttribute("cart");
        if(cart == null){
            cart = new Cart();
            request.getSession().setAttribute("cart",cart);
        }
        cart.addItem(cartItem);
        //请求重定向回到商品列表中按钮点击发起请求的页面
        response.sendRedirect(request.getHeader("Referer"));
    }
}

注意:

  1. 本项目是将购物车信息 Cart 对象保存到 session 域中
  2. 使用请求头信息 Referer ,来获取请求发起时候的地址,最后请求重定向回到该地址

7.4、购物车的展示

需要在购物车页面展示购物车商品信息,一般在 jsp 页面使用数据的时候,就要想到使用 Servlet 程序处理数据,然后请求转发到 jsp 页面中

但是本项目在此处,在进行添加操作的时候,已经将购物车对象放进了 session 域中,所以展示购物车商品信息不需要经过 Servlet 程序,直接获取 session 域中数据 ${sessionScope.cart}

springboot购物车功能 javaweb购物车_javascript_06

在购物车页面下方的去结账超链接部分,如果购物车没有数据就不显示,判断一下 session 域中的 items 是否为空即可

springboot购物车功能 javaweb购物车_java_07

购物车没有数据,在页面显示提示信息【亲,当前购物车为空!快跟小伙伴们去浏览商品吧!!!】

<table>
	<tr>
		<td>商品名称</td>
		<td>数量</td>
		<td>单价</td>
		<td>金额</td>
		<td>操作</td>
	</tr>
	<%--如果购物车空的情况--%>
	<c:if test="${empty sessionScope.cart.items}">
		<tr>
				<%--跨列表格--%>
			<td colspan="5"><a href="${basePath}">亲,当前购物车为空!快跟小伙伴们去浏览商品吧!!!</a></td>
		</tr>
	</c:if>
	<%--如果购物车非空的情况--%>
	<c:if test="${not empty sessionScope.cart.items}">
		<%--使用 JSTL 标签对 Map 进行遍历--%>
		<c:forEach items="${sessionScope.cart.items}" var="entry">
			<tr>
				<td>${entry.value.name}</td>
				<td>${entry.value.count}</td>
				<td>${entry.value.price}</td>
				<td>${entry.value.totalPrice}</td>
				<td><a class="deletefromcart" href="cartServlet?methodName=deleteItem&id=${entry.value.id}">删除</a></td>
			</tr>
		</c:forEach>
	</c:if>
</table>
<%--如果购物车非空才输出页面的内容--%>
<c:if test="${not empty sessionScope.cart.items}">
	<div class="cart_info">
		<span class="cart_span">购物车中共有<span class="b_count">${sessionScope.cart.totalCount}</span>件商品</span>
		<span class="cart_span">总金额<span class="b_price">${sessionScope.cart.totalPrice}</span>元</span>
		<span class="cart_span"><a href="#">清空购物车</a></span>
		<span class="cart_span"><a href="pages/cart/checkout.jsp">去结账</a></span>
	</div>
</c:if>

7.5、删除购物车商品项

CartServlet 程序

public class CartServlet extends BaseServlet {
    private BookServiceImpl bookService = new BookServiceImpl();
    //删除购物车商品项
    protected void deleteItem(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //获取请求的参数:商品编号,本项目中也就是图书编号
        int id = WebUtils.parseInt(request.getParameter("id"), 0);
        //获取前购物车信息
        Cart cart = (Cart) request.getSession().getAttribute("cart");
        if(cart != null){
            cart.deleteItem(id);
        }
        //请求重定向回到商品列表中按钮点击发起请求的页面
        response.sendRedirect(request.getHeader("Referer"));
    }
}

购物车/pages/cart/cart.jsp 页面的代码:

删除的请求地址:

springboot购物车功能 javaweb购物车_jquery_08


删除的确认提示操作:

<script type="text/javascript">
		$(function () {
			//给删除超链接绑定单击事件,用于弹出提示信息
			$("a.deletefromcart").click(function () {
				return confirm("确定删除【"+$(this).parent().parent().children("td").first().text()+"】吗?")
			})
		})
	</script>

springboot购物车功能 javaweb购物车_springboot购物车功能_09

7.6、清空购物车

CartServlet 程序

public class CartServlet extends BaseServlet {
    private BookServiceImpl bookService = new BookServiceImpl();
    //清空购物车
    protected void clear(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //获取前购物车信息
        Cart cart = (Cart) request.getSession().getAttribute("cart");
        if(cart != null){
            cart.clear();
        }
        //请求重定向回到商品列表中按钮点击发起请求的页面
        response.sendRedirect(request.getHeader("Referer"));
    }
}

cart.jsp 页面的内容

给清空购物车添加请求地址,和添加 id 属性:

springboot购物车功能 javaweb购物车_ci_10

清空的确认提示操作:

<script type="text/javascript">
	$(function () {
		//给清空购物车绑定单击事件
		$("#clearcart").click(function () {
			return confirm("你确定要清空购物车吗?")
		})
	})
</script>

7.7、修改购物车商品数量

springboot购物车功能 javaweb购物车_springboot购物车功能_11


CartServlet 程序

public class CartServlet extends BaseServlet {
    private BookServiceImpl bookService = new BookServiceImpl();
    //修改购物车商品数量
    protected void updateCount(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        int id = WebUtils.parseInt(request.getParameter("id"), 0);
        int count = WebUtils.parseInt(request.getParameter("count"), 1);
        //获取前购物车信息
        Cart cart = (Cart) request.getSession().getAttribute("cart");
        if(cart != null){
            cart.updateCount(id,count);
        }
        //请求重定向回到商品列表中按钮点击发起请求的页面
        response.sendRedirect(request.getHeader("Referer"));
    }
}

修改 pages/cart/cart.jsp 购物车页面

springboot购物车功能 javaweb购物车_springboot购物车功能_12


修改商品数量 js 代码:

给数量的输入框绑定事件,来实现输入数量之后,鼠标移向其他地方,数量的修改就生效

第一可能考虑到 失去焦点事件,但是需要判断用户输入的数量与之前的数量相比是否有变化,没有变化就不需要进行修改

所以这里使用 内容发生改变事件,当输入框的内容发生改变的时候,就触发事件

$(".updateCount").change(function () {
	var name = $(this).parent().parent().find("td:first").text();
	var count = $(this).val();
	var bbbid = $(this).attr("bbbid");
	if(confirm("你确定要修改【"+ name +"】的数量为【"+ count +"】吗?")){
		location.href = "${basePath}cartServlet?methodName=updateCount&count="+count+"&id="+bbbid;
	}else {
		//用户不想更换数量,让输入框还原到之前的数字
		// defaultValue 属性是表单项 Dom 对象的属性。它表示默认的 value 属性
		this.value = this.defaultValue;
	}
})

7.8、 首页,购物车数据回显

在添加商品到购物车的时候,保存最后一个添加的商品名称:

springboot购物车功能 javaweb购物车_springboot购物车功能_13


在 pages/client/index.jsp 页面中输出购物车信息:

判断一下购物车是否为空

<div style="text-align: center">
	<%--购物车为空的输出--%>
	<c:if test="${empty sessionScope.cart.items}">
		<span> </span>
		<div>
			<span style="color: red">当前购物车为空</span>
		</div>
	</c:if>
		<%--购物车非空的输出--%>
		<c:if test="${not empty sessionScope.cart.items}">
			<span>您的购物车中有${sessionScope.cart.totalCount}件商品</span>
			<div>
				您刚刚将<span style="color: red">${sessionScope.cartItemName}</span>加入到了购物车中
			</div>
		</c:if>
</div>

8、订单

8.1、订单模块的分析

后台管理有管理订单页面

springboot购物车功能 javaweb购物车_jquery_14


前台用户有我的订单页面

springboot购物车功能 javaweb购物车_jquery_15

springboot购物车功能 javaweb购物车_jquery_16


分析订单的功能,然后一个功能对于着 Servlet 程序里面的一个方法

Servlet 程序李曼的方法对应着 Service 层里面的方法

Service 层里面的方法需要使用数据库的地方,就用到 DAO

DAO 层是一个 JavaBean,对应着一个 DAO
(所以本模块中有两个 DAO )

8.2、创建订单模块的数据库表

use book;
create table t_order(
	`order_id` varchar(50) primary key,
	`create_time` datetime,
	`price` decimal(11,2),
	`status` int,
	`user_id` int,
	foreign key(`user_id`) references t_user(`id`)
);
create table t_order_item(
	`id` int primary key auto_increment,
	`name` varchar(100),
	`count` int,
	`price` decimal(11,2),
	`total_price` decimal(11,2),
	`order_id` varchar(50),
	foreign key(`order_id`) references t_order(`order_id`)
);

8.3、创建订单模块的数据模型

由订单的界面,分析订单的模型:
一个对应订单的管理,需要创建 JavaBean、数据库
一个对应订单内部详情,包含着商品信息,需要创建 JavaBean、数据库

public class Order {
    //订单编号
    private String orderId;
    //订购时间
    private Date createTime;
    //发货状态:0 未发货,1 已发货,2 表示已签收
    private Integer status = 0;
    //用户编号
    private Integer userId;
    private BigDecimal price;
}
public class OrderItem {
    private Integer id;
    //订单编号
    private String orderId;
    //单价
    private BigDecimal price;
    //总价
    private BigDecimal totalPrice;
    private String name;
    private Integer count;
}

8.4、编写订单模块的 Dao 程序

DAO 层是一个 JavaBean,对应着一个 DAO
(所以本模块中有两个 DAO )

OrderDAO 接口

public interface OrderDAO {
    //生成订单的时候,将信息保存到数据库中
    void saveOrder(Order order);
    //用户查询订单
    List<Order> queryOrderByUserId(int userId);
    //根据订单号查询订单
    Order queryOrderByOrderId(String orderId);
    //查看所有订单
    List<Order> queryAllOrder();
    //更改发货状态
    void changeOrderStatus(String orderId,int newStatus);
}

OrderDAO 实现

public class OrderDAOImpl extends BaseDAO<Order> implements OrderDAO{
    @Override
    public void saveOrder(Order order) {
        //生成订单的时候,将信息保存到数据库中
        Connection conn = jdbcUtils.getconn();
        String sql = "INSERT INTO `t_order`(`order_id`,`create_time`,`price`,`status`,`user_id`) VALUES(?,?,?,?,?);";
        update(conn,sql,order.getOrderId(),order.getCreateTime(),order.getPrice(),order.getStatus(),order.getUserId());
        jdbcUtils.close(conn);
    }
    @Override
    public List<Order> queryOrderByUserId(int userId) {
        //用户查询订单
        Connection conn = jdbcUtils.getconn();
        String sql = "SELECT `order_id` orderId,`create_time` createTime,`price`,`status`,`user_id` userId FROM `t_order` WHERE `user_id` = ?;";
        List<Order> orders = queryForList(conn, sql, userId);
        jdbcUtils.close(conn);
        return orders;
    }
    @Override
    public Order queryOrderByOrderId(String orderId) {
        //根据订单号查询订单
        Connection conn = jdbcUtils.getconn();
        String sql = "SELECT `order_id` orderId,`create_time` createTime,`price`,`status`,`user_id` userId FROM `t_order` WHERE `order_id` = ?;";
        Order order = queryForOne(conn, sql, orderId);
        jdbcUtils.close(conn);
        return order;
    }
    @Override
    public List<Order> queryAllOrder() {
        //查看所有订单
        Connection conn = jdbcUtils.getconn();
        String sql = "SELECT `order_id` orderId,`create_time` createTime,`price`,`status`,`user_id` userId FROM `t_order`;";
        List<Order> orders = queryForList(conn, sql);
        jdbcUtils.close(conn);
        return orders;
    }
    @Override
    public void changeOrderStatus(String orderId, int newStatus) {
        //更改发货状态
        Connection conn = jdbcUtils.getconn();
        String sql = "UPDATE `t_order` SET `status`=? WHERE `order_id`=?;";
        update(conn,sql,newStatus,orderId);
        jdbcUtils.close(conn);
    }
}

OrderItemDAO 接口

public interface OrderItemDAO {
    //生成订单的时候,将信息保存到数据库中
    void saveOrderItem(OrderItem orderItem);
    //查看订单详情
    List<OrderItem> queryOrderItem(String orderId);
}

OrderItemDAO 实现

public class OrderItemDAOImpl extends BaseDAO<OrderItem> implements OrderItemDAO {
    @Override
    public void saveOrderItem(OrderItem orderItem) {
        //生成订单的时候,将信息保存到数据库中
        Connection conn = jdbcUtils.getconn();
        String sql = "INSERT INTO `t_orderitem`(`name`,`count`,`price`,`total_price`,`order_id`) VALUES(?,?,?,?,?);";
        update(conn,sql,orderItem.getName(),orderItem.getCount(),orderItem.getPrice(),orderItem.getTotalPrice(),orderItem.getOrderId());
        jdbcUtils.close(conn);
    }

    @Override
    public List<OrderItem> queryOrderItem(String orderId) {
        //查看订单详情
        Connection conn = jdbcUtils.getconn();
        String sql = "SELECT `id`,`name`,`count`,`price`,`total_price` totalPrice,`order_id` orderId FROM `t_orderitem` WHERE `order_id`=?;";
        List<OrderItem> orderItems = queryForList(conn, sql, orderId);
        jdbcUtils.close(conn);
        return orderItems;
    }
}

8.5、编写订单模块的 Service

OrderService 接口

public interface OrderService {
    //生成订单,返回订单号
    String createOrder(Cart cart, Integer userId);
    //查询所有订单
    List<Order> showAllOrders();
    //管理员发货
    void sendOrder(String orderId);
    //查看订单详情
    List<OrderItem> queryOrderDetail(String orderId);
    //用户查看我的所有订单
    List<Order> showMyOrders(Integer userId);
    //用户签收订单
    void receiveOrder(String orderId);
}

OrderService 实现类

public class OrderServiceImpl implements OrderService {
    private OrderDAOImpl orderDAOImpl= new OrderDAOImpl();
    private OrderItemDAOImpl orderItemDAOImpl= new OrderItemDAOImpl();

    @Override
    public String createOrder(Cart cart, Integer userId) {
        //生成订单,返回订单号
        // 订单号 ===> 唯一性
        String orderId = System.currentTimeMillis()+""+userId;
        Order order = new Order(orderId,new Date(),0,userId,cart.getTotalPrice());
        orderDAOImpl.saveOrder(order);
        for (CartItem cartItem : cart.getItems().values()) {
            OrderItem orderItem = new OrderItem(null,orderId,cartItem.getName(),cartItem.getCount(),cartItem.getPrice(),cartItem.getTotalPrice());
            orderItemDAOImpl.saveOrderItem(orderItem);
            //当购物车的数据生成订单之后,商品的销量和库存要发生变化
            Book book = new BookServiceImpl().queryBookById(cartItem.getId());
            book.setSales(book.getSales() + cartItem.getCount());
            book.setStock(book.getStock() - cartItem.getCount());     //应该要在某处判断订购的数量不会超过库存数量
            //BookServiceImpl 是 Book 的service层,执行更新的结果是变动数据库的数据
            new BookServiceImpl().updateBook(book);
        }
        //当购物车的数据生成订单之后,要清空购物车
        cart.clear();
        return orderId;
    }

    @Override
    public List<Order> showAllOrders() {
        //查询所有订单
        List<Order> orders = orderDAOImpl.queryAllOrder();
        return orders;
    }

    @Override
    public void sendOrder(String orderId) {
        //管理员发货
        //判断发货状态
        Order order = orderDAOImpl.queryOrderByOrderId(orderId);
        if(order.getStatus() == 0){
            orderDAOImpl.changeOrderStatus(orderId,1);
            System.out.println("管理员发货成功");
        }else {
            System.out.println("管理员发货失败,订单发货状态异常");
        }
    }

    @Override
    public List<OrderItem> queryOrderDetail(String orderId) {
        //查看订单详情
        List<OrderItem> orderItems = orderItemDAOImpl.queryOrderItem(orderId);
        return orderItems;
    }

    @Override
    public List<Order> showMyOrders(Integer userId) {
        //用户查看我的所有订单
        List<Order> orders = orderDAOImpl.queryOrderByUserId(userId);
        return orders;
    }

    @Override
    public void receiveOrder(String orderId) {
        //用户签收订单
        //判断发货状态
        Order order = orderDAOImpl.queryOrderByOrderId(orderId);
        if(order.getStatus() == 1){
            orderDAOImpl.changeOrderStatus(orderId,2);
            System.out.println("用户签收成功");
        }else {
            System.out.println("用户签收失败,订单发货状态异常");
        }
    }
}

8.6、编写订单模块的 web 层和页面联调

如果直接请求重定向的地址如下:

response.sendRedirect("/pages/user/login.jsp");

则页面显示如下:

springboot购物车功能 javaweb购物车_jquery_17


缺少工程名

所以应该是:

response.sendRedirect(request.getContextPath()+"/pages/user/login.jsp");

OrderServlet 程序:

public class OrderServlet extends BaseServlet {
    private OrderServiceImpl orderServiceImpl = new OrderServiceImpl();
    //生成订单
    protected void createOrder(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        Cart cart = (Cart) request.getSession().getAttribute("cart");
        User user = (User) request.getSession().getAttribute("user");
        //如果用户没有登录,跳转到登录页面
        if(user == null){
            response.sendRedirect(request.getContextPath()+"/pages/user/login.jsp");
            //页面跳转之后就不可以再执行其他语句
            return;
        }
        String orderId = orderServiceImpl.createOrder(cart, user.getId());
        //如果这里使用请求转发,那么当 F5 刷新浏览器的时候,又会执行一遍 “ 生成订单 ” 操作
//        request.setAttribute("orderId",orderId);
//        request.getRequestDispatcher("/pages/cart/checkout.jsp").forward(request,response);
        request.getSession().setAttribute("orderId",orderId);
        response.sendRedirect(request.getContextPath()+"/pages/cart/checkout.jsp");
    }
    //查询所有订单
    protected void showAllOrders(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        List<Order> orders = orderServiceImpl.showAllOrders();
        request.setAttribute("AllOrders",orders);
        request.getRequestDispatcher("/pages/manager/order_manager.jsp").forward(request,response);
    }
    //管理员发货
    protected void sendOrder(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        orderServiceImpl.sendOrder(request.getParameter("orderId"));
        response.sendRedirect(request.getContextPath()+"/orderServlet?methodName=showAllOrders");
    }
    //查看订单详情
    protected void queryOrderDetail(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        List<OrderItem> orderItem = orderServiceImpl.queryOrderDetail(request.getParameter("orderId"));
        request.setAttribute("orderItem",orderItem);
        request.getRequestDispatcher("/pages/order/order_items.jsp").forward(request,response);
    }
    //用户查看我的所有订单
    protected void showMyOrders(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        User user = (User) request.getSession().getAttribute("user");
        //如果用户没有登录,跳转到登录页面
        if(user == null){
            response.sendRedirect(request.getContextPath()+"/pages/user/login.jsp");
            //页面跳转之后就不可以再执行其他语句
            return;
        }
        List<Order> orders = orderServiceImpl.showMyOrders(user.getId());
        request.setAttribute("MyOrders",orders);
        request.getRequestDispatcher("/pages/order/order.jsp").forward(request,response);
    }
    //用户签收订单
    protected void receiveOrder(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        orderServiceImpl.receiveOrder(request.getParameter("orderId"));
        response.sendRedirect(request.getContextPath()+"/orderServlet?methodName=showMyOrders");
    }
}

修改 pages/cart/cart.jsp 页面,结账的请求地址:

springboot购物车功能 javaweb购物车_jquery_18


修改 pages/cart/checkout.jsp 页面,输出订单号:

springboot购物车功能 javaweb购物车_javascript_19


修改 pages/common/manager_menu.jsp 页面,订单管理的请求地址:

springboot购物车功能 javaweb购物车_ci_20

修改 pages/manager/order_manager.jsp 页面,查询所有订单:

<table>
	<tr>
		<td>日期</td>
		<td>金额</td>
		<td>详情</td>
		<td>发货</td>
	</tr>
	<c:forEach items="${requestScope.AllOrders}" var="order">
		<tr>
			<td>${order.createTime}</td>
			<td>${order.price}</td>
			<td><a href="orderServlet?methodName=queryOrderDetail&orderId=${sessionScope.orderId}">查看详情</a></td>
			<c:choose>
				<c:when test="${order.status == 0}">
					<td><a href="orderServlet?methodName=sendOrder&orderId=${sessionScope.orderId}">点击发货</a></td>
				</c:when>
				<c:when test="${order.status == 1}">
					<td>已发货</td>
				</c:when>
				<c:when test="${order.status == 2}">
					<td>已签收</td>
				</c:when>
			</c:choose>
		</tr>
	</c:forEach>
</table>

上面页面中的,管理员发货:

springboot购物车功能 javaweb购物车_springboot购物车功能_21


修改 pages/manager/order_manager.jsp 页面,修改 pages/order/order.jsp 页面,查看订单详情:

springboot购物车功能 javaweb购物车_java_22


修改 pages/client/index.jsp 页面,我的订单的请求地址:

springboot购物车功能 javaweb购物车_javascript_23


修改 pages/common/welcome_menu.jsp 页面,我的订单的请求地址:

springboot购物车功能 javaweb购物车_java_24


修改 pages/order/order.jsp 页面,我的订单页面:

<table>
	<tr>
		<td>日期</td>
		<td>金额</td>
		<td>状态</td>
		<td>详情</td>
	</tr>
	<c:forEach items="${requestScope.MyOrders}" var="order">
		<tr>
			<td>${order.createTime}</td>
			<td>${order.price}</td>
			<c:choose>
				<c:when test="${order.status == 0}">
					<td>未发货</td>
				</c:when>
				<c:when test="${order.status == 1}">
					<td><a href="orderServlet?methodName=receiveOrder&orderId=${sessionScope.orderId}">已发货,点击签收</a></td>
				</c:when>
				<c:when test="${order.status == 2}">
					<td>已签收</td>
				</c:when>
			</c:choose>
			<td><a href="orderServlet?methodName=queryOrderDetail&orderId=${sessionScope.orderId}">查看详情</a></td>
		</tr>
	</c:forEach>
</table>

上面页面中的,用户签收订单

springboot购物车功能 javaweb购物车_ci_25