[TOC]
## 步骤 1 : 先运行,看到效果,再学习
先将完整的 spring 项目(向老师要相关资料),配置运行起来,确认可用之后,再学习做了哪些步骤以达到这样的效果。
## 步骤 2 : 模仿和排错
在确保可运行项目能够正确无误地运行之后,再严格照着教程的步骤,对代码模仿一遍。
模仿过程难免代码有出入,导致无法得到期望的运行结果,此时此刻通过比较**正确答案** ( 可运行项目 ) 和自己的代码,来定位问题所在。
采用这种方式,**学习有效果,排错有效率**,可以较为明显地提升学习速度,跨过学习路上的各个槛。
## 步骤 3 : 页面截图
重启tomcat,通过访问地址
`http://127.0.0.1:8080/tmall_ssm/admin_propertyValue_edit?productId=5`
可以看到产品属性设置的界面
>注: 这productId=4是产品的id,根据你的实际运行情况,采取不同的id值
>
![](https://box.kancloud.cn/a845850326eeef07f8fee70c571420c0_909x160.png)
## 步骤 4 : PropertyValue
为PropertyValue增加一个Property属性以及getter,setter
~~~
package com.dodoke.tmall.pojo;
public class PropertyValue {
private Integer id;
private String value;
private Integer productId;
private Integer propertyId;
/* 非数据库字段 */
private Property property;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value == null ? null : value.trim();
}
public Integer getProductId() {
return productId;
}
public void setProductId(Integer productId) {
this.productId = productId;
}
public Integer getPropertyId() {
return propertyId;
}
public void setPropertyId(Integer propertyId) {
this.propertyId = propertyId;
}
public Property getProperty() {
return property;
}
public void setProperty(Property property) {
this.property = property;
}
}
~~~
## 步骤 5 : PropertyValueService
创建PropertyValueService,提供多个方法,各个方法的作用在接下来的实现类PropertyValueServiceImpl中讲解
~~~
package com.dodoke.tmall.service;
import java.util.List;
import com.dodoke.tmall.pojo.Product;
import com.dodoke.tmall.pojo.PropertyValue;
public interface PropertyValueService {
void init(Product p);
void update(PropertyValue pv);
PropertyValue get(int propertyId, int productId);
List<PropertyValue> list(int productId);
}
~~~
## 步骤 6 : PropertyValueServiceImpl
PropertyValueServiceImpl实现了PropertyValueService:
1. get(int propertyId, int productId)
根据属性id和产品id获取PropertyValue对象
2. list(int productId)
根据产品id获取所有的属性值
3. init方法
3.1 这个方法的作用是初始化PropertyValue。 为什么要初始化呢? 因为对于PropertyValue的管理,没有增加,只有修改。 所以需要通过初始化来进行自动地增加,以便于后面的修改。
3.2 首先根据产品获取分类,然后获取这个分类下的所有属性集合
3.3 然后用属性和产品id去查询,看看这个属性和这个产品,是否已经存在属性值了。
3.4 如果不存在,那么就创建一个属性值,并设置其属性和产品,接着插入到数据库中。
这样就完成了属性值的初始化。
4. update(PropertyValue pv)
更新
~~~
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.PropertyValueMapper;
import com.dodoke.tmall.pojo.Product;
import com.dodoke.tmall.pojo.Property;
import com.dodoke.tmall.pojo.PropertyValue;
import com.dodoke.tmall.pojo.PropertyValueExample;
import com.dodoke.tmall.service.PropertyService;
import com.dodoke.tmall.service.PropertyValueService;
@Service
public class PropertyValueServiceImpl implements PropertyValueService {
@Autowired
PropertyValueMapper propertyValueMapper;
@Autowired
PropertyService propertyService;
/**
* 初始化PropertyValue
*/
@Override
public void init(Product p) {
// 根据产品获取分类,然后获取这个分类下的所有属性集合
List<Property> pts = propertyService.list(p.getCategoryId());
for (Property pt : pts) {
// 用属性和产品id去查询对应属性值
PropertyValue pv = get(pt.getId(), p.getId());
// 看看这个属性和这个产品,是否已经存在属性值了。若不存在,那么就创建一个属性值,并设置其属性和产品,接着插入到数据库中
if (null == pv) {
pv = new PropertyValue();
pv.setProductId(p.getId());
pv.setPropertyId(pt.getId());
propertyValueMapper.insert(pv);
}
}
}
/**
* 更新
*/
@Override
public void update(PropertyValue pv) {
propertyValueMapper.updateByPrimaryKeySelective(pv);
}
/**
* 根据属性id和产品id获取PropertyValue对象
*/
@Override
public PropertyValue get(int propertyId, int productId) {
PropertyValueExample example = new PropertyValueExample();
example.createCriteria().andPropertyIdEqualTo(propertyId).andProductIdEqualTo(productId);
List<PropertyValue> pvs = propertyValueMapper.selectByExample(example);
if (pvs.isEmpty())
return null;
return pvs.get(0);
}
/**
* 根据产品id获取所有的属性值
*/
@Override
public List<PropertyValue> list(int productId) {
PropertyValueExample example = new PropertyValueExample();
example.createCriteria().andProductIdEqualTo(productId);
List<PropertyValue> result = propertyValueMapper.selectByExample(example);
for (PropertyValue pv : result) {
Property property = propertyService.get(pv.getPropertyId());
pv.setProperty(property);
}
return result;
}
}
~~~
## 步骤 7 : PropertyValueController
准备PropertyValueController类
~~~
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 org.springframework.web.bind.annotation.ResponseBody;
import com.dodoke.tmall.pojo.Product;
import com.dodoke.tmall.pojo.PropertyValue;
import com.dodoke.tmall.service.ProductService;
import com.dodoke.tmall.service.PropertyValueService;
@Controller
@RequestMapping("")
public class PropertyValueController {
@Autowired
PropertyValueService propertyValueService;
@Autowired
ProductService productService;
/**
* 属性值编辑
*
* @param model
* 模型
* @param productId
* 产品id
* @return 页面路径
*/
@RequestMapping("admin_propertyValue_edit")
public String edit(Model model, int productId) {
// 根据产品id, 获取产品对象
Product p = productService.get(productId);
// 初始化属性值
propertyValueService.init(p);
List<PropertyValue> pvs = propertyValueService.list(p.getId());
model.addAttribute("p", p);
model.addAttribute("pvs", pvs);
return "admin/editPropertyValue";
}
/**
* 属性值更新
* @param pv 属性值对象
* @return 提示信息字符串
*/
@RequestMapping("admin_propertyValue_update")
@ResponseBody
public String update(PropertyValue pv) {
propertyValueService.update(pv);
return "success";
}
}
~~~
## 步骤 8 : editPropertyValue.jsp
增加editPropertyValue.jsp
## 步骤 9 : 编辑功能讲解
通过产品管理界面的设置属性,跳到编辑页面
调用PropertyValueController的edit方法:
1. 根据productId获取product对象,因为面包屑导航里需要显示产品的名称和分类的连接。
2. 初始化属性值: propertyValueService.init(p)。 因为在第一次访问的时候,这些属性值是不存在的,需要进行初始化。
3. 根据产品,获取其对应的属性值集合。
4. 服务端跳转到editPropertyValue.jsp 上
5. 在editPropertyValue.jsp上,用c:forEach遍历出这些属性值
![](https://box.kancloud.cn/e1b4be3b9bee6ffb1f7badd2e56b6de1_85x136.png)
PropertyValueController 代码片段:
~~~
/**
* 属性值编辑
*
* @param model
* 模型
* @param productId
* 产品id
* @return 页面路径
*/
@RequestMapping("admin_propertyValue_edit")
public String edit(Model model, int productId) {
// 根据产品id, 获取产品对象
Product p = productService.get(productId);
// 初始化属性值
propertyValueService.init(p);
List<PropertyValue> pvs = propertyValueService.list(p.getId());
model.addAttribute("p", p);
model.addAttribute("pvs", pvs);
return "admin/editPropertyValue";
}
~~~
editPropertyValue.jsp:
~~~
<c:forEach items="${pvs}" var="pv">
<div class="eachPV">
<span class="pvName" >${pv.property.name}</span>
<span class="pvValue"><input class="pvValue" pvid="${pv.id}" type="text" value="${pv.value}"></span>
</div>
</c:forEach>
~~~
## 步骤 10 : 修改功能讲解
修改功能采用的是使用post方式提交ajax的异步调用方式
1. 监听输入框上的keyup事件
2. 获取输入框里的值
3. 获取输入框上的自定义属性pvid,这就是当前PropertyValue对应的id
4. 把边框的颜色修改为黄色,表示正在修改的意思
5. 借助JQuery的ajax函数 $.post,把id和值,提交到admin_propertyValue_update
6. admin_propertyValue_update导致PropertyValueController的update方法被调用
* 参数 PropertyValue 获取浏览器Ajax方式提交的参数
* 通过 propertyValueService.update(propertyValue) 更新到数据库
* 结合方法update上的注解@ResponseBody和return "success" 就会向浏览器返回字符串 "success"
* propertyValueService调用的是`propertValueMapper.updateByPrimaryKeySelective(pv); `这个方法只会更新propertyValue存在的字段,而参数PropertyValue只有id和value有值,所以即便这个PropertyValue对象没有productId和propertyId值,修改的时候也不会影响该PropertyValue的productId和propertyId。
7. 浏览器判断如果返回值是"success",那么就把边框设置为绿色,表示修改成功,否则设置为红色,表示修改失败
![](https://box.kancloud.cn/a845850326eeef07f8fee70c571420c0_909x160.png)
editPropertyValue.jsp:
~~~
$("input.pvValue").keyup(function(){
var value = $(this).val();
var page = "admin_propertyValue_update";
var pvid = $(this).attr("pvid");
var parentSpan = $(this).parent("span");
parentSpan.css("border","1px solid yellow");
$.post(
page,
{"value":value,"id":pvid},
function(result){
if("success"==result) {
parentSpan.css("border","1px solid green");
} else {
parentSpan.css("border","1px solid red");
}
}
);
});
~~~
PropertyValueController 代码片段:
~~~
/**
* 属性值更新
* @param pv 属性值对象
* @return 提示信息字符串
*/
@RequestMapping("admin_propertyValue_update")
@ResponseBody
public String update(PropertyValue pv) {
propertyValueService.update(pv);
return "success";
}
~~~
## 步骤 11 : 删除,增加功能不需要
属性的维护是在分类中进行,这里仅仅做值的设置。 不提供删除和增加功能
> 这里属性不提供删除功能,会导致没办法删除带有属性的产品,其实,对于产品而言,要删除还是挺麻烦的,最好标记成为删除状态比较好。 否则要删除的数据太多了,产品图片信息,属性值信息,订单项信息,评价信息,这些都是依赖产品的。
产品毕竟是核心数据,还是使用标记的好,不要轻易删除的好。
- 项目简介
- 功能一览
- 前台
- 后台
- 开发流程
- 需求分析-展示
- 首页
- 产品页
- 分类页
- 搜索结果页
- 购物车查看页
- 结算页
- 确认支付页
- 支付成功页
- 我的订单页
- 确认收货页
- 确认收货成功页
- 评价页
- 需求分析-交互
- 分类页排序
- 立即购买
- 加入购物车
- 调整订单项数量
- 删除订单项
- 生成订单
- 订单页功能
- 确认付款
- 确认收货
- 提交评价信息
- 登录
- 注册
- 退出
- 搜索
- 前台需求列表
- 需求分析后台
- 分类管理
- 属性管理
- 产品管理
- 产品图片管理
- 产品属性设置
- 用户管理
- 订单管理
- 后台需求列表
- 表结构设计
- 数据建模
- 表与表之间的关系
- 后台-分类管理
- 可运行的项目
- 静态资源
- JSP包含关系
- 查询
- 分页
- 增加
- 删除
- 编辑
- 修改
- 做一遍
- 重构
- 分页方式
- 分类逆向工程
- 所有逆向工程
- 后台其他页面
- 属性管理实现
- 产品管理实现
- 产品图片管理实现
- 产品属性值设置
- 用户管理实现
- 订单管理实现
- 前端
- 前台-首页
- 可运行的项目
- 静态资源
- ForeController
- home方法
- home.jsp
- homePage.jsp
- 前台-无需登录
- 注册
- 登录
- 退出
- 产品页
- 模态登录
- 分类页
- 搜索
- 前台-需要登录
- 购物流程
- 立即购买
- 结算页面
- 加入购物车
- 查看购物车页面
- 登录状态拦截器
- 其他拦截器
- 购物车页面操作
- 订单状态图
- 生成订单
- 我的订单页
- 我的订单页操作
- 评价产品
- 总结