企业🤖AI智能体构建引擎,智能编排和调试,一键部署,支持私有化部署方案 广告
[TOC] ## 步骤 1 : 先运行,看到效果,再学习 先将完整的 tmall_ssm 项目(向老师要相关资料),配置运行起来,确认可用之后,再学习做了哪些步骤以达到这样的效果。 ## 步骤 2 : 模仿和排错 在确保可运行项目能够正确无误地运行之后,再严格照着教程的步骤,对代码模仿一遍。 模仿过程难免代码有出入,导致无法得到期望的运行结果,此时此刻通过比较**正确答案** ( 可运行项目 ) 和自己的代码,来定位问题所在。 采用这种方式,**学习有效果,排错有效率**,可以较为明显地提升学习速度,跨过学习路上的各个槛。 ## 步骤 3 : 运行效果 立即购买之后,在页面上会报错,因为截至目前的学习进度,购买成功之后跳转到的结算页面还没有开发,将在后续知识点开发。 `HTTP Status 404 - /tmall_ssm/forebuy` 那么点击购买都做了什么事情呢? 会在t_order_item表里插入一条数据,举例说明,这条数据会表示: 1. pid =844 购买的商品id 2. oid = null, 这个订单项还没有生成对应的订单,即还在购物车中 3. uid= 3,用户的id是3 4. number=3, 购买了3件产品 ![](https://box.kancloud.cn/0ef6198d91870b50e29aefb0566c10c3_483x132.png) ## 步骤 4 : 在产品页点击立即购买 如果未登录,那么点击立即购买之前会弹出`模态登录窗口`,关于这个功能的详细介绍在**模态登录**,在此不做赘述。 登录之后,点击立即购买,会访问地址 http://127.0.0.1:8080/tmall_ssm/forebuyone?pid=844&num=3 并带上了产品id 844和购买数量3 ![](https://box.kancloud.cn/2dee407b9f959e9bb4e7d7ff53892350_342x283.png) ## 步骤 5 : OrderItemService 为OrderItemService新增方法listByUser ~~~ package com.dodoke.tmall.service; import java.util.List; import com.dodoke.tmall.pojo.Order; import com.dodoke.tmall.pojo.OrderItem; public interface OrderItemService { void add(OrderItem c); void delete(int id); void update(OrderItem c); OrderItem get(int id); List list(); void fill(List<Order> os); void fill(Order o); int getSaleCount(int pid); List<OrderItem> listByUser(int uid); } ~~~ ## 步骤 6 : OrderItemServiceImpl 为OrderItemServiceImpl新增加方法listByUser的实现 ~~~ package com.dodoke.tmall.service.impl; import java.util.List; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import com.dodoke.tmall.mapper.OrderItemMapper; import com.dodoke.tmall.pojo.Order; import com.dodoke.tmall.pojo.OrderItem; import com.dodoke.tmall.pojo.OrderItemExample; import com.dodoke.tmall.pojo.Product; import com.dodoke.tmall.service.OrderItemService; import com.dodoke.tmall.service.ProductService; @Service public class OrderItemServiceImpl implements OrderItemService { @Autowired OrderItemMapper orderItemMapper; @Autowired ProductService productService; @Override public void add(OrderItem c) { orderItemMapper.insert(c); } @Override public void delete(int id) { orderItemMapper.deleteByPrimaryKey(id); } @Override public void update(OrderItem c) { orderItemMapper.updateByPrimaryKeySelective(c); } @Override public OrderItem get(int id) { OrderItem result = orderItemMapper.selectByPrimaryKey(id); setProduct(result); return result; } public List<OrderItem> list() { OrderItemExample example = new OrderItemExample(); example.setOrderByClause("id desc"); return orderItemMapper.selectByExample(example); } @Override public void fill(List<Order> os) { // 遍历每个订单,然后挨个调用fill(Order order)。 for (Order o : os) { fill(o); } } public void fill(Order o) { // 1. 根据订单id查询出其对应的所有订单项 OrderItemExample example = new OrderItemExample(); example.createCriteria().andOrderIdEqualTo(o.getId()); example.setOrderByClause("id desc"); List<OrderItem> ois = orderItemMapper.selectByExample(example); // 2. 通过setProduct为所有的订单项设置Product属性 setProduct(ois); float total = 0; int totalNumber = 0; // 3. 遍历所有的订单项,然后计算出该订单的总金额和总数量 for (OrderItem oi : ois) { total += oi.getNumber() * oi.getProduct().getPromotePrice(); totalNumber += oi.getNumber(); } o.setTotal(total); o.setTotalNumber(totalNumber); // 4. 最后再把订单项设置在订单的orderItems属性上。 o.setOrderItems(ois); } public void setProduct(List<OrderItem> ois) { for (OrderItem oi : ois) { setProduct(oi); } } private void setProduct(OrderItem oi) { Product p = productService.get(oi.getProductId()); oi.setProduct(p); } @Override public int getSaleCount(int pid) { OrderItemExample example = new OrderItemExample(); example.createCriteria().andProductIdEqualTo(pid); List<OrderItem> ois = orderItemMapper.selectByExample(example); int result = 0; for (OrderItem oi : ois) { result += oi.getNumber(); } return result; } @Override public List<OrderItem> listByUser(int uid) { OrderItemExample example =new OrderItemExample(); example.createCriteria().andUserIdEqualTo(uid).andOrderIdIsNull(); List<OrderItem> result =orderItemMapper.selectByExample(example); setProduct(result); return result; } } ~~~ ## 步骤 7 : ForeController.buyone() 通过上个步骤访问的地址 /forebuyone 导致ForeController.buyone()方法被调用 1. 获取参数pid 2. 获取参数num 3. 根据pid获取产品对象p 4. 从session中获取用户对象user 接下来就是新增订单项OrderItem, 新增订单项要考虑两个情况 a. 如果已经存在这个产品对应的OrderItem,并且还没有生成订单,即还在购物车中。 那么就应该在对应的OrderItem基础上,调整数量 a.1 基于用户对象user,查询没有生成订单的订单项集合 a.2 遍历这个集合 a.3 如果产品是一样的话,就进行数量追加 a.4 获取这个订单项的 id b. 如果不存在对应的OrderItem,那么就新增一个订单项OrderItem b.1 生成新的订单项 b.2 设置数量,用户和产品 b.3 插入到数据库 b.4 获取这个订单项的 id 最后, 基于这个订单项id客户端跳转到结算页面/forebuy ~~~ package com.dodoke.tmall.controller; import java.util.Collections; import java.util.List; import javax.servlet.http.HttpSession; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.util.HtmlUtils; import com.dodoke.tmall.comparator.ProductAllComparator; import com.dodoke.tmall.comparator.ProductDateComparator; import com.dodoke.tmall.comparator.ProductPriceComparator; import com.dodoke.tmall.comparator.ProductReviewComparator; import com.dodoke.tmall.comparator.ProductSaleCountComparator; import com.dodoke.tmall.pojo.Category; import com.dodoke.tmall.pojo.OrderItem; import com.dodoke.tmall.pojo.Product; import com.dodoke.tmall.pojo.ProductImage; import com.dodoke.tmall.pojo.PropertyValue; import com.dodoke.tmall.pojo.Review; import com.dodoke.tmall.pojo.User; import com.dodoke.tmall.service.CategoryService; import com.dodoke.tmall.service.OrderItemService; import com.dodoke.tmall.service.OrderService; import com.dodoke.tmall.service.ProductImageService; import com.dodoke.tmall.service.ProductService; import com.dodoke.tmall.service.PropertyValueService; import com.dodoke.tmall.service.ReviewService; import com.dodoke.tmall.service.UserService; import com.github.pagehelper.PageHelper; @Controller @RequestMapping("") public class ForeController { @Autowired CategoryService categoryService; @Autowired ProductService productService; @Autowired UserService userService; @Autowired ProductImageService productImageService; @Autowired PropertyValueService propertyValueService; @Autowired OrderService orderService; @Autowired OrderItemService orderItemService; @Autowired ReviewService reviewService; @RequestMapping("forehome") public String home(Model model) { List<Category> cs = categoryService.list(); productService.fill(cs); productService.fillByRow(cs); model.addAttribute("cs", cs); return "fore/home"; } @RequestMapping("foreregister") public String register(Model model, User user) { String name = user.getName(); // 把账号里的特殊符号进行转义 name = HtmlUtils.htmlEscape(name); user.setName(name); boolean exist = userService.isExist(name); if (exist) { String m = "用户名已经被使用,不能使用"; model.addAttribute("msg", m); model.addAttribute("user", null); return "fore/register"; } userService.add(user); return "redirect:registerSuccessPage"; } @RequestMapping("forelogin") public String login(@RequestParam("name") String name, @RequestParam("password") String password, Model model, HttpSession session) { name = HtmlUtils.htmlEscape(name); User user = userService.get(name, password); if (null == user) { model.addAttribute("msg", "账号密码错误"); return "fore/login"; } session.setAttribute("user", user); return "redirect:forehome"; } @RequestMapping("forelogout") public String logout(HttpSession session) { session.removeAttribute("user"); return "redirect:forehome"; } @RequestMapping("foreproduct") public String product(int pid, Model model) { Product p = productService.get(pid); // 根据对象p,获取这个产品对应的单个图片集合 List<ProductImage> productSingleImages = productImageService.list(p.getId(), ProductImageService.type_single); // 根据对象p,获取这个产品对应的详情图片集合 List<ProductImage> productDetailImages = productImageService.list(p.getId(), ProductImageService.type_detail); p.setProductSingleImages(productSingleImages); p.setProductDetailImages(productDetailImages); // 获取产品的所有属性值 List<PropertyValue> pvs = propertyValueService.list(p.getId()); // 获取产品对应的所有的评价 List<Review> reviews = reviewService.list(p.getId()); // 设置产品的销量和评价数量 productService.setSaleAndReviewNumber(p); model.addAttribute("reviews", reviews); model.addAttribute("p", p); model.addAttribute("pvs", pvs); return "fore/product"; } @RequestMapping("forecheckLogin") @ResponseBody public String checkLogin(HttpSession session) { User user = (User) session.getAttribute("user"); if (null != user) { return "success"; } return "fail"; } @RequestMapping("foreloginAjax") @ResponseBody public String loginAjax(@RequestParam("name") String name, @RequestParam("password") String password, HttpSession session) { name = HtmlUtils.htmlEscape(name); User user = userService.get(name, password); if (null == user) { return "fail"; } session.setAttribute("user", user); return "success"; } @RequestMapping("forecategory") public String category(int cid, String sort, Model model) { Category c = categoryService.get(cid); productService.fill(c); productService.setSaleAndReviewNumber(c.getProducts()); if (null != sort) { switch (sort) { case "review": Collections.sort(c.getProducts(), new ProductReviewComparator()); break; case "date": Collections.sort(c.getProducts(), new ProductDateComparator()); break; case "saleCount": Collections.sort(c.getProducts(), new ProductSaleCountComparator()); break; case "price": Collections.sort(c.getProducts(), new ProductPriceComparator()); break; case "all": Collections.sort(c.getProducts(), new ProductAllComparator()); break; } } model.addAttribute("c", c); return "fore/category"; } @RequestMapping("foresearch") public String search(String keyword, Model model) { PageHelper.offsetPage(0, 20); List<Product> ps = productService.search(keyword); productService.setSaleAndReviewNumber(ps); model.addAttribute("ps", ps); return "fore/searchResult"; } @RequestMapping("forebuyone") public String buyone(int pid, int num, HttpSession session) { Product p = productService.get(pid); int oiid = 0; User user = (User) session.getAttribute("user"); boolean found = false; List<OrderItem> ois = orderItemService.listByUser(user.getId()); for (OrderItem oi : ois) { if (oi.getProduct().getId().intValue() == p.getId().intValue()) { oi.setNumber(oi.getNumber() + num); orderItemService.update(oi); found = true; oiid = oi.getId(); break; } } if (!found) { OrderItem oi = new OrderItem(); oi.setUserId(user.getId()); oi.setNumber(num); oi.setProductId(pid); orderItemService.add(oi); oiid = oi.getId(); } return "redirect:forebuy?oiid=" + oiid; } } ~~~ > oiid 接下来的知识点就会讲解 ## 拓展 如果模仿现在的天猫网站,立即购买和购物车没有关联,思路如何实现呢? > 提示: 可以为 orderItem 增加一个 type 字段, 用来标记是从 立即购买创建的,还是加入购物车创建的。 在购物车页面,之显示后者,不显示前者即可。