🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
[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 : 删除,增加功能不需要 属性的维护是在分类中进行,这里仅仅做值的设置。 不提供删除和增加功能 > 这里属性不提供删除功能,会导致没办法删除带有属性的产品,其实,对于产品而言,要删除还是挺麻烦的,最好标记成为删除状态比较好。 否则要删除的数据太多了,产品图片信息,属性值信息,订单项信息,评价信息,这些都是依赖产品的。 产品毕竟是核心数据,还是使用标记的好,不要轻易删除的好。