JavaWeb商城订单模型+分页模型(JavaWeb+jsp+Ajax)

书城项目完整版:https://github.com/AsajuHuishi/bookStore

昨天实现了订单模型的全部基本功能,这里首先简单介绍订单模型,然后以订单模型的查看所有订单功能为例介绍分页模型,然后以发货功能为例介绍ajax局部更新页面,同时回顾我在写代码时遇到并解决的几个bug。

1. 订单模型

订单基本功能

订单模型的基本功能包括:

  • 生成订单(用户)
  • 查看所有订单(管理员)
  • 查看我的订单(用户)
  • 查看订单详情(管理员,用户)
  • 发货(管理员)
  • 签收(用户)

实体类和数据库表建立

建立订单类 Order:除了订单号,还包括根据用户结账的购物车信息获取商品总价,根据登录信息获得用户id(外键),根据结账时间获取建立订单的时间,以及一个唯一的订单号。
建立订单项类 OrderItem:一个购物车包含多个商品项,对应地,一个订单类有多个订单项,订单项的属性(商品id,名称,单价,购买数量,总价格)都来自购物车里的商品项。一个订单的多个订单项使用相同的订单号(外键)。

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`)
);

DESC t_order;

订单servlet

订单的servlet代码,这里的每一个方法对应上面的一个功能。

package indi.huishi.web;

import com.google.gson.Gson;
import indi.huishi.pojo.*;
import indi.huishi.service.OrderService;
import indi.huishi.service.impl.OrderServiceImpl;
import indi.huishi.utils.JdbcUtils;
import indi.huishi.utils.WebUtils;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.List;

public class OrderServlet extends BaseServlet{
    OrderService orderService = new OrderServiceImpl();
    /**
     * 去结账
     * @param req
     * @param resp
     * @throws ServletException
     * @throws IOException
     */
    protected void createOrder(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        System.out.println("结账");
        // cart和用户user都在session里
        User user = (User) req.getSession().getAttribute("user");
        // 如果User==null没有登录,转到登录页面
        if(user==null){
            req.getRequestDispatcher("/pages/user/login.jsp").forward(req,resp);
            return;
        }
//        System.out.println("OrderServlet当前线程"+Thread.currentThread().getName());
        Cart cart = (Cart) req.getSession().getAttribute("cart");
        if(cart!=null){
            // 使用事务
            String orderId = null;
            orderId = orderService.createOrder(cart, user.getId());
            req.getSession().setAttribute("orderId",orderId);
            resp.sendRedirect(req.getContextPath()+"/pages/cart/checkout.jsp");
        }
    }

    /**
     * 查询所有订单(未使用)
     * @param req
     * @param resp
     * @throws ServletException
     * @throws IOException
     */
    protected void showAllOrders(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//        System.out.println("查询所有订单");
        // 获得日期 金额 详情(订单项) 发货状态
        List<Order> orders = orderService.showAllOrders();
        req.setAttribute("orders",orders);
        // 请求转发
        req.getRequestDispatcher("/pages/manager/order_manager.jsp").forward(req,resp);
    }

    /**
     * 查询所有订单--分页
     * @param req
     * @param resp
     * @throws ServletException
     * @throws IOException
     */
    protected void showAllOrdersByPage(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("查询所有订单分页");
        // 获取当前页数和每页的条目数量
        int pageNo = WebUtils.parseInt(req.getParameter("pageNo"), 1);
        int pageSize = 4;
        // 生成当前页的对象
        Page<Order> page = orderService.page(pageNo, pageSize);
        // 将请求跳转页面(点击下一页跳回到本页)的地址写入url
        page.setUrl("orderServlet?action=showAllOrdersByPage");
        // 保存到请求域
        req.setAttribute("pageOrder",page);
        // 请求转发
        req.getRequestDispatcher("/pages/manager/order_manager.jsp").forward(req,resp);
    }

    /**
     * 查看订单详情
     * @param req
     * @param resp
     * @throws ServletException
     * @throws IOException
     */
    protected void showOrderDetail(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("查看订单详情...");
        // 获取订单id
        String orderId = req.getParameter("orderId");
        // 获取所有订单项
        List<OrderItem> orderItems = orderService.showOrderDetail(orderId);
        // 保存到请求域
        req.setAttribute("orderItems", orderItems);
        // 请求转发
        req.getRequestDispatcher("/pages/manager/order_manager_detail.jsp").forward(req,resp);
    }

    /**
     * 修改发货状态,发货
     * @param req
     * @param resp
     * @throws ServletException
     * @throws IOException
     */
    protected void sendOrder(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("修改发货状态...");
        // 获取订单id,当前状态
        String orderId = req.getParameter("orderId");
        String status = req.getParameter("status");
        int stat = WebUtils.parseInt(status, -1);
        // 结果
        if (stat!=0){
            resp.getWriter().write(new Gson().toJson("已发货"));
        } else{
            stat = 1;
            int res = orderService.updateStatus(orderId, stat);
            if (res!=0){
                System.out.println("发货成功");
                resp.getWriter().write(new Gson().toJson("发货成功 代签收"));
            }else{
                resp.getWriter().write(new Gson().toJson("发货失败"));
            }
        }
    }


    /**
     * 查看我的订单(分页)
     * @param req
     * @param resp
     * @throws ServletException
     * @throws IOException
     */
    protected void showMyOrder(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("查看我的订单");
        // 获取用户id 保存在Session域对象
        User user = (User)req.getSession().getAttribute("user");
        Integer userId = user.getId();
        // 获取当前页和每页条目数
        int pageNo = WebUtils.parseInt(req.getParameter("pageNo"),1);
        int pageSize = 4;
        // 分页查找该用户的订单
        Page<Order> orderPage = orderService.pageForMyOrder(userId, pageNo, pageSize);
        System.out.println(orderPage);
        // 将其保存到请求域
        req.setAttribute("pageOrder", orderPage);
        // 跳转到页面
        req.getRequestDispatcher("/pages/order/order.jsp").forward(req,resp);
    }

    /**
     * 修改订单状态:用户签收
     * @param req
     * @param resp
     * @throws ServletException
     * @throws IOException
     */
    protected void receiveOrder(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("用户签收");
        // 和商家发货一样,本质上还是获取订单id和发货状态
        String orderId = req.getParameter("orderId");
        // 获取发货状态status 正常应该是1(已发货才能签收)
        int status = WebUtils.parseInt(req.getParameter("status"), -1);
        if(status!=1){
            resp.getWriter().write(new Gson().toJson("状态异常,签收失败"));
        }else{
            status = status + 1;
            // 修改
            int result = orderService.updateStatus(orderId, status);
            if (result!=0){
                resp.getWriter().write(new Gson().toJson("已签收"));
            }else{
                resp.getWriter().write(new Gson().toJson("签收失败"));
            }
        }
    }
}


2. 分页模型实现显示全部订单

查看所有订单查看我的订单中,可能很多条记录,这里使用分页模型实现。
分页模型:建立Page类,属性包括每页显示的订单条目数pageSize,展示给用户的页数pageNo,在数据库中查询订单条目总数pageTotalCount,需要的总页数pagetotal,以及当前页的显示内容items。

package indi.huishi.pojo;

import java.util.List;

/**
 * 分页模型对象
 * @param <T>泛型是具体javaBean类
 */
public class Page<T> {

    //当前页显示数量
    public static Integer PAGE_SIZE=4;
    // 总页数
    private Integer pageTotal;
    // 总记录数
    private Integer pageTotalCount;
    // 当前页
    private Integer pageNo;
    // 当前页数据
    private List<T> items;



    // 分页条请求地址
    private String url;

    public Integer getPageTotal() {
        return pageTotal;
    }
    public String getUrl() {
        return url;
    }

    public void setUrl(String url) {
        this.url = url;
    }

    public void setPageTotal(Integer pageTotal) {
        this.pageTotal = pageTotal;
    }

    public Integer getPageTotalCount() {
        return pageTotalCount;
    }

    public void setPageTotalCount(Integer pageTotalCount) {
        this.pageTotalCount = pageTotalCount;
    }

    public Integer getPageNo() {
        return pageNo;
    }

    public void setPageNo(Integer pageNo) {
        // 数据边界有效检查
        // 如果页码小于1 就显示第一页
        if (pageNo < 1){
            pageNo = 1;
        }else if (pageNo > pageTotal){
            pageNo = pageTotal;
        }
        this.pageNo = pageNo;
    }

    public List<T> getItems() {
        return items;
    }

    public void setItems(List<T> items) {
        this.items = items;
    }

    public static Integer getPageSize() {
        return PAGE_SIZE;
    }
    public void setPageSize(Integer pageSize) {
        PAGE_SIZE = pageSize;
    }
}

分页service方法

以下以查看所有订单为例,其service层方法实现根据当前页数pageNo和每页显示条目数pageSize,获取该页的订单信息。首先创建Page类的对象,然后根据dao层方法查询得到pageTotal和items,给page所有属性赋值完成后,再返回给servlet。

    /**
     * 查看所有订单(分页)
     */
    @Override
    public Page<Order> page(int pageNo, int pageSize) {
        Page<Order> page = new Page<Order>();
        //设置5属性

        // 每页数量
        page.setPageSize(pageSize);
        // 总记录数
        Integer pageTotalCount = orderDao.queryForPageTotalCount();
        page.setPageTotalCount(pageTotalCount);
        // 总页码
        Integer pageTotal = pageTotalCount / pageSize;
        if (pageTotalCount % pageSize > 0){
            pageTotal++;
        }
        page.setPageTotal(pageTotal);
        // 当前页
        page.setPageNo(pageNo);

        // 当前页数据
        Integer begin = (pageNo-1)*pageSize;//开始索引
        List<Order> items = orderDao.queryForPageItems(begin,pageSize);
        page.setItems(items);

        return page;
    }

分页servlet方法

servlet获取用户要跳转的页数pageNo,以及固定的pageSize,调用service方法,service方法将查询好的page对象返回给servlet,将其保存到request域中(pageOrder),请求转发jsp。
这里的url属性是jsp页面上点击跳转页码时的访问当前servlet方法的路径,因为除了pageNo不同以外均相同,可以封装起来。

    /**
     * 查询所有订单--分页
     * @param req
     * @param resp
     * @throws ServletException
     * @throws IOException
     */
    protected void showAllOrdersByPage(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("查询所有订单分页");
        // 获取当前页数和每页的条目数量
        int pageNo = WebUtils.parseInt(req.getParameter("pageNo"), 1);
        int pageSize = 4;
        // 生成当前页的对象
        Page<Order> page = orderService.page(pageNo, pageSize);
        // 将请求跳转页面(点击下一页跳回到本页)的地址写入url
        page.setUrl("orderServlet?action=showAllOrdersByPage");
        // 保存到请求域
        req.setAttribute("pageOrder",page);
        // 请求转发
        req.getRequestDispatcher("/pages/manager/order_manager.jsp").forward(req,resp);
    }

jsp页面

jsp根据请求域中保存的pageOrder,使用jstl进行遍历,显示当前页面每个订单的信息。

	<div id="main">
		<table>
			<tr>
				<td>日期</td>
				<td>金额</td>
				<td>详情</td>
				<td>发货</td>
				
			</tr>
			<c:forEach items="${requestScope.pageOrder.items}" var="order">
			<tr>
				<td>${order.createTime}</td>
				<td>${order.price}</td>
				<td><a href="orderServlet?action=showOrderDetail&orderId=${order.orderId}">查看详情</a></td><%--根据 订单id 查看--%>
				<td><span>
						<input class="sendBtn" type="button" orderId="${order.orderId}" status="${order.status}" value="点击发货">
					</span>
				</td>
			</tr>
			</c:forEach>

		</table>
		<%--分页--%>
		<%@include file="/pages/common/page_order_naiv.jsp"%>
	</div>

在这里插入图片描述

这样显示全部订单的功能就完成了。但是我们希望“点击发货”按钮之后,这个位置会显示发货成功或失败的状态,这就是下面介绍的发货功能。


3. Ajax实现发货功能

接下来使用Ajax实现发货功能。
发货:订单有未发货、已发货、已签收三个状态,分别用0,1,2表示。在上面jsp的发货一栏,管理员可以选择点击发货,也就是更改订单的状态。通过“点击发货”按钮,servlet获取该订单的订单id以及当前的状态,在数据库更改该订单的状态(变成已发货状态),然后跳转到当前页面,将“点击发货”的按钮变成“发货成功,待签收”的提示。

jQuery的Ajax代码

因为只涉及页面局部的变化,使用Ajax可以方便的实现。这里需要注意在 Ajax里面无法直接使用$(this) ,需要先定义变量document保存$(this)。

	<script type="text/javascript">
		$(function (){
			$(".sendBtn").click(function(){/*修改发货*/
				var document = $(this);// ajax里面不能直接用$(this)
				// 点击发货
				var orderId = $(this).attr("orderId");
				var status = $(this).attr("status");
				// alert("ss"+status);
				$.getJSON("http://localhost:8080/07_book/orderServlet?action=sendOrder","orderId="+orderId+"&status="+status,function(data){
					// 传过来的是字符串
					// alert(document.parent().html())
					document.parent().html(data);//在按钮的位置写新的状态
				});
			});
		});
	</script>

servlet方法返回json字符串

json是一种轻量级的数据交换格式。如果发货成功,就传一个“发货成功 待签收”json字符串给客户端。浏览器接收到之后,点击发货按钮的位置会变成“发货成功 待签收”。

    protected void sendOrder(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("修改发货状态...");
        // 获取订单id,当前状态
        String orderId = req.getParameter("orderId");
        String status = req.getParameter("status");
        int stat = WebUtils.parseInt(status, -1);
        // 结果
        if (stat!=0){
            resp.getWriter().write(new Gson().toJson("已发货"));
        } else{
            stat = 1;
            int res = orderService.updateStatus(orderId, stat);
            if (res!=0){
                System.out.println("发货成功");
                resp.getWriter().write(new Gson().toJson("发货成功 待签收"));
            }else{
                resp.getWriter().write(new Gson().toJson("发货失败"));
            }
        }
    }

在这里插入图片描述

刷新页面的问题

如果此时刷新页面,就会重新显示“点击发货”按钮。刷新会重新请求查询所有订单方法,数据库内容(发货状态)发生了变化,所以请求域的page对象发生了变化,但jsp仍然是原来的“点击发货”按钮。
所以在jsp显示订单的时候,需要判断当前的发货状态来显示不同状态的内容,也就是用jstl的条件判断order.status。

	<div id="main">
		<table>
			<tr>
				<td>日期</td>
				<td>金额</td>
				<td>详情</td>
				<td>发货</td>
				
			</tr>
			<c:forEach items="${requestScope.pageOrder.items}" var="order">
			<tr>
				<td>${order.createTime}</td>
				<td>${order.price}</td>
				<td><a href="orderServlet?action=showOrderDetail&orderId=${order.orderId}">查看详情</a></td><%--根据 订单id 查看--%>
				<td><span class="sendOrder">
					<c:if test="${order.status==0}"><%--发货--%>
						<input class="sendBtn" type="button" orderId="${order.orderId}" status="${order.status}" value="点击发货">
					</c:if>
					<c:if test="${order.status==1}">
						发货成功 待签收
					</c:if>
					<c:if test="${order.status==2}">
						已签收
					</c:if>
					</span>
				</td>
			</tr>
			</c:forEach>

		</table>
		<%--分页--%>
		<%@include file="/pages/common/page_order_naiv.jsp"%>
	</div>
  • 2
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值