[TOC]
## 步驟 1 : 明確需求,首頁需要什么數據?
那么首頁需要什么數據呢? 從**首頁展示需求分析**上來看:
1. 在橫向導航欄上提供4個分類連接
2. 在縱向導航欄上提供全部17個分類連接
3. 當鼠標移動到某一個縱向分類連接的時候,顯示這個分類下的**推薦產品列表**
4. 按照每種分類顯示5個商品的方式,顯示所有17種分類
注:**推薦產品列表**就是如圖所示的一個分類右邊的產品列表。

## 步驟 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
這樣一個集合屬性

~~~
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**
- 項目簡介
- 功能一覽
- 前臺
- 后臺
- 開發流程
- 需求分析-展示
- 首頁
- 產品頁
- 分類頁
- 搜索結果頁
- 購物車查看頁
- 結算頁
- 確認支付頁
- 支付成功頁
- 我的訂單頁
- 確認收貨頁
- 確認收貨成功頁
- 評價頁
- 需求分析-交互
- 分類頁排序
- 立即購買
- 加入購物車
- 調整訂單項數量
- 刪除訂單項
- 生成訂單
- 訂單頁功能
- 確認付款
- 確認收貨
- 提交評價信息
- 登錄
- 注冊
- 退出
- 搜索
- 前臺需求列表
- 需求分析后臺
- 分類管理
- 屬性管理
- 產品管理
- 產品圖片管理
- 產品屬性設置
- 用戶管理
- 訂單管理
- 后臺需求列表
- 表結構設計
- 數據建模
- 表與表之間的關系
- 后臺-分類管理
- 可運行的項目
- 靜態資源
- JSP包含關系
- 查詢
- 分頁
- 增加
- 刪除
- 編輯
- 修改
- 做一遍
- 重構
- 分頁方式
- 分類逆向工程
- 所有逆向工程
- 后臺其他頁面
- 屬性管理實現
- 產品管理實現
- 產品圖片管理實現
- 產品屬性值設置
- 用戶管理實現
- 訂單管理實現
- 前端
- 前臺-首頁
- 可運行的項目
- 靜態資源
- ForeController
- home方法
- home.jsp
- homePage.jsp
- 前臺-無需登錄
- 注冊
- 登錄
- 退出
- 產品頁
- 模態登錄
- 分類頁
- 搜索
- 前臺-需要登錄
- 購物流程
- 立即購買
- 結算頁面
- 加入購物車
- 查看購物車頁面
- 登錄狀態攔截器
- 其他攔截器
- 購物車頁面操作
- 訂單狀態圖
- 生成訂單
- 我的訂單頁
- 我的訂單頁操作
- 評價產品
- 總結