ThinkChat2.0新版上线,更智能更精彩,支持会话、画图、阅读、搜索等,送10W Token,即刻开启你的AI之旅 广告
[TOC] ## 步骤 1 : 明确需求,首页需要什么数据? 那么首页需要什么数据呢? 从**首页展示需求分析**上来看: 1. 在横向导航栏上提供4个分类连接 2. 在纵向导航栏上提供全部17个分类连接 3. 当鼠标移动到某一个纵向分类连接的时候,显示这个分类下的**推荐产品列表** 4. 按照每种分类显示5个商品的方式,显示所有17种分类 注:**推荐产品列表**就是如图所示的一个分类右边的产品列表。 ![](https://box.kancloud.cn/036257969f2b10ea748ed6127c1b7891_960x456.png) ## 步骤 2 : Category Category新增两个瞬时字段products和productsByRow。 ~~~ List<Product> products; List<List<Product>> productsByRow; ~~~ products比较好理解,代表一个分类下有多个产品。 productsByRow这个属性的类型是`List<List<Product>> productsByRow`。 即一个分类又对应多个 `List<Product>`,提供这个属性,是为了在首页竖状导航的分类名称右边显示推荐产品列表。 如截图所示,一个分类会对应多行产品,而一行产品里又有多个产品记录。 为了实现界面上的这个功能,为Category类设计了 List<List<Product>> productsByRow 这样一个集合属性 ![](https://box.kancloud.cn/074f19a2fc5824755da5a5ae0d4b5c6f_932x472.png) ~~~ package com.dodoke.tmall.pojo; import java.util.List; public class Category { private Integer id; private String name; /* 如下是非数据库字段 */ private List<Product> products; private List<List<Product>> productsByRow; public List<Product> getProducts() { return products; } public void setProducts(List<Product> products) { this.products = products; } public List<List<Product>> getProductsByRow() { return productsByRow; } public void setProductsByRow(List<List<Product>> productsByRow) { this.productsByRow = productsByRow; } public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name == null ? null : name.trim(); } } ~~~ ## 步骤 3 : ProductService ProductService新增加3个方法 ~~~ public void fill(List<Category> categorys); public void fill(Category category); public void fillByRow(List<Category> categorys); ~~~ ~~~ package com.dodoke.tmall.service; import java.util.List; import com.dodoke.tmall.pojo.Category; import com.dodoke.tmall.pojo.Product; public interface ProductService { void add(Product c); void delete(int id); void update(Product c); Product get(int id); List list(int categoryId); void setFirstProductImage(Product p); /** * 为分类填充产品集合 * * @param categorys */ public void fill(List<Category> categorys); /** * 为多个分类填充产品集合 * * @param category */ public void fill(Category category); /** * 为多个分类填充推荐产品集合,即把分类下的产品集合,按照8个为一行,拆成多行,以利于后续页面上进行显示 * * @param categorys */ public void fillByRow(List<Category> categorys); } ~~~ ## 步骤 4 : ProductServiceImpl ProductServiceImpl为ProductService中新增加的三个方法提供实现。 1. 为分类填充产品集合 `public void fill(Category category);` 2. 为多个分类填充产品集合 `public void fill(List<Category> categorys);` 3.为多个分类填充推荐产品集合,即把分类下的产品集合,按照8个为一行,拆成多行,以利于后续页面上进行显示 `public void fillByRow(List<Category> categorys);` ~~~ package com.dodoke.tmall.service.impl; import java.util.ArrayList; import java.util.Date; import java.util.List; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import com.dodoke.tmall.mapper.ProductMapper; import com.dodoke.tmall.pojo.Category; import com.dodoke.tmall.pojo.Product; import com.dodoke.tmall.pojo.ProductExample; import com.dodoke.tmall.pojo.ProductImage; import com.dodoke.tmall.service.CategoryService; import com.dodoke.tmall.service.ProductImageService; import com.dodoke.tmall.service.ProductService; @Service public class ProductServiceImpl implements ProductService { @Autowired ProductMapper productMapper; @Autowired CategoryService categoryService; @Autowired ProductImageService productImageService; @Override public void add(Product p) { p.setCreateDate(new Date()); productMapper.insert(p); } @Override public void delete(int id) { productMapper.deleteByPrimaryKey(id); } @Override public void update(Product p) { productMapper.updateByPrimaryKeySelective(p); } @Override public Product get(int id) { Product p = productMapper.selectByPrimaryKey(id); setFirstProductImage(p); setCategory(p); return p; } private void setCategory(Product p) { int categoryId = p.getCategoryId(); Category category = categoryService.get(categoryId); p.setCategory(category); } @Override public List list(int categoryId) { ProductExample example = new ProductExample(); example.createCriteria().andCategoryIdEqualTo(categoryId); example.setOrderByClause("id desc"); List result = productMapper.selectByExample(example); setFirstProductImage(result); setCategory(result); return result; } public void setCategory(List<Product> ps) { for (Product p : ps) { setCategory(p); } } /** * 根据productId和图片类型查询出所有的单个图片,然后把第一个取出来放在firstProductImage上。 * * @param p * 产品 */ @Override public void setFirstProductImage(Product p) { List<ProductImage> pis = productImageService.list(p.getId(), ProductImageService.type_single); if (!pis.isEmpty()) { ProductImage pi = pis.get(0); p.setFirstProductImage(pi); } } /** * 给多个产品设置图片 * * @param ps * 产品集合 */ public void setFirstProductImage(List<Product> ps) { for (Product p : ps) { setFirstProductImage(p); } } /** * 为分类填充产品集合 * * @param categorys */ @Override public void fill(Category c) { List<Product> ps = list(c.getId()); c.setProducts(ps); } /** * 为多个分类填充产品集合 * * @param category */ @Override public void fill(List<Category> cs) { for (Category c : cs) { fill(c); } } /** * 为多个分类填充推荐产品集合,即把分类下的产品集合,按照8个为一行,拆成多行,以利于后续页面上进行显示 * * @param categorys */ @Override public void fillByRow(List<Category> cs) { // 把分类下的产品集合,按照8个为一行,拆成多行,以利于后续页面上进行显示 int productNumberEachRow = 8; // 将categorylist中每个category拿出来循环 for (Category c : cs) { // 获取每个分类中对应的产品,在使用fillByRow(List<Category> cs)这个方法前,需要先使用fill方法,注入分类中的所有产品,因此在这里才可以取出产品 List<Product> products = c.getProducts(); // 每一行产品的list List<List<Product>> productsByRow = new ArrayList<>(); for (int i = 0; i < products.size(); i += productNumberEachRow) { int size = i + productNumberEachRow; // 界限判断 size = size > products.size() ? products.size() : size; // 该方法返回的是父list的一个子集合,从fromIndex(包含),到toIndex(不包含) List<Product> productsOfEachRow = products.subList(i, size); productsByRow.add(productsOfEachRow); } c.setProductsByRow(productsByRow); } } } ~~~ ## 步骤 5 : ForeController home()方法映射首页访问路径 "forehome". 1. 查询所有分类 2. 为这些分类填充产品集合 3. 为这些分类填充推荐产品集合 4. 服务端跳转到home.jsp ~~~ package com.dodoke.tmall.controller; import java.util.List; 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 com.dodoke.tmall.pojo.Category; 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.UserService; @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; @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"; } } ~~~ ## 步骤 6 : home.jsp home.jsp涉及多个页面,将在后续讲解**home.jsp**