JavaWeb企业实战项目(四):订单模块

编程入门 行业动态 更新时间:2024-10-27 01:26:40

JavaWeb企业<a href=https://www.elefans.com/category/jswz/34/1769775.html style=实战项目(四):订单模块"/>

JavaWeb企业实战项目(四):订单模块

Web项目系列文章推荐:
👉 JavaWeb企业实战项目(一):环境搭建-用户注册-邮件发送
👉 JavaWeb企业实战项目(二):用户登录-首页详情-商品分类
👉 JavaWeb企业实战项目(三):商品模块
👉 JavaWeb企业实战项目(五):后台模块1
👉 JavaWeb企业实战项目(六):后台模块2
👉 待更新

文章目录

        • 1、任务总述
        • 2、订单模型抽取
        • 3、实现订单模块相关程序
        • 4、订单查询-原理分析
        • 5、实现订单详情查询
        • 6、支付功能-原理分析
        • 7、实现支付功能

1、任务总述

1、模型的抽取
2、提交订单
3、查询我的订单
4、订单详情
5、支付功能

2、订单模型抽取

订单: 对本次交易的记录和描述
分析超市小票:
会员ID:1231231
流水号:hrwj_ba_31_sy003_1002
交易时间:2017年3月10日08:41:53
商品名称 商品价格 商品数量 小计
 好日子  15     2    30
 芙蓉王  25     2    50
 黄鹤楼  15     3    45
 大前门  10     1    10
 总金额:135元

设计表,存储小票上的数据
会员id   流水号  交易时间  商品名称  商品价格  商品数量  小计  总金额
1231231  XXX    XXXX   好日子   15      2    30   135
1231231  XXX    XXXX   芙蓉王   25      2    50   135
1231231  XXX    XXXX   黄鹤楼   15      3    45   135
1231231  XXX    XXXX   大前门   10      1    10   135
弊端:数据冗余严重 DB原则:存储最少的数据,办更多的事情

用户表user(uid,username,password,name,birthday,telephone,state,code…)

一个表专注于交易描述,订单表 orders
订单id(流水号)  会员id  交易时间  总金额  收货人姓名  地址  电话  订单状态(1234)
1123      1231231  XXXX   135
1124      1234444  YYYY   200

orders表中的会员id列参照了用户表uid
订单状态:
买家:下单未付款,付款未发货,已发货,签收
卖家: 未付款,发货,未签收,已收货(结束)

一个表专注于每笔订单详细交易情况,订单项orderitem
订单项id  商品id  数量  小计  所在订单编号
001    p003   2   30    1123
002    p005   2   50    1123
003    p101   3   45    1123
004    p220   1   10    1123
005    p334   1   101    1124
006    p556   3   54    1124
007    p445   5   45    1124
orderitem表中的商品id参照了商品表的pid
orderitem表中的所在订单编号参照了订单表的订单id

提交订单原理分析:
用户点击提交订单,将购物车中的数据以订单/订单项形式保存下来,清空购物车

保存订单:
为订单表中插入一行数据,描述本次交易,这行数据部分数据是通过程序赋予,部分数据来自购物车的,部分数据来自session中的用户
oid:UUIDUtils orderTime:new Date(); total: 从购物车获取
state:1 address: null name:null telephone:null uid:从session中的用户获取

保存订单项:
向订单项表中插入数据,描述当前订单的详细的购买信息,部分数据来自于购物车,部分数据需要通过程序赋予
itemid: UUIDUtils quantity:来自于购物车中的购物项 total:来自于购物车中的购物项
pid:来自于购物车上的购物项下商品对象pid oid:来自于当前订单id

提交订单时,订单以及订单项必须同时成功(事务)

3、实现订单模块相关程序

实现目标:
OrderServlet OrderService OrderServiceImp OrderDao OrderDaoImp
Order{ User user, List list=new ArrayList(); …}
OrderItem{ Product product,Order order;}

步骤实现:
1、准备工作
  <a href="${pageContext.request.contextPath}/OrderServlet?method=saveOrder">
2、OrderServlet -> saveOrder

public String saveOrder(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {//确认用户登录状态User user = (User)request.getSession().getAttribute("userinfo");if(user==null){request.setAttribute("msg", "请在登录之后再下单!");return "/jsp/info.jsp";}Cart cart = (Cart)request.getSession().getAttribute("cart");//创建订单对象,为订单对象赋值Order order = new Order();order.setOid(UUIDUtils.getId());order.setState(1);order.setOrderTime(new Date());order.setTotal(cart.getTotalPrice());order.setUser(user);//遍历购物项的同时,创建订单项for (CartItem item: cart.getCartItems()) {OrderItem oitem = new OrderItem();oitem.setItemid(UUIDUtils.getCode());oitem.setQuantity(item.getNum());oitem.setTotal(item.getPrice());oitem.setProduct(item.getProduct());//设置当前的订单项属于哪个订单:程序的角度体检订单项和订单对应关系oitem.setOrder(order);order.getOrderitem().add(oitem);}//调用业务层功能:保存订单OrderService service = new OrderServiceImpl();//将订单数据,用户数据,订单下所有订单项都传递到了service层service.saveOrder(order);//清空购物车cart.clearCart();//将订单放入requestrequest.setAttribute("order", order);//转发/jsp/order_info.jspreturn "/jsp/order_info.jsp";
}

3、OrderService
  利用事务保存订单,订单项

@Override
public void saveOrder(Order order) {OrderDao dao = new OrderDaoImpl();try {JDBCUtils.startTransaction();dao.saveOrderAndItem(order);JDBCUtilsmitAndClose();} catch (SQLException e) {e.printStackTrace();JDBCUtils.rollbackAndClose();}
}

4、OrderDao

@Override
public void saveOrderAndItem(Order order) throws SQLException {String sql1 = "insert into orders values (?,?,?,?,?,?,?,?)";String sql2 = "insert into orderitem values (?,?,?,?,?)";QueryRunner qr = new QueryRunner(JDBCUtils.getDataSource());Object[] objs1 = {order.getOid(),order.getOrderTime(),order.getTotal(),order.getState(),order.getAddress(),order.getName(),order.getTelephone(),order.getUser().getUid()};List<OrderItem> orderitem = order.getOrderitem();qr.update(sql1,objs1);for (OrderItem item : orderitem) {Object[] objs2 = {item.getItemid(),item.getQuantity(),item.getTotal(),item.getProduct().getPid(),order.getOid()};qr.update(sql2,objs2);}
}

5、/jsp/order_info.jsp
  获取到订单信息(和之前一样,把对象抽取出来)
实现总结: 1、模型的抽取  2、业务层事务

4、订单查询-原理分析

注重软能力的提升

原理如下:

步骤实现:
1、准备工作
<a href="${pageContext.request.contextPath}/OrderServlet?method=findMyOrdersWithPage&num=1">我的订单</a>
2、OrderServlet__>findMyOrdersWithPage

public String findMyOrdersWithPage(HttpServletRequest request, HttpServletResponse response) throws Exception {//获取当前页数与session中的用户信息int curPage = Integer.parseInt(request.getParameter("num"));User user = (User)request.getSession().getAttribute("userinfo");//创建service对象并执行findMyOrdersWithPage函数OrderService service = new OrderServiceImpl();//返回的是一个List<Order>对象,保存了多个订单PageModel pm = service.findMyOrdersWithPage(user,curPage);//作用域保存对象,并转发order_list页面request.setAttribute("page", pm);return "/jsp/order_list.jsp";
}

3、OrderServiceImp

@Override
public PageModel findMyOrdersWithPage(User user, int curPage) throws Exception{//获取总数int count = dao.getCount(user);System.out.println("商品总述"+count);//生成pageModel对象PageModel pm = new PageModel(curPage,count,3);//关联集合List<Order> orders = dao.findMyOrdersWithPage(user,pm.getStartIndex(),pm.getPageSize());pm.setList(orders);//关联urlpm.setUrl("OrderServlet?method=findMyOrdersWithPage");return pm;
}

4、OrderDaoImp
  *_利用MapListHandler封装多表查询结果
  *_多表查询语句
  *_BeanUtils自动填充数据

@Override
public List<Order> findMyOrdersWithPage(User user, int startIndex, int pageSize) throws Exception {//实用limit实现分页查询String sql1 = "select * from orders where uid = ? limit ?,?";List<Order> orders = qr.query(sql1, new BeanListHandler<Order>(Order.class),user.getUid(),startIndex,pageSize);	//foreach循环orders对象for (Order o : orders) {//获得oid并编写sql2代码,其中查询为多表查询String oid = o.getOid();String sql2 = "select * from orderitem o,product p where o.pid=p.pid and o.oid = ?";//利用MapListHandler封装多表查询结果List<Map<String, Object>> map = qr.query(sql2, new MapListHandler(),oid);for (Map<String, Object> map2 : map) {OrderItem item = new OrderItem();Product product = new Product();// 1_创建时间类型的转换器DateConverter dt = new DateConverter();// 2_设置转换的格式dt.setPattern("yyyy-MM-dd");// 3_注册转换器ConvertUtils.register(dt, java.util.Date.class);//直接实用populate对对象进行封装,内部利用get函数与map键值匹配并赋值BeanUtils.populate(item, map2);BeanUtils.populate(product, map2);//完成item与product、order与item的关系item.setProduct(product);item.setOrder(o);o.getOrderitem().add(item);}}return orders;
}

5、实现/jsp/order_list.jsp 获取订单信息,完成响应

<strong>我的订单</strong>
<table class="table table-bordered"><c:if test="${empty page}"><h3>暂无订单</h3></c:if><c:forEach items="${page.list}" var="o"><tbody><tr class="success"><th colspan="5">订单编号:${o.oid} 总金额:¥${o.total}元<c:if test="${o.state==1}"><a href="${pageContext.request.contextPath}/OrderServlet?method=findOrderByOid&oid=${o.oid}">付款</a></c:if><c:if test="${o.state==2}">未发货</c:if><c:if test="${o.state==3}"><a href="#">签收</a></c:if><c:if test="${o.state==4}">已收货</c:if></th></tr><tr class="warning"><th>图片</th><th>商品</th><th>价格</th><th>数量</th><th>小计</th></tr><c:forEach items="${o.orderitem}" var="item"><tr class="active"><td width="60" width="40%"><input type="hidden" name="id" value="22"><img src="${pageContext.request.contextPath}/${item.product.pimage}" width="70" height="60"></td><td width="30%"><a target="_blank"> ${item.product.pname}</a></td><td width="20%">¥${item.product.shop_price}</td><td width="10%">${item.quantity}</td><td width="15%"><span class="subtotal">¥${item.total}</span></td></tr></c:forEach></tbody></c:forEach>
</table>

PS:遍历数据时,2个循环,大循环遍历订单,小循环遍历的是订单上的订单项

5、实现订单详情查询

原理如下:

步骤实现:
1、准备工作 order_list.jsp 修改连接
<a href="${pageContext.request.contextPath}/OrderServlet?method=findOrderByOid&oid=${o.oid}">付款</a>
2、OrderServlet -> findOrderByOid

public String findOrderByOid(HttpServletRequest request, HttpServletResponse response) throws Exception {//获取list页面传过来的oid参数String oid = request.getParameter("oid");//调用业务层功能:根据订单编号查询订单信息OrderService service = new OrderServiceImpl();Order order = service.findOrderByOid(oid);//将Order放入request作用域中并执行转发request.setAttribute("order", order);return "/jsp/order_info.jsp";
}

3、OrderService

return dao.findOrderByOid(oid);

4、OrderDaoImp
思路:
  根据订单oid查询当前订单
  根据订单oid查询订单下所有的订单项以及订单项关联的商品

@Override
public Order findOrderByOid(String oid) throws Exception {String sql = "select * from orders where oid = ?";Order order = qr.query(sql, new BeanHandler<Order>(Order.class),oid);sql = "select * from orderitem o,product p where o.pid=p.pid and o.oid = ?";//利用MapListHandler封装多表查询结果List<Map<String, Object>> map = qr.query(sql, new MapListHandler(),oid);for (Map<String, Object> map2 : map) {OrderItem item = new OrderItem();Product product = new Product();// 1_创建时间类型的转换器DateConverter dt = new DateConverter();// 2_设置转换的格式dt.setPattern("yyyy-MM-dd");// 3_注册转换器ConvertUtils.register(dt, java.util.Date.class);//直接实用populate对对象进行封装,内部利用get函数与map键值匹配并赋值BeanUtils.populate(item, map2);BeanUtils.populate(product, map2);//完成item与product、order与item的关系item.setProduct(product);item.setOrder(order);order.getOrderitem().add(item);}return order;
}

5、/jsp/order_info.jsp
开发中:多个功能对应同一个JSP页面,为了提高代码复用率,所有的功能在向同一个
    JSP页面转发的时候,向request存入相同的数据(属性名一致)

6、支付功能-原理分析

基础概念:
银行接口:
  优点:资金没有延时
  缺点:银行API发生变化,支付功能需要更改
第三方支付api:
  缺点:资金延时,收费
  优点:银行API发生变化,支付功能不需要更改
支付数据执行过程:

如何保证数据传输有效性:
张三和李四传输数据:
 原文:ABCDE
 算法:对原文中的每个字符的ASC码增加一个数字(公开)
 秘钥:增加的3(只有张三和李四知道)
 密文:CDEFG
张三向李四传递数据:ABCDE&CDEFG
李四获取到张三的数据之后:ABCDE利用算法和秘钥3对原文再次加密得到密文
比较得到的密文和获取到的密文是否一致,一致数据是合法的

加密算法:对称加密,非对称加密
对称加密:原文<----->密文
非对称加密:原文<----->密文

A公司实现电商项目,A公司需要拿着公司营业执照,银行账户各种资质证明,去易宝支付申请使用权限,易宝支付审核之后为A公司分配商户编号,秘钥

7、实现支付功能

原理如下:

步骤实现:
1、准备工作 /jsp/order_info.jsp
  //设置form表单(method,action,id)
  //设置form表单 input 标签的name属性 address name telephone
  //设置隐藏域 传递订单oid
  都是像以前的常规做法,不贴代码
2、OrderServlet___>payOrder
  //获取订单oid,收货人地址,姓名,电话,银行
  //更新订单上收货人的地址,姓名,电话
  //向易宝支付发送参数
  由于易宝支付已经挂了,想注册一个商户都注册不了,所以就直接完成支付

public String payOrder(HttpServletRequest request, HttpServletResponse response) throws Exception {//获取订单oid、收货人地址/电话/姓名/银行String oid = request.getParameter("oid");String name = request.getParameter("name");String telephone = request.getParameter("telephone");String address = request.getParameter("address");String pd_FrpId = request.getParameter("pd_FrpId");//调用业务层功能:更新订单上收货人的地址、姓名、电话OrderService service = new OrderServiceImpl();Order order = service.findOrderByOid(oid);order.setAddress(address);order.setTelephone(telephone);order.setName(name);order.setState(2);service.updateOrder(order);request.setAttribute("msg", "支付成功!订单号:" + oid + "&emsp;金额:" + order.getTotal());return "/jsp/info.jsp";/** 向易宝支付发送参数 **//*//把付款所需要的参数准备好:String p0_Cmd = "Buy";//商户编号String p1_MerId = "10001126856";//订单编号String p2_Order = oid;//金额String p3_Amt = "0.01";String p4_Cur = "CNY";String p5_Pid = "";String p6_Pcat = "";String p7_Pdesc = "";//接受响应参数的ServletString p8_Url = "http://localhost:8080/store_v5/OrderServlet?method=callBack";String p9_SAF = "";String pa_MP = "";String pr_NeedResponse = "1";//公司的秘钥String keyValue = "69cl522AV6q613Ii4W6u8K6XuW8vM1N6bFgyv769220IuYe9u37N4y7rI4Pl";//调用易宝的加密算法,对所有数据进行加密,返回电子签名String hmac = PaymentUtil.buildHmac(p0_Cmd, p1_MerId, p2_Order, p3_Amt, p4_Cur, p5_Pid, p6_Pcat, p7_Pdesc, p8_Url, p9_SAF, pa_MP, pd_FrpId, pr_NeedResponse, keyValue);StringBuffer sb = new StringBuffer("?");sb.append("p0_Cmd=").append(p0_Cmd).append("&");sb.append("p1_MerId=").append(p1_MerId).append("&");sb.append("p2_Order=").append(p2_Order).append("&");sb.append("p3_Amt=").append(p3_Amt).append("&");sb.append("p4_Cur=").append(p4_Cur).append("&");sb.append("p5_Pid=").append(p5_Pid).append("&");sb.append("p6_Pcat=").append(p6_Pcat).append("&");sb.append("p7_Pdesc=").append(p7_Pdesc).append("&");sb.append("p8_Url=").append(p8_Url).append("&");sb.append("p9_SAF=").append(p9_SAF).append("&");sb.append("pa_MP=").append(pa_MP).append("&");sb.append("pd_FrpId=").append(pd_FrpId).append("&");sb.append("pr_NeedResponse=").append(pr_NeedResponse).append("&");sb.append("hmac=").append(hmac);System.out.println(sb.toString());// 使用重定向:response.sendRedirect(sb.toString());*/
}

3、OrderServlet___>callBack
  //接收响应会的数据
  //确保数据有效性
  //更新订单状态
  //向request放入提示信息
  //转发到/jsp/info.jsp

/** 易宝支付GG,此功能作废!*/
public void callBack(HttpServletRequest request, HttpServletResponse response) throws Exception {// 验证请求来源和数据有效性// 阅读支付结果参数说明String p1_MerId = request.getParameter("p1_MerId");String r0_Cmd = request.getParameter("r0_Cmd");String r1_Code = request.getParameter("r1_Code");String r2_TrxId = request.getParameter("r2_TrxId");String r3_Amt = request.getParameter("r3_Amt");String r4_Cur = request.getParameter("r4_Cur");String r5_Pid = request.getParameter("r5_Pid");String r6_Order = request.getParameter("r6_Order");String r7_Uid = request.getParameter("r7_Uid");String r8_MP = request.getParameter("r8_MP");String r9_BType = request.getParameter("r9_BType");String rb_BankId = request.getParameter("rb_BankId");String ro_BankOrderId = request.getParameter("ro_BankOrderId");String rp_PayDate = request.getParameter("rp_PayDate");String rq_CardNo = request.getParameter("rq_CardNo");String ru_Trxtime = request.getParameter("ru_Trxtime");// hmacString hmac = request.getParameter("hmac");// 利用本地密钥和加密算法 加密数据String keyValue = "69cl522AV6q613Ii4W6u8K6XuW8vM1N6bFgyv769220IuYe9u37N4y7rI4Pl";boolean isValid = PaymentUtil.verifyCallback(hmac, p1_MerId, r0_Cmd,r1_Code, r2_TrxId, r3_Amt, r4_Cur, r5_Pid, r6_Order, r7_Uid,r8_MP, r9_BType, keyValue);if (isValid) {// 有效if (r9_BType.equals("1")) {// 浏览器重定向response.setContentType("text/html;charset=utf-8");OrderService service = new OrderServiceImpl();Order order = service.findOrderByOid(r6_Order);order.setState(2);service.updateOrder(order);request.setAttribute("msg", "支付成功!订单号:" + r6_Order + "金额:" + r3_Amt);} else if (r9_BType.equals("2")) {// 修改订单状态:// 服务器点对点,来自于易宝的通知System.out.println("收到易宝通知,修改订单状态!");//// 回复给易宝success,如果不回复,易宝会一直通知response.getWriter().print("success");}} else {throw new RuntimeException("数据被篡改!");}
}

总结:
1、熟练掌握sql语句查询与更新
2、熟悉调试的方法,真正开发项目的时候是不会有源码对比参考的
3、总整体层面上了解程序的作用过程

更多推荐

JavaWeb企业实战项目(四):订单模块

本文发布于:2024-02-25 02:36:32,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1697501.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:实战   模块   订单   项目   企业

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!