zoukankan      html  css  js  c++  java
  • (转)淘淘商城系列——内容分类管理

    http://blog.csdn.net/yerenyuan_pku/article/details/72837691

    通过上文的学习,我们已经学会搭建内容管理系统这个工程,本文我们就来学习如何进行内容分类管理。

    展示内容分类

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

    我们再来看下content-category.jsp页面,这个页面就是内容分类页面,页面中的<ul id="contentCategory" class="easyui-tree">是用来展示内容分类树的,$(function(){...})是在页面加载完后要调用的js代码,下面这段代码是用来获取分类列表数据的,发起的url请求是/content/category/list。 

    • animate:true的意思是设置动画,如果设置为true,展开树形结构时是慢慢展开的效果;如果设置为false,展开树形结构就一下子展开了。
    • method:"GET"指定发起的是GET请求。


    接下来,我们来编写Service层的代码。首先在taotao-content-interface工程下的com.taotao.content.service包中新建一个接口——ContentCategoryService.java,并在接口中添加一个getContentCatList方法,如下图所示。

    从中可以看出方法的返回值是EasyUITreeNode的集合,EasyUITreeNode类的内容如下所示。 

    • id是树节点的id。
    • text是节点的名称。
    • state是指树形是闭合的还是打开的,如果当前节点还有子节点,那么state的值是”closed”,如果当前节点已经是叶子节点了,那么state的值是”open”。

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

    为方便大家复制,将该实现类代码贴出,如下:

    /**
     * 内容分类管理服务
     * <p>Title: ContentCategoryServiceImpl</p>
     * <p>Description: </p>
     * <p>Company: www.itcast.cn</p> 
     * @version 1.0
     */
    @Service
    public class ContentCategoryServiceImpl implements ContentCategoryService {
    
        @Autowired
        private TbContentCategoryMapper contentCategoryMapper;
    
        @Override
        public List<EasyUITreeNode> getContentCatList(long parentId) {
            // 根据parentId查询子节点列表
            TbContentCategoryExample example = new TbContentCategoryExample();
            // 设置查询条件
            Criteria criteria = example.createCriteria();
            criteria.andParentIdEqualTo(parentId);
            // 执行查询
            List<TbContentCategory> list = contentCategoryMapper.selectByExample(example);
            // 返回结果为List
            List<EasyUITreeNode> resultList = new ArrayList<EasyUITreeNode>();
            for (TbContentCategory tbContentCategory : list) {
                EasyUITreeNode node = new EasyUITreeNode();
                node.setId(tbContentCategory.getId());
                node.setText(tbContentCategory.getName());
                node.setState(tbContentCategory.getIsParent() ? "closed" : "open");
                // 添加到列表
                resultList.add(node);
            }
            return resultList;
        }
    
    }
    • 1

    下面我们发布一下该服务的这个接口,我们在taotao-content-service工程的spring目录下的applicationContext-service.xml配置文件中添加如下配置:

    <!-- 声明需要暴露的服务接口 -->
    <dubbo:service interface="com.taotao.content.service.ContentCategoryService" ref="contentCategoryServiceImpl" timeout="300000" />


    注意:dubbo服务向外暴露的端口应该由20880改为20881(每发布一个服务就要更改一个端口)。因为taotao-manager服务绑定的端口号是20880,现在我们又起了一个服务(taotao-content),但是它们在同一台服务器上,同一台服务器上的一个端口只能被一个服务绑定。 
    然后我们再来编写表现层的代码。我们需要在taotao-manager-web工程中添加Controller类来实现内容分类展示,前提是我们需要先添加对taotao-content-interface的依赖,如下图所示。 

    接着我们需要在taotao-manager-web工程的springmvc.xml配置文件中添加对ContentCategoryService的引用,即要向springmvc.xml配置文件中添加如下配置:

    <dubbo:reference interface="com.taotao.content.service.ContentCategoryService" id="contentCategoryService" />
    • 1
    • 1


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

    ContentCategoryController类的代码如下,这里需要注意的是,第一次查询内容分类的时候是没有参数的,因此需要指定一个默认值0,后续点击要展开某个节点的话,就会把该节点的id传过来了。

    /**
     * 内容分类管理Controller
     * <p>Title: ContentCategoryController</p>
     * <p>Description: </p>
     * <p>Company: www.itcast.cn</p> 
     * @version 1.0
     */
    @Controller
    public class ContentCategoryController {
    
        @Autowired
        private ContentCategoryService contentCategoryService;
    
        @RequestMapping("/content/category/list")
        @ResponseBody
        public List<EasyUITreeNode> getContentCatList(@RequestParam(defaultValue="0") Long id) {
            return contentCategoryService.getContentCatList(id);
        }
    
    
    }
    • 1

    在启动测试之前,我们需要先打包taotao-content到本地maven仓库。由于查询内容分类列表涉及到了taotao-manager和taotao-content这两个服务和taotao-manager-web,所以我们依次启动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方法。 

    编写的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是我们操作的节点的id。
    • var _node = tree.tree('find',0);:意思是在树中找到id为0的节点(由于新建的节点暂时定义id为0,因此会找到刚添加的节点)。
    • tree.tree("select",_node.target).tree('beginEdit',_node.target);:这行代码的意思是让新建的节点处于可编辑状态。

    我们从menuHandler方法中可以看到实际添加节点的操作不在这个方法中,这个方法真正执行的操作是删除节点,如下图所示。 

    以上这段代码的意思便是去发起url为”/content/category/delete/”的请求,传递的参数是父级id和要删除的节点的id。function(){...}指代回调函数,其中tree.tree("remove",node.target);的意思就是从树形结构中删掉这个节点。 
    既然添加节点的操作不在menuHandler这个方法中,那么实际进行添加节点到数据库表中的操作是在哪儿控制的呢?如下图所示的onAfterEdit事件。 

    • 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,即将id从0更新为添加到数据库中的节点的id,data.data.id就是指添加到数据库中的节点的id。
    • if(node.id == 0)条件不成立,则说明不是添加新节点操作,而是更新节点操作,其中$.post("/content/category/update",{id:node.id,name:node.text});的意思是请求”/content/category/update”的url,传递的参数有节点id、节点名称。

    以上js代码要是让我自己写,我肯定是写不出来的,本人对jQuery仍然比较陌生,这确实是一个致命伤。我勉强分析完了以上那些js代码,下面我们便来一一实现内容分类的添加、修改、删除功能。 
    我们首先实现新增节点这个功能,由于都是单表操作,因此使用逆向工程生成的代码足以满足要求了,直接修改服务层即可,我们到taotao-content-interface工程添加一个方法,如下图所示。 

    从insertContentCat方法中可以看出其接收两个参数:parentId、name,这与content-category.jsp页面传递过来的参数是一致的,分别是父级id和节点的名称。我们还可以看出该方法返回TaotaoResult对象,它里面包装了TbContentCategory对象。 
    下面我们到taotao-content-service工程中去实现这个接口,不过在此之前,由于逆向工程自动生成的insert方法不会自动帮我们给主键的值赋值,所以我们需要添加主键返回,即需要在TbContentCategoryMapper.xml文件中新增一段sql片段,如下: 

    之所以这样做是因为我们需要用到这个id给树形结构中新增加的节点id赋值,而在TbContentCategoryMapper.xml文件中新增的sql片段就是给新添加的对象的主键赋值的。 
    注意:修改完TbContentCategoryMapper.xml映射文件后,需要向本地仓库安装taotao-manager-dao包。 
    做好以上准备后,我们到ContentCategoryServiceImpl类中实现添加内容分类的方法了,如下所示。 

    为方便大家复制,现把ContentCategoryServiceImpl实现类中的insertContentCat方法贴出。

    @Override
    public TaotaoResult insertContentCat(long parentId, String name) {
        // 创建一个内容分类对象
        TbContentCategory contentCategory = new TbContentCategory();
        contentCategory.setName(name);
        contentCategory.setParentId(parentId);
        // 新添加的节点都是叶子节点
        contentCategory.setIsParent(false);
        // 排序方法默认设置为1
        contentCategory.setSortOrder(1);
        // 分类状态:1(正常),2(删除)
        contentCategory.setStatus(1);
        contentCategory.setCreated(new Date());
        contentCategory.setUpdated(new Date());
        // 插入节点
        contentCategoryMapper.insert(contentCategory);
        // 判断父节点是否为叶子节点,为何要判断?
        TbContentCategory parentNode = contentCategoryMapper.selectByPrimaryKey(parentId);
        if (!parentNode.getIsParent()) {
            parentNode.setIsParent(true);
            // 更新父节点
            contentCategoryMapper.updateByPrimaryKey(parentNode);
        }
        return TaotaoResult.ok(contentCategory); // contentCategory对象里面是包含id属性的
    }

    服务层写完后,我们再写表现层的代码,我们到taotao-manager-web工程的ContentCategoryController类当中添加一个insertContentCat方法,如下图所示。 

    由于taotao-manager-dao工程和taotao-content工程都做了修改,因此我们重新打包taotao-manager-dao(上面修改完TbContentCategoryMapper.xml映射文件就已打包了)和taotao-content工程,然后重启taotao-manager、taotao-content和taotao-manager-web工程。重启成功后,我们到后台管理系统去增加两个分类,如下图所示。 
     
    至此,新增节点这个功能就已实现!真是不容易啊!

    重命名节点

    由于时间紧张,在此并不实现该功能,留待以后开发。未完,待续。。。敬请期待。

    删除节点

    由于时间紧张,在此并不实现该功能,留待以后开发。未完,待续。。。敬请期待。

  • 相关阅读:
    suse12安装详解
    Centos7上部署openstack mitaka配置详解(将疑难点都进行划分)
    菜鸟帮你跳过openstack配置过程中的坑[文末新添加福利]
    openstack中dashboard页面RuntimeError: Unable to create a new session key. It is likely that the cache is unavailable.
    Multiple network matches found for name 'selfservice', use an ID to be more specific.报错
    查看 SELinux状态及关闭SELinux
    SELinux深入理解
    IP地址、子网掩码、网络号、主机号、网络地址、主机地址
    Oracle job procedure 存储过程定时任务
    POI文件导出至EXCEL,并弹出下载框
  • 原文地址:https://www.cnblogs.com/telwanggs/p/6945942.html
Copyright © 2011-2022 走看看