学习淘淘商城第二十六课(内容分类管理)

   上节课我们一起搭建了内容服务工程,这节课我们一起学习如何添加内容分类。

      我们到后台管理页面看看关于内容管理的内容,如下图所示。


      我们再来看下content-category.jsp页面,这个页面就是内容分类页面,页面中<ul id="contentCategory" class="easyui-tree">用来展示内容分类树,$(function()是在页面加载完后要调用的js,下面这段代码是用来获取分类列表数据的,发起的url请求是/content/category/list,animate:true的意思是设置动画,如果设置为true,展开树形结构时是慢慢展开的效果。如果设置为false展开树形结构就一下子展开了。method:"GET"指定发起的是GET请求。

[html]  view plain  copy
  1. $("#contentCategory").tree({  
  2.         url : '/content/category/list',  
  3.         animate: true,  
  4.         method : "GET",  


      在com.taotao.content.service包下新建接口类ContentCategoryService.java,在接口类中添加一个接口getContentCategoryList。


       返回值是EasyUITreeNode的集合,EasyUITreeNode类的内容如下所示。id是树节点的id,text是节点的名称,state是指树形是闭合的还是打开的,如果当前节点还有子节点,那么state的值是"closed",如果当前节点已经是叶子节点了,那么state的值是"open"。


      下面我们实现上面的接口,我们在taotao-content-service的com.taotao.content.service.impl包下新建ContentCategoryServiceImpl实现类,该类实现ContentCategoryService接口类。如下图所示。


       为方便复制,实现类代码如下:

[html]  view plain  copy
  1. package com.taotao.content.service.impl;  
  2.   
  3. import java.util.ArrayList;  
  4. import java.util.List;  
  5.   
  6. import org.springframework.beans.factory.annotation.Autowired;  
  7. import org.springframework.stereotype.Service;  
  8.   
  9. import com.taotao.common.pojo.EasyUITreeNode;  
  10. import com.taotao.content.service.ContentCategoryService;  
  11. import com.taotao.mapper.TbContentCategoryMapper;  
  12. import com.taotao.pojo.TbContentCategory;  
  13. import com.taotao.pojo.TbContentCategoryExample;  
  14. import com.taotao.pojo.TbContentCategoryExample.Criteria;  
  15.   
  16. @Service  
  17. public class ContentCategoryServiceImpl implements ContentCategoryService {  
  18.     @Autowired  
  19.     private TbContentCategoryMapper contentCategoryMapper;  
  20.   
  21.     @Override  
  22.     public List<EasyUITreeNode> getContentCategoryList(long parentId) {  
  23.         //创建一个查询类  
  24.         TbContentCategoryExample contentCategoryExample = new TbContentCategoryExample();  
  25.         //设置查询条件  
  26.         Criteria criteria = contentCategoryExample.createCriteria();  
  27.         criteria.andParentIdEqualTo(parentId);  
  28.         //查询  
  29.         List<TbContentCategory> categoryList = contentCategoryMapper.selectByExample(contentCategoryExample);  
  30.         //将categoryList转换为List<EasyUITreeNode>  
  31.         List<EasyUITreeNode> resultList = new ArrayList<>();  
  32.         for(TbContentCategory contentCategory : categoryList){  
  33.             EasyUITreeNode easyUITreeNode = new EasyUITreeNode();  
  34.             easyUITreeNode.setId(contentCategory.getId());  
  35.             easyUITreeNode.setText(contentCategory.getName());  
  36.             easyUITreeNode.setState(contentCategory.getIsParent() ? "closed":"open");  
  37.             resultList.add(easyUITreeNode);  
  38.         }  
  39.         return resultList;  
  40.     }  
  41.   
  42. }  
       下面我们发布一下该服务的这个接口,我们在taotao-content-service工程的spring目录下的applicationContext-service.xml文件中发布<dubbo:service interface="com.taotao.content.service.ContentCategoryService" ref="ContentCategoryServiceImpl" timeout="300000"/>

     下面我们需要在taotao-manager-web工程添加Controller类来实现内容分类展示,前提是我们需要先添加对taotao-content-interface的依赖,如下图所示。


       接着我们需要在taotao-manager-web的springmvc.xml中添加对ContentCategoryService的引用,添加的内容:<dubbo:reference interface="com.taotao.content.service.ContentCategoryService" id="contentCategoryService" />,如下图所示。


     下面我们在ContentCategoryController类中调用服务接口。@RequestMapping("/content/category/list")的url是从content-category.jsp当中粘贴过来的。


     代码如下,这里需要注意的是,第一次查询内容分类的时候没有参数的,因此需要指定一个默认值0,后续点击要展开某个节点的话,就会把节点id传过来了。还有就是参数parentId与id名称不一致,因此需要@RequestParam(name="id",defaultValue="0")这样来把id的值赋值给"parentId"。

[html]  view plain  copy
  1. package com.taotao.controller;  
  2.   
  3. import java.util.List;  
  4.   
  5. import org.springframework.beans.factory.annotation.Autowired;  
  6. import org.springframework.stereotype.Controller;  
  7. import org.springframework.web.bind.annotation.RequestMapping;  
  8. import org.springframework.web.bind.annotation.RequestParam;  
  9. import org.springframework.web.bind.annotation.ResponseBody;  
  10.   
  11. import com.taotao.common.pojo.EasyUITreeNode;  
  12. import com.taotao.content.service.ContentCategoryService;  
  13.   
  14. @Controller  
  15. public class ContentCategoryController {  
  16.       
  17.     @Autowired  
  18.     private ContentCategoryService contentCategoryService;  
  19.       
  20.     @RequestMapping("/content/category/list")  
  21.     @ResponseBody  
  22.     public List<EasyUITreeNode> getContentCategoryList(@RequestParam(name="id",defaultValue="0") Long parentId){  
  23.         List<EasyUITreeNode> list = contentCategoryService.getContentCategoryList(parentId);  
  24.         return list;  
  25.     }  
  26. }  
     在启动测试之前,我们需要先打包taotao-content到本地maven仓库,方法是在工程上右键------->Run As------>Maven install。

     由于查询内容分类列表涉及到了两个服务和taotao-manager-web,因此需要启动taotao-manager服务和taotao-content服务和taotao-manager-web。

     在启动之前先打包taotao-manager和taotao-content到本地maven仓库,然后依次启动taotao-manager和taotao-content,然后是taotao-manager-web,启动好之后我们访问后台,如下图所示,发现可以正常显示内容分类列表了。


       分类列表展示出来了,我们下面要做的便是管理内容分类,比如增加、重命名、删除等操作,这些操作可以在某个节点上右键,在右键菜单中操作(当然,现在还没有实现这三个功能),如下图所示。


       右键菜单是在content-category.jsp页面的一个<div>中定义的,如下图所示。onContextMenu: function(e,node){这行代码的意思是当我们鼠标点击右键的时候触发该js方法,方法的参数中"e"代表事件,node代表鼠标在哪个节点上。e.preventDefault();代表事件传递,$(this).tree('select',node.target);这行代码的意思是$(this)指定鼠标所在的节点转变为jquery对象,.tree('select',node.target);意思是选中这个节点(node这行会添加背景颜色)。$('#contentCategoryMenu').menu('show',{这行代码的意思是让右键菜单显示出来,下面的left和top是指坐标。


      对节点进行操作的流程是,当我们点击右键菜单中的任何一个操作的时候,data-options="onClick:menuHandler"告诉我们它会触发menuHandler方法。function menuHandler(item)这行代码的意思是定义menuHandler方法,参数item是指右键菜单这个对象,下面通过item.name来判断用户选择的是哪个操作。var tree = $("#contentCategory");这行代码当然就是获取分类树了,var node = tree.tree("getSelected");这行代码是获取选中的节点,tree.tree('append', {这行代码的意思是我们点击"添加"的时候会在这个节点下面追加一个节点,parent: (node?node.target:null),是为新节点指定父节点,data里面的text是指新建的节点名称叫"新建分类",id:0,表示新建的节点暂时定义id为0,parentId:node.id是指新建节点的parentId是我们操作的节点。var _node = tree.tree('find',0);的意思是在树种找到id为0的节点(由于新建的节点暂时定义id为0,因此会找到刚添加的节点),tree.tree("select",_node.target).tree('beginEdit',_node.target);这行代码的意思是让新建的节点处于可编辑状态。可以看到实际添加节点的操作不在menuHandler这个方法中,这个方法真正执行的操作是删除节点,$.post("/content/category/delete/",{parentId:node.parentId,id:node.id},function(){这行代码的意思便是去发起url为"/content/category/delete/"的请求,传递的参数是父级id和要删除的节点的id。function()是指回调函数,tree.tree("remove",node.target);意思就是从树形结构中删掉这个节点。


       那么,实际进行添加节点到数据库的操作是在哪儿控制的呢?如下图所示,onAfterEdit : function(node){意思很明显了,就是我们编辑完之后鼠标离开编辑节点后触发的事件,参数node是指新建的节点,var _tree = $(this);是指得到tree,if(node.id == 0){的意思是如果node的id是0,(我们新建的节点id就暂时是0,因此会进入这个if当中),$.post("/content/category/create"的意思是添加节点会去请求"/content/category/create"这个url。{parentId:node.parentId,name:node.text}是指传递的参数有两个,分别是父级id和节点的名称。function(data)是回调函数,data是返回的对象。if(data.status == 200){很显然是指操作成功。_tree.tree("update",{target : node.target,id : data.data.id});的意思是如果操作成功了,那么就要去更新一下新添加的节点的id,data.data.id是指添加到数据库中的节点的Id。如果if(node.id == 0)条件不成立,说明不是添加新节点操作,而是更新节点操作。$.post("/content/category/update",{id:node.id,name:node.text});意思是请求url为"/content/category/update",传递的参数有节点id、节点名称。


       分析完了js代码,下面我们便来一一实现内容分类的添加、修改、删除功能

       首先是添加功能,由于都是单表操作,因此使用逆向工程生成的代码就可以满足要求,我们直接修改服务层即可,我们到taotao-content-interface工程添加一个接口,如下图所示。


        下面我们到taotao-content-service工程中去实现这个接口,不过在此之前,由于逆向工程自动生成的insert方法不会自动帮我们给主键的值赋值,因此我们需要在mapper.xml文件中新增一段sql,id取值为"saveAndGetId",这段sql的意思是保存内容分类并且自动给对象的id属性赋值,之所以这样做是因为我们需要用到这个id给树形结构中新增加的节点id赋值,<selectKey keyProperty="id" resultType="long" order="AFTER">就是给新添加的对象的主键赋值的,如下图所示。


        为方便复制,现粘贴如下

[html]  view plain  copy
  1. <insert id="saveAndGetId" parameterType="com.taotao.pojo.TbContentCategory"   
  2.              useGeneratedKeys="true" keyProperty="id">  
  3.     insert into tb_content_category (parent_id, name, status, sort_order, is_parent, created, updated)  
  4.     values (#{parentId,jdbcType=BIGINT}, #{name,jdbcType=VARCHAR},   
  5.       #{status,jdbcType=INTEGER}, #{sortOrder,jdbcType=INTEGER}, #{isParent,jdbcType=BIT},   
  6.       #{created,jdbcType=TIMESTAMP}, #{updated,jdbcType=TIMESTAMP})  
  7.       <selectKey keyProperty="id" resultType="long" order="AFTER">  
  8.            SELECT LAST_INSERT_ID()  
  9.       </selectKey>  
  10.   </insert>  
      在TbContentCategoryMapper.xml添加完sql语句之后,我们需要到TbContentCategoryMapper类中添加对应的方法,如下图所示。

       做好以上准备后,我们到ContentCategoryServiceImpl类中实现添加内容分类接口了,如下所示。

      实现类代码如下

[html]  view plain  copy
  1. @Override  
  2.     public TaotaoResult addContentCategory(long parentId, String name) {  
  3.         //实例化一个对象  
  4.         TbContentCategory contentCategory = new TbContentCategory();  
  5.         //填充属性值  
  6.         contentCategory.setParentId(parentId);  
  7.         contentCategory.setName(name);  
  8.         //状态。可选值:1(正常),2(删除),刚添加的节点肯定是正常的  
  9.         contentCategory.setStatus(1);  
  10.         //刚添加的节点肯定不是父节点  
  11.         contentCategory.setIsParent(false);  
  12.         //数据库中现在默认的都是1,所以这里我们也写成1  
  13.         contentCategory.setSortOrder(1);  
  14.         //保存当前操作时间  
  15.         contentCategory.setCreated(new Date());  
  16.         contentCategory.setUpdated(new Date());  
  17.         //插入节点到数据库  
  18.         contentCategoryMapper.saveAndGetId(contentCategory);  
  19.         //添加一个节点需要判断父节点是不是叶子节点,如果父节点是叶子节点的话,  
  20.         //需要改成父节点状态  
  21.         TbContentCategory parent = contentCategoryMapper.selectByPrimaryKey(parentId);  
  22.         if(!parent.getIsParent()){  
  23.             parent.setIsParent(true);  
  24.             contentCategoryMapper.updateByPrimaryKey(parent);  
  25.         }  
  26.         return TaotaoResult.ok(contentCategory);  
  27.     }  

       服务层写完后,我们再写Controller层,我们到taotao-manager-web工程的ContentCategoryController.java当中添加Controller方法,如下图所示。


       由于taotao-manager-dao工程和taotao-content工程都做了修改,因此我们重新打包taotao-manager-dao和taotao-content工程,然后重启taotao-manager、taotao-content和taotao-manager-web工程。重启后,我们到后台管理系统去增加两个分类,如下图所示,完全正确。

          做完了内容分类添加,下面我们实现以下内容分类修改和删除,其中我们需要先修改下content-category.jsp页面的删除请求的参数,因为树形结构的节点只有id、name、sate三个属性,并没有parentId属性,只有新增的节点给parentId赋值了,对于页面刚加载完的树形目录,节点是没有parentId属性的,因此我们把parentId这个参数去掉,我们只通过节点id便可以删除节点了。删除parentId参数后变为"$.post("/content/category/delete/",{id:node.id},function(){"


        下面我们到taotao-content-interface添加两个接口,分别是修改分类和删除分类接口,如下图所示。


     接口类代码如下:

[html]  view plain  copy
  1. package com.taotao.content.service;  
  2.   
  3. import java.util.List;  
  4.   
  5. import com.taotao.common.pojo.EasyUITreeNode;  
  6. import com.taotao.common.pojo.TaotaoResult;  
  7.   
  8. public interface ContentCategoryService {  
  9.     //获取内容分类列表  
  10.     List<EasyUITreeNode> getContentCategoryList(long parentId);  
  11.     //添加内容分类,注意参数名称要与content-category.jsp页面指定的参数名称一致  
  12.     TaotaoResult addContentCategory(long parentId,String name);  
  13.     //修改内容分类,注意参数名称要与content-category.jsp页面指定的参数名称一致  
  14.     TaotaoResult updateContentCategory(long id,String name);  
  15.     //删除内容分类,注意参数名称要与content-category.jsp页面指定的参数名称一致  
  16.     TaotaoResult deleteContentCategory(long id);  
  17. }  

     接着,我们到taotao-content-service来实现这两个接口,ContentCategoryServiceImpl全部代码如下所示。

[html]  view plain  copy
  1. package com.taotao.content.service.impl;  
  2.   
  3. import java.util.ArrayList;  
  4. import java.util.Date;  
  5. import java.util.List;  
  6.   
  7. import org.springframework.beans.factory.annotation.Autowired;  
  8. import org.springframework.stereotype.Service;  
  9.   
  10. import com.taotao.common.pojo.EasyUITreeNode;  
  11. import com.taotao.common.pojo.TaotaoResult;  
  12. import com.taotao.content.service.ContentCategoryService;  
  13. import com.taotao.mapper.TbContentCategoryMapper;  
  14. import com.taotao.pojo.TbContentCategory;  
  15. import com.taotao.pojo.TbContentCategoryExample;  
  16. import com.taotao.pojo.TbContentCategoryExample.Criteria;  
  17.   
  18. @Service  
  19. public class ContentCategoryServiceImpl implements ContentCategoryService {  
  20.     @Autowired  
  21.     private TbContentCategoryMapper contentCategoryMapper;  
  22.   
  23.     @Override  
  24.     public List<EasyUITreeNode> getContentCategoryList(long parentId) {  
  25.         //创建一个查询类  
  26.         TbContentCategoryExample contentCategoryExample = new TbContentCategoryExample();  
  27.         //设置查询条件  
  28.         Criteria criteria = contentCategoryExample.createCriteria();  
  29.         criteria.andParentIdEqualTo(parentId);  
  30.         //查询  
  31.         List<TbContentCategory> categoryList = contentCategoryMapper.selectByExample(contentCategoryExample);  
  32.         //将categoryList转换为List<EasyUITreeNode>  
  33.         List<EasyUITreeNode> resultList = new ArrayList<>();  
  34.         for(TbContentCategory contentCategory : categoryList){  
  35.             EasyUITreeNode easyUITreeNode = new EasyUITreeNode();  
  36.             easyUITreeNode.setId(contentCategory.getId());  
  37.             easyUITreeNode.setText(contentCategory.getName());  
  38.             easyUITreeNode.setState(contentCategory.getIsParent() ? "closed":"open");  
  39.             resultList.add(easyUITreeNode);  
  40.         }  
  41.         return resultList;  
  42.     }  
  43.   
  44.     @Override  
  45.     public TaotaoResult addContentCategory(long parentId, String name) {  
  46.         //实例化一个对象  
  47.         TbContentCategory contentCategory = new TbContentCategory();  
  48.         //填充属性值  
  49.         contentCategory.setParentId(parentId);  
  50.         contentCategory.setName(name);  
  51.         //状态。可选值:1(正常),2(删除),刚添加的节点肯定是正常的  
  52.         contentCategory.setStatus(1);  
  53.         //刚添加的节点肯定不是父节点  
  54.         contentCategory.setIsParent(false);  
  55.         //数据库中现在默认的都是1,所以这里我们也写成1  
  56.         contentCategory.setSortOrder(1);  
  57.         //保存当前操作时间  
  58.         contentCategory.setCreated(new Date());  
  59.         contentCategory.setUpdated(new Date());  
  60.         //插入节点到数据库  
  61.         contentCategoryMapper.saveAndGetId(contentCategory);  
  62.         //添加一个节点需要判断父节点是不是叶子节点,如果父节点是叶子节点的话,  
  63.         //需要改成父节点状态  
  64.         TbContentCategory parent = contentCategoryMapper.selectByPrimaryKey(parentId);  
  65.         if(!parent.getIsParent()){  
  66.             parent.setIsParent(true);  
  67.             contentCategoryMapper.updateByPrimaryKey(parent);  
  68.         }  
  69.         return TaotaoResult.ok(contentCategory);  
  70.     }  
  71.   
  72.     @Override  
  73.     public TaotaoResult updateContentCategory(long id, String name) {  
  74.         //通过id查询节点对象  
  75.         TbContentCategory contentCategory = contentCategoryMapper.selectByPrimaryKey(id);  
  76.         //判断新的name值与原来的值是否相同,如果相同则不用更新  
  77.         if(name != null && name.equals(contentCategory.getName())){  
  78.             return TaotaoResult.ok();  
  79.         }  
  80.         contentCategory.setName(name);  
  81.         //设置更新时间  
  82.         contentCategory.setUpdated(new Date());  
  83.         //更新数据库  
  84.         contentCategoryMapper.updateByPrimaryKey(contentCategory);  
  85.         //返回结果  
  86.         return TaotaoResult.ok();  
  87.     }  
  88.       
  89.     //通过父节点id来查询所有子节点,这是抽离出来的公共方法  
  90.     private List<TbContentCategory> getContentCategoryListByParentId(long parentId){  
  91.         TbContentCategoryExample example = new TbContentCategoryExample();  
  92.         Criteria criteria = example.createCriteria();  
  93.         criteria.andParentIdEqualTo(parentId);  
  94.         List<TbContentCategory> list = contentCategoryMapper.selectByExample(example);  
  95.         return list;  
  96.     }  
  97.       
  98.     //递归删除节点  
  99.     private void deleteNode(long parentId){  
  100.         List<TbContentCategory> list = getContentCategoryListByParentId(parentId);  
  101.         for(TbContentCategory contentCategory : list){  
  102.             contentCategory.setStatus(2);  
  103.             contentCategoryMapper.updateByPrimaryKey(contentCategory);  
  104.             if(contentCategory.getIsParent()){  
  105.                 deleteNode(contentCategory.getId());  
  106.             }  
  107.         }  
  108.     }  
  109.   
  110.     @Override  
  111.     public TaotaoResult deleteContentCategory(long id) {  
  112.         //删除分类,就是改节点的状态为2  
  113.         TbContentCategory contentCategory = contentCategoryMapper.selectByPrimaryKey(id);  
  114.         //状态。可选值:1(正常),2(删除)  
  115.         contentCategory.setStatus(2);  
  116.         contentCategoryMapper.updateByPrimaryKey(contentCategory);  
  117.         //我们还需要判断一下要删除的这个节点是否是父节点,如果是父节点,那么就级联  
  118.         //删除这个父节点下的所有子节点(采用递归的方式删除)  
  119.         if(contentCategory.getIsParent()){  
  120.             deleteNode(contentCategory.getId());  
  121.         }  
  122.         //需要判断父节点当前还有没有子节点,如果有子节点就不用做修改  
  123.         //如果父节点没有子节点了,那么要修改父节点的isParent属性为false即变为叶子节点  
  124.         TbContentCategory parent = contentCategoryMapper.selectByPrimaryKey(contentCategory.getParentId());  
  125.         List<TbContentCategory> list = getContentCategoryListByParentId(parent.getId());  
  126.         //判断父节点是否有子节点是判断这个父节点下的所有子节点的状态,如果状态都是2就说明  
  127.         //没有子节点了,否则就是有子节点。  
  128.         boolean flag = false;  
  129.         for(TbContentCategory tbContentCategory : list){  
  130.             if(tbContentCategory.getStatus() == 0){  
  131.                 flag = true;  
  132.                 break;  
  133.             }  
  134.         }  
  135.         //如果没有子节点了  
  136.         if(!flag){  
  137.             parent.setIsParent(false);  
  138.             contentCategoryMapper.updateByPrimaryKey(parent);  
  139.         }  
  140.         //返回结果  
  141.         return TaotaoResult.ok();  
  142.     }  
  143.   
  144. }  


      我们到ContentCategoryController暴露两个接口,如下图所示。



     代码如下:

[html]  view plain  copy
  1. @RequestMapping("/content/category/create")    
  2.     @ResponseBody    
  3.     public TaotaoResult addContentCategory(Long parentId,String name){    
  4.         TaotaoResult taotaoResult = contentCategoryService.addContentCategory(parentId, name);    
  5.         return taotaoResult;    
  6.     }    
  7.       
  8.     @RequestMapping("/content/category/update")    
  9.     @ResponseBody    
  10.     public TaotaoResult updateContentCategory(Long id,String name){    
  11.         TaotaoResult taotaoResult = contentCategoryService.updateContentCategory(id, name);    
  12.         return taotaoResult;    
  13.     }    
  14.         
  15.     @RequestMapping("/content/category/delete/")    
  16.     @ResponseBody    
  17.     public TaotaoResult deleteContentCategory(Long id){    
  18.         TaotaoResult taotaoResult = contentCategoryService.deleteContentCategory(id);    
  19.         return taotaoResult;    
  20.     }    


       代码写完了,我们重新打包taotao-content工程,然后重启taotao-content工程和taotao-manager-web工程。增加、修改、删除就都好使了。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值