• (转)淘淘商城系列——内容分类管理


    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工程。重启成功后,我们到后台管理系统去增加两个分类,如下图所示。 
     
    至此,新增节点这个功能就已实现!真是不容易啊!

    重命名节点

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

    删除节点

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

  • 相关阅读:
    04-struts2框架中获取servlet api及Result结果类型
    03-Action类的创建方式及访问
    一位资深程序员大牛给予Java初学者的学习建议(转)
    C++中数组指针
    Ubuntu 开机出现 grub rescue> 终端模式修复方法
    windows和linux双系统下扩容方法
    C 字符串处理
    C++类中变量定义初始化总结
    python创建xml
    OpenBlas compile centOS6.7 ./kernel/x86_64/dgemm_kernel_4x4_haswell.S:2548: Error: no such instruction: `vpermpd $
  • 原文地址:https://www.cnblogs.com/telwanggs/p/6945942.html
Copyright © 2020-2023  润新知