Design and Implementation of an Online Course Purchase System(17)

Complete the analysis and implementation of CMS system

Posted by Chen Xingxu on June 3, 2020

易课寄在线购课系统开发笔记(十七)–完成CMS系统的分析与实现

内容分类管理

展示内容分类

功能分析

请求的 url:/content/category/list

请求的参数:id,当前节点的\id。第一次请求没有参数,需要给默认值 “0”

响应数据:List<EasyUITreeNode>(@ResponseBody)

Json 数据。

[{id:1,text:节点名称,state:open(closed)},

{id:2,text:节点名称2,state:open(closed)},

{id:3,text:节点名称3,state:open(closed)}]

业务逻辑:

1、取查询参数 id,parentId

2、根据 parentId 查询 ecourses_content_category,查询子节点列表。

3、得到List<EcoursesContentCategory>

4、把列表转换成List<EasyUITreeNode>

Dao 层

使用逆向工程

Service

参数:long parentId

返回值:List<EasyUITreeNode>

package cn.ecourses.content.service.impl;
//Content classification management Service
@Service
public class ContentCategoryServiceImpl implements ContentCategoryService {

	@Autowired
	private EcoursesContentCategoryMapper contentCategoryMapper;
	
	@Override
	public List<EasyUITreeNode> getContentCatList(long parentId) {
		// List of query subnodes based on parentid
		EcoursesContentCategoryExample example = new EcoursesContentCategoryExample();
		Criteria criteria = example.createCriteria();
		//Setting up query conditions
		criteria.andParentIdEqualTo(parentId);
		//Execute the query
		List<EcoursesContentCategory> catList = contentCategoryMapper.selectByExample(example);
		//Convert to EasyUITreeNode list
		List<EasyUITreeNode> nodeList = new ArrayList<>();
		for (EcoursesContentCategory ecoursesContentCategory : catList) {
			EasyUITreeNode node = new EasyUITreeNode();
			node.setId(ecoursesContentCategory.getId());
			node.setText(ecoursesContentCategory.getName());
			node.setState(ecoursesContentCategory.getIsParent()?"closed":"open");
			//Add to the list
			nodeList.add(node);
		}
		return nodeList;
	}

}

发布服务

<dubbo:service interface="cn.ecourses.content.service.ContentCategoryService" ref="contentCategoryServiceImpl" timeout="600000"/>

表现层

ecourses-bms-web 依赖 ecourses-content-interface 模块

springmvc.xml 中添加服务的引用

<dubbo:reference interface="cn.ecourses.content.service.ContentCategoryService" id="contentCategoryService" />

新增节点

功能分析

请求的url:/content/category/create 请求的参数: Long parentId,String name 响应的结果: JSON 数据,ECoursesResult,其中包含一个对象,对象有 id 属性,新产生的内容分类 id 业务逻辑: 1、接收两个参数:parentId、name 2、向 ecourses_content_category 表中插入数据。 a) 创建一个 EcoursesContentCategory 对象 b) 补全 EcoursesContentCategory 对象的属性 c) 向 ecourses_content_category 表中插入数据 3、判断父节点的 isparent 是否为 true,不是 true 需要改为 true。 4、需要主键返回。 5、返回 ECoursesResult,其中包装 EcoursesContentCategory 对象

Dao 层

可以使用逆向工程。需要添加主键返回:

注意:修改完代码后,需要向本地仓库安装 ecourses-bms-dao 包

Service层

参数:parentId、name 返回值:返回 ECoursesResult,其中包装 EcoursesContentCategory 对象

@Override
public ECoursesResult addContentCategory(long parentId, String name) {
    //Create a POJO object corresponding to the ecourses_content_category table
    EcoursesContentCategory contentCategory = new EcoursesContentCategory();
    //Setting the properties of the POJO
    contentCategory.setParentId(parentId);
    contentCategory.setName(name);
    //1(normal),2(delete)
    contentCategory.setStatus(1);
    //The default sort is 1
    contentCategory.setSortOrder(1);
    //The newly added node must be a leaf node
    contentCategory.setIsParent(false);
    contentCategory.setCreated(new Date());
    contentCategory.setUpdated(new Date());
    //Insert into the database
    contentCategoryMapper.insert(contentCategory);
    //Determine the isparent property of the parent node. If not true is changed to true
    //Query the parent node according to parentid
    EcoursesContentCategory parent = contentCategoryMapper.selectByPrimaryKey(parentId);
    if (!parent.getIsParent()) {
        parent.setIsParent(true);
        //Update to the database
        contentCategoryMapper.updateByPrimaryKey(parent);
    }
    //Return to the result, return to ECoursesResult, including POJO
    return ECoursesResult.ok(contentCategory);
}

发布服务

<dubbo:service interface="cn.ecourses.content.service.ContentCategoryService" ref="contentCategoryServiceImpl" timeout="600000"/>

表现层

请求的url:/content/category/create

请求的参数:

Long parentId,String name

响应的结果:

JSON 数据,ECoursesResult

@RequestMapping(value="/create", method=RequestMethod.POST)
@ResponseBody
public ECoursesResult createContentCategory(Long parentId, String name) {
    //调用服务添加节点
    ECoursesResult ecoursesResult = contentCategoryService.addContentCategory(parentId, name);
    return ecoursesResult;
}

内容分类重命名

请求的 url:/content/category/update 参数:id,当前节点id。name,重命名后的名称。 业务逻辑:根据 id 更新记录。 返回值:返回 ECoursesResult.ok()

Dao 层

可以使用逆向工程。

Service层

参数:Long id, String name 返回值:返回 ECoursesResult

@Override
public ECoursesResult updateContentCategory(Long id, String name) {
    //创建一个pojo
    EcoursesContentCategory contentCategory = contentCategoryMapper.selectByPrimaryKey(id);
    contentCategory.setName(name);
    contentCategoryMapper.updateByPrimaryKey(contentCategory);
    return ECoursesResult.ok();
}

表现层

请求的 url:/content/category/update 参数:Long id, String name 返回值:ECoursesResult

@RequestMapping("/update")
@ResponseBody
public ECoursesResult updateNode(Long id, String name) {
    ECoursesResult result = contentCategoryService.updateContentCategory(id, name);
    return result;
}

内容分类删除结点

请求的url:/content/category/delete/

参数:id,当前节点的 id。

响应的数据:JSON ECoursesResult

业务逻辑:

1、根据 id 删除记录。

2、判断父节点下是否还有子节点,如果没有需要把父节点的 isparent 改为 false

3、如果删除的是父节点,子节点要级联删除。

两种解决方案:

1)如果判断是父节点不允许删除。

2)递归删除。

Dao 层

可以使用逆向工程。

Service层

参数:Long id 返回值:ECoursesResult

@Override
public ECoursesResult deleteContentCategory(Long id) {
    deleteCategoryAndChildNode(id);
    return ECoursesResult.ok();
}

@Override
public List<EcoursesContentCategory> getChildNodeList(Long id) {
    //查询所有父节点为传入id的节点
    EcoursesContentCategoryExample example = new EcoursesContentCategoryExample();
    Criteria criteria = example.createCriteria();
    criteria.andParentIdEqualTo(id);
    //返回所有符合要求的节点
    return contentCategoryMapper.selectByExample(example);
}

@Override
public void deleteCategoryAndChildNode(Long id) {
    //获取要删除的Category
    EcoursesContentCategory ecContentCategory = new EcoursesContentCategory();
    ecContentCategory = contentCategoryMapper.selectByPrimaryKey(id);

    //判断是否为父节点
    if(ecContentCategory.getIsParent()){
        //获得所有该节点下的孩子节点
        List<EcoursesContentCategory> list = getChildNodeList(id);
        //删除所有孩子节点
        for(EcoursesContentCategory category : list){
            deleteCategoryAndChildNode(category.getId());
        }
    }
    //判断父节点下是否还有其他子节点
    if(getChildNodeList(ecContentCategory.getParentId()).size()==1){
        //没有则将父节点标记为叶子节点
        EcoursesContentCategory parentCategory = contentCategoryMapper.selectByPrimaryKey(ecContentCategory.getParentId());
        parentCategory.setIsParent(false);
        contentCategoryMapper.updateByPrimaryKey(parentCategory);

    }
    //删除本节点
    contentCategoryMapper.deleteByPrimaryKey(id);
    return;
}

表现层

请求的 url:/content/category/delete 参数:Long id 返回值:ECoursesResult

@RequestMapping("/delete")
@ResponseBody
public ECoursesResult deleteNode(Long id) {
    ECoursesResult result = contentCategoryService.deleteContentCategory(id);
    return result;
}

内容管理

功能点分析

1、内容列表查询

2、新增内容

3、编辑内容

4、删除内容

内容列表查询

请求的 url:/content/query/list

参数:categoryId 分类 id

响应的数据:JSON 数据

{total:查询结果总数量,rows[{id:1,title:aaa,subtitle:bb,…}]}

EasyUIDataGridResult

描述课程数据 List<EcoursesContent>

查询的表:ecourses_content

业务逻辑:

根据内容分类 id 查询内容列表。要进行分页处理。

Dao 层

可以使用逆向工程。

Service层

参数:Long categoryId, int page, int rows 返回值:EasyUIDataGridResult

@Override
public EasyUIDataGridResult queryContentList(Long categoryId, int page, int rows) {
    //分页处理
    PageHelper.startPage(page, rows);
            //查询课程列表
    EcoursesContentExample example = new EcoursesContentExample();
    Criteria criteria = example.createCriteria();
    criteria.andCategoryIdEqualTo(categoryId);
    List<EcoursesContent> list = contentMapper.selectByExampleWithBLOBs(example);
    //取记录总条数
    PageInfo<EcoursesContent> pageInfo = new PageInfo<>(list);
            //创建EasyUIDataGridResult结果集
    EasyUIDataGridResult result = new EasyUIDataGridResult();
    result.setRows(list);
    result.setTotal(pageInfo.getTotal());
    return result;
}

表现层

请求的 url:/content/query/list 参数:Long categoryId, int page, int rows 返回值:EasyUIDataGridResult

@RequestMapping("/query/list")
@ResponseBody
public EasyUIDataGridResult queryContentList(Long categoryId, int page, int rows) {
    return contentService.queryContentList(categoryId, page, rows);
}

新增内容

功能分析

新增内容,必须指定一个内容分类。

提交表单请求的 url:/content/save 参数:表单的数据。使用 pojo 接收 EcoursesContent 返回值:ECoursesResult(json 数据) 业务逻辑: 1、把 EcoursesContent 对象属性补全。 2、向 ecourses_content 表中插入数据。 3、返回 ECoursesResult

Dao 层

可以使用逆向工程。

Service 层

参数:EcoursesContent content 返回值:ECoursesResult

@Override
public ECoursesResult addContent(EcoursesContent content) {
    //将内容数据插入到内容表
    content.setCreated(new Date());
    content.setUpdated(new Date());
    //插入到数据库
    contentMapper.insert(content);
    //缓存同步,删除缓存中对应的数据。
    jedisClient.hdel(CONTENT_LIST, content.getCategoryId().toString());
    return ECoursesResult.ok();
}

表现层

请求的 url:/content/save 参数:EcoursesContent content 返回值:ECoursesResult

@RequestMapping(value="/save", method=RequestMethod.POST)
@ResponseBody
public ECoursesResult addContent(EcoursesContent content) {
    //调用服务把内容数据保存到数据库
    ECoursesResult ecoursesResult = contentService.addContent(content);
    return ecoursesResult;
}

编辑内容

Dao 层

可以使用逆向工程。

Service 层

参数:EcoursesContent content 返回值:ECoursesResult

@Override
public ECoursesResult updateContent(EcoursesContent content) {
    //将内容数据插入到内容表
    content.setUpdated(new Date());
    //插入到数据库
    contentMapper.updateByPrimaryKeySelective(content);
    //缓存同步,删除缓存中对应的数据。
    jedisClient.hdel(CONTENT_LIST, content.getCategoryId().toString());
    return ECoursesResult.ok();
}

表现层

请求的 url:/content/edit 参数:EcoursesContent content 返回值:ECoursesResult

@RequestMapping(value="/edit", method=RequestMethod.POST)
@ResponseBody
public ECoursesResult editParam(EcoursesContent content) {
    ECoursesResult result = contentService.updateContent(content);
    return result;
}

删除内容

Dao 层

可以使用逆向工程。

Service 层

参数:String ids 返回值:ECoursesResult

@Override
public ECoursesResult deleteContentByIds(String ids) {
    String[] idArray = ids.split(","); 
    for (String id : idArray) {  
        contentMapper.deleteByPrimaryKey(Long.valueOf(id));  
    }  
    return ECoursesResult.ok();
}

表现层

请求的 url:/content/delete 参数:String ids 返回值:ECoursesResult

@RequestMapping("/delete")
@ResponseBody
public ECoursesResult deleteParam(@RequestParam("ids") String ids) {
    ECoursesResult result = contentService.deleteContentByIds(ids);
    return result;
}

发布服务

<dubbo:service interface="cn.ecourses.content.service.ContentService" ref="contentServiceImpl" timeout="600000"/>

引用服务

ecourses-bms-web 工程中引用

<dubbo:reference interface="cn.ecourses.content.service.ContentService" id="contentService" />