This is my study notes from MOOC.
表设计
表需求
前台
- 商品分类
- 商品售卖地区
- 用户信息
- 商品列表
- 商品详情
- 购物车
- 订单表
- 个人中心:消息、收藏、收货地址、个人信息
后台
- 商品管理
- 订单管理
- 安全权限:独立模块,菜单、角色、用户表。
- 地区管理
- 商家管理
结构ER图
前台
- deal:商品
- deal_category:商品分类
- area:商品地区,虽然是同一个商品,但是为了简单区分,把同一商品不同的售卖地区标定为不同的商品。
- deal_detail:商品详情,详情页才使用,使用频率不同。
- image_info:商品图片
- cart:购物车
- order_basic:订单基本信息,订单编号、收件人、下单时间、支付方式、状态等。
- order_detail:订单详细信息,包含的商品信息、单价、数量、总价等。
- user:用户
- user_basic_info:用户基本信息
- address:用户的收货地址
- favorite:用户的收藏
- message:用户消息(站内信)
后台
- admin_user:用户
- admin_user_role:用户角色
- admin_role:角色
- admin_function:菜单
- admin_role_function:角色<->菜单的关联表。
首页代码(后台)
主要代码是左侧分类
+下方4大+4小的商品信息
。
IndexController(首页Controller)
import javax.servlet.http.HttpServletRequest;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.List;
@Controller
public class IndexController extends BaseSiteController {
@Autowired private DealService dealService;
@Autowired private DealCategoryService categoryService;
@RequestMapping(value = "/", method = RequestMethod.GET)
public String index(Model model, HttpServletRequest request) {
//1.分类
//2.首页商品
//3.每个大分类下显示8个商品
List<DealCategory> categories = categoryService.getCategories();
model.addAttribute("categories", categories);
//根据IP确定
Long areaId = getAreaId(request);
//1.构造一个结构体存放每个分类的8个商品
//2.页面循环结构体的集合
//3.结构体包含8个商品,1个分类
//4.8个商品分两组
List<IndexCategoryDealDTO> indexCategoryDealDTOs = new ArrayList<>();
categories.forEach(category -> {
List<Deal> deals = dealService.getDealsForIndex(areaId, category.getSelfAndChildrenIds());
indexCategoryDealDTOs.add(new IndexCategoryDealDTO(category, deals));
});
model.addAttribute("indexCategoryDealDTOs", indexCategoryDealDTOs);
return "index";
}
}
注:
(1)index方法配置RequestMapping
注解,关联的URL为/
,且方法为GET
。
(2)首页左侧为商品分类,下方为商品分类的商品(四大图+四小图),故代码要获取分类信息,以及每一个分类信息的商品信息(获取到4+4的辅助类后,构造一个基于分类的辅助类列表,传到前台显示)。
(3)还要根据Request获取访问者的IP,确定售卖地区。
(4)跳转到index
页面,由SpringMVC进行页面解析。
DealCategoryService(商品分类的Service)
// 涉及的主要方法
public List<DealCategory> getCategories() {
List<DealCategory> dealCategories = getAllWithoutDeleted();//从缓存或数据库中查询全部
//JDK8的stream处理,把根分类区分出来
List<DealCategory> roots = dealCategories.stream().filter(dealCategory -> (dealCategory.getParentId() == 0)).collect(Collectors.toList());
//对跟分类进行排序
roots.sort(new Comparator<DealCategory>() {
@Override
public int compare(DealCategory o1, DealCategory o2) {
return o1.getOrderNum() > o2.getOrderNum() ? 1 : -1;
}
});
//把非根分类区分出来
List<DealCategory> subs = dealCategories.stream().filter(dealCategory -> (dealCategory.getParentId() != 0)).collect(Collectors.toList());
//递归构建结构化的分类信息
roots.forEach(root -> buildSubs(root, subs));
return roots;
}
/**
* 查询所有未删除的商品类别
*
* @return
*/
private List<DealCategory> getAllWithoutDeleted() {
List<DealCategory> allCategories = dealCategoryCacheOperator.getAllDealCategories();
// CacheUtil.getAllEntities(DealCategory.class);
if (allCategories == null || allCategories.size() == 0) {
allCategories = dealCategoryDAO.getAllWithoutDeleted();
for (DealCategory dealCategory : allCategories) {
dealCategoryCacheOperator.putDealCategory(dealCategory);
// CacheUtil.putEntity("DealCategory." + dealCategory.getId(), dealCategory);
// CacheUtil.putEntity(dealCategory);
}
}
return allCategories;
}
注:
(1)从缓存或数据库中读取全部的分类信息
(2)找到根分类信息,以及找到非根分类。
(3)将其分类信息构建成链表(父子关系)
的结构,返回给方法调用者。
(4)若缓存中不存在,则查找数据库并放在缓存中。
IndexCategoryDealDTO
因为首页每个分类要显示四大图+四小图
的形式,构建一个辅助类帮助存放这8个商品。
public class IndexCategoryDealDTO {
@Getter @Setter private DealCategory category;
@Getter @Setter private List<Deal> first;
@Getter @Setter private List<Deal> second;
public IndexCategoryDealDTO(DealCategory category, List<Deal> deals) {
this.category = category;
//1.从deals截取出前4个赋值给first
//2.再4个赋值给second
//3.不够怎么办?不够4个与不够8个
//4.多了怎么办?
if (CollectionUtils.isEmpty(deals)) {
this.first = new ArrayList<>();
this.second = new ArrayList<>();
} else if (deals.size() > 4) {
this.first = deals.subList(0, 4);
if (deals.size() > 8) {
this.second = deals.subList(4, 8);
} else {
this.second = deals.subList(4, deals.size());
}
} else {
this.first = new ArrayList<>(deals);
this.second = new ArrayList<>();
}
}
}
注:
(1)构造函数,传入所有的商品信息,帮助构建4+4的商品列表。
前台(freemarker)
基于freemarker模板,文件后缀为.ftl
index.ftl
<#import "macro/common.ftl" as common>
<html>
<head>
<title>首页</title>
</head>
<body>
<div class="banner comWidth clearfix">
<div class="banner_bar banner_big">
<ul class="imgBox">
<li><a href="#"><img src="${ctx}/images/banner/banner_01.jpg" alt="banner"></a></li>
<li><a href="#"><img src="${ctx}/images/banner/banner_02.jpg" alt="banner"></a></li>
</ul>
<div class="imgNum">
<a href="#" class="active"></a><a href="#"></a><a href="#"></a><a href="#"></a>
</div>
</div>
</div>
<#if indexCategoryDealDTOs??>
<#list indexCategoryDealDTOs as dto>
<div class="shopTit comWidth">
<span class="icon"></span><h3>${dto.category.name}</h3>
<a href="${ctx}/category/${dto.category.urlName}" class="more">更多>></a>
</div>
<div class="shopList comWidth clearfix">
<div class="leftArea">
<div class="banner_bar banner_sm">
<ul class="imgBox">
<li><a href="#"><img src="images/banner/banner_sm_01.jpg" alt="banner"></a></li>
<li><a href="#"><img src="images/banner/banner_sm_02.jpg" alt="banner"></a></li>
</ul>
<div class="imgNum">
<a href="#" class="active"></a><a href="#"></a><a href="#"></a><a href="#"></a>
</div>
</div>
</div>
<div class="rightArea">
<#if dto.first?exists>
<div class="shopList_top clearfix">
<#list dto.first as deal>
<div class="shop_item">
<div class="shop_img">
<a href="${ctx}/item/${deal.skuId}"><img src="${helper.getDealImageUrlForIndexDeal1List(deal)}" alt=""></a>
</div>
<h3>${deal.dealTitle}</h3>
<p><@common.formatPrice deal.dealPrice/></p>
<#--<p>${deal.dealPrice}</p>-->
</div>
</#list>
</div>
</#if>
<#if dto.second?exists>
<div class="shopList_sm clearfix">
<#list dto.second as deal>
<div class="shopItem_sm">
<div class="shopItem_smImg">
<a href="${ctx}/item/${deal.skuId}"><img src="${helper.getDealImageUrlForIndexDeal2List(deal)}" alt=""></a>
</div>
<div class="shopItem_text">
<p>${deal.dealTitle}</p>
<h3><@common.formatPrice deal.dealPrice/></h3>
</div>
</div>
</#list>
</div>
</#if>
</div>
</div>
</#list>
</#if>
</body>
</html>
注:
(1)注意首部的import
,包括了一些freemarker的宏
(定义一些工具)。
(2)<#if>
标签,进行判断。
(3)<#list ** as **>
标签,进行循环。
(4)剩下的大概的意思,应该都会懂,取循环变量的字段去做显示。