【实战】6-2 分类管理开发
来源:互联网 发布:上海 风情 知乎 编辑:程序博客网 时间:2024/06/05 03:44
前言
商品分类模块给它设计的接口暂时不多,这一章节也比较简单,除了一个递归获取所有子节点的接口外~
接下来就一个一个文件的放出来,大家直接参考和看代码中的注释就好了。
controller设计
这里在controller/backend包下创建CategoryManageController.java,专门用来控制对商品分类的操作。
功能大部分还是在service中实现的,这里主要是把session中的相关信息拿出来,并做一些简单的判断,如是否登录,是否是管理员等。
注意使用了一个新的注解@RequestParam(value = “parentId”,defaultValue = “0”)可以实现不传参数情况下的默认参数(感觉这些注解实现了很强大的功能,有时间要好好了解一下具体的实现原理)。
package top.winxblast.happymall.controller.backend;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Controller;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RequestMethod;import org.springframework.web.bind.annotation.RequestParam;import org.springframework.web.bind.annotation.ResponseBody;import top.winxblast.happymall.common.Const;import top.winxblast.happymall.common.ResponseCode;import top.winxblast.happymall.common.ServerResponse;import top.winxblast.happymall.pojo.User;import top.winxblast.happymall.service.CategoryService;import top.winxblast.happymall.service.UserService;import javax.servlet.http.HttpSession;/** * 目录管理模块 * * @author winxblast * @create 2017/10/28 **/@Controller@RequestMapping(value = "/manage/category")public class CategoryManageController { @Autowired private UserService userService; @Autowired private CategoryService categoryService; /** * 添加商品类别 * 添加这个注解@RequestParam(value = "parentId",defaultValue = "0")主要是为了没有传这个参数时有个默认值。 * @param session 通过session验证用户是否已登录以及是否为管理员 * @param categoryName * @param parentId * @return */ @RequestMapping(value = "add_category.do", method = RequestMethod.GET) @ResponseBody public ServerResponse<String> addCategory(HttpSession session, String categoryName, @RequestParam(value = "parentId",defaultValue = "0") int parentId) { User user = (User)session.getAttribute(Const.CURRENT_USER); if(user == null) { return ServerResponse.createByErrorCodeMessage(ResponseCode.NEED_LOGIN.getCode(), "用户未登录,请登录"); } //校验是否为管理员,功能放到service中 if(userService.checkAdminRole(user).isSuccess()) { //是管理员 //增加处理分类的逻辑 return categoryService.addCategory(categoryName, parentId); } else { return ServerResponse.createByErrorMessage("无权限,需要管理员权限"); } } /** * 修改品类名称 * @param session * @param categoryId * @param categoryName * @return */ @RequestMapping(value = "set_category_name.do", method = RequestMethod.GET) @ResponseBody public ServerResponse<String> setCategoryName(HttpSession session, Integer categoryId, String categoryName) { User user = (User)session.getAttribute(Const.CURRENT_USER); if(user == null) { return ServerResponse.createByErrorCodeMessage(ResponseCode.NEED_LOGIN.getCode(), "用户未登录,请登录"); } //校验是否为管理员,功能放到service中 if(userService.checkAdminRole(user).isSuccess()) { //是管理员 //更新categoryName return categoryService.updateCategoryName(categoryId, categoryName); }else { return ServerResponse.createByErrorMessage("无权限,需要管理员权限"); } } /** * 通过父类id获取下一级子分类 * @param session * @param categoryId 不传参数默认为0 * @return */ @RequestMapping(value = "get_category.do", method = RequestMethod.GET) @ResponseBody public ServerResponse getChildrenParallelCategory(HttpSession session, @RequestParam(value = "categoryId", defaultValue = "0")Integer categoryId) { User user = (User)session.getAttribute(Const.CURRENT_USER); if(user == null) { return ServerResponse.createByErrorCodeMessage(ResponseCode.NEED_LOGIN.getCode(), "用户未登录,请登录"); } //校验管理员 if(userService.checkAdminRole(user).isSuccess()) { //查询子节点的category信息,并且不递归,只查询下一级 return categoryService.getChildrenParallelCategory(categoryId); } else { return ServerResponse.createByErrorMessage("无权限,需要管理员权限"); } } /** * 通过递归查询该分类下所有子分类 * 这个方法的名字取的我也是醉了···最讨厌取名字了,这里老师取名感觉也是随意 * @param session * @param categoryId 不传参数默认为0 * @return */ @RequestMapping(value = "get_deep_category.do", method = RequestMethod.GET) @ResponseBody public ServerResponse getCategoryAndDeepChildrenCategory(HttpSession session, @RequestParam(value = "categoryId", defaultValue = "0")Integer categoryId) { User user = (User)session.getAttribute(Const.CURRENT_USER); if(user == null) { return ServerResponse.createByErrorCodeMessage(ResponseCode.NEED_LOGIN.getCode(), "用户未登录,请登录"); } //校验管理员 if(userService.checkAdminRole(user).isSuccess()) { //查询当前节点及递归子节点的id return categoryService.selectCategoryAndChildrenById(categoryId); } else { return ServerResponse.createByErrorMessage("无权限,需要管理员权限"); } }}
service设计
先给出接口的定义把CategoryService。后来我按照阿里巴巴Java规约的一些习惯把接口命名前面的大写“I”去掉了,直接使用xxService,然后在实现类后面加上Impl。
package top.winxblast.happymall.service;import top.winxblast.happymall.common.ServerResponse;import top.winxblast.happymall.pojo.Category;import java.util.List;/** * 分类操作模块接口 * * @author winxblast * @create 2017/10/28 **/public interface CategoryService { ServerResponse<String> addCategory(String categoryName, Integer parentId); ServerResponse<String> updateCategoryName(Integer categoryId, String categoryName); ServerResponse<List<Category>> getChildrenParallelCategory(Integer categoryId); ServerResponse selectCategoryAndChildrenById(Integer categoryId);}
然后是接口的实现类。这里混用了google的guava和Apache的commons,网上讨论也比较多,暂时还没有精力去分辨那个好,这里就先按老师写的混用着。
至于以后工作中那就看同事用什么就用什么啦
package top.winxblast.happymall.service.impl;import com.google.common.collect.Lists;import com.google.common.collect.Sets;import org.apache.commons.collections.CollectionUtils;import org.apache.commons.lang3.StringUtils;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Service;import top.winxblast.happymall.common.ServerResponse;import top.winxblast.happymall.dao.CategoryMapper;import top.winxblast.happymall.pojo.Category;import top.winxblast.happymall.service.CategoryService;import java.util.List;import java.util.Set;/** * 分类模块接口实现类 * * @author winxblast * @create 2017/10/28 **/@Service("categoryService")public class CategoryServiceImpl implements CategoryService { private Logger logger = LoggerFactory.getLogger(CategoryServiceImpl.class); @Autowired private CategoryMapper categoryMapper; /** * 添加品类 * @param categoryName 品类名称 * @param parentId 父品类id,SpringMVC中默认使用0,如果没有传入 * @return */ @Override public ServerResponse<String> addCategory(String categoryName, Integer parentId) { if(parentId == null || StringUtils.isBlank(categoryName)) { return ServerResponse.createByErrorMessage("添加品类参数错误"); } Category category = new Category(); category.setName(categoryName); category.setParentId(parentId); category.setStatus(true);//表示这个分类是可用的,有效的 int rowCount = categoryMapper.insert(category); if(rowCount > 0) { return ServerResponse.createBySuccessMessage("添加品类成功"); } return ServerResponse.createByErrorMessage("添加品类失败"); } /** * 修改品类名字 * @param categoryId * @param categoryName * @return */ @Override public ServerResponse<String> updateCategoryName(Integer categoryId, String categoryName) { if(categoryId == null || StringUtils.isBlank(categoryName)) { return ServerResponse.createByErrorMessage("更新品类参数错误"); } Category category = new Category(); category.setId(categoryId); category.setName(categoryName); int rowCount = categoryMapper.updateByPrimaryKeySelective(category); if(rowCount > 0) { return ServerResponse.createBySuccessMessage("更改品类名字成功"); } return ServerResponse.createByErrorMessage("更改品类名字失败"); } /** * 仅获取下一级分类 * @param categoryId * @return */ @Override public ServerResponse<List<Category>> getChildrenParallelCategory(Integer categoryId) { List<Category> categoryList = categoryMapper.selectCategoryChildrenByParentId(categoryId); if(CollectionUtils.isEmpty(categoryList)) { //这里没有子分类为什么打印日志比较好呢,应该可以有其他处理方法,这里按照老师的讲解来 logger.info("未找到当前分类的子分类"); } return ServerResponse.createBySuccess(categoryList); } /** * 递归查询本节点id和孩子节点id * 和下面一个private方法联合使用 * @param categoryId * @return */ @Override public ServerResponse selectCategoryAndChildrenById(Integer categoryId) { //这个跟我平时不一样,用的谷歌的一个包来初始化,里面也有很多方便的工具 Set<Category> categorySet = Sets.newHashSet(); findChildCatgory(categorySet,categoryId); //同样是谷歌guava里的方法 List<Integer> categoryIdList = Lists.newArrayList(); if(categoryId != null) { for (Category categoryItem : categorySet) { categoryIdList.add(categoryItem.getId()); } } return ServerResponse.createBySuccess(categoryIdList); } /** * 这里要重写Category的hashcode和equals方法 * 递归算法算出子节点 */ private Set<Category> findChildCatgory(Set<Category> categorySet, Integer categoryId) { Category category = categoryMapper.selectByPrimaryKey(categoryId); if(category != null) { categorySet.add(category); } //查找子节点,递归算法一定要有停止条件 List<Category> categoryList = categoryMapper.selectCategoryChildrenByParentId(categoryId); //由于mybatis的设计,如果没有查询结果,也不会返回null,所以下面不用进行null判断 for (Category categoryItem : categoryList) { findChildCatgory(categorySet, categoryItem.getId()); } return categorySet; }}
注意这里重写了category的hashcode和equals方法,因为要把按我们想要的方式放进hashset中。这两个方法的重写直接使用idea提供的方法就可以了。
dao层
对于数据库的操作,在mybatis generator的基础上,自己就添加了一个方法,以下为相关接口及xml配置内容,我自己添加的内容在两个文件的最后部分。
CategoryMapper.java
package top.winxblast.happymall.dao;import top.winxblast.happymall.pojo.Category;import java.util.List;public interface CategoryMapper { /** * This method was generated by MyBatis Generator. * This method corresponds to the database table happymall_category * * @mbggenerated Sun Oct 08 14:03:47 CST 2017 */ int deleteByPrimaryKey(Integer id); /** * This method was generated by MyBatis Generator. * This method corresponds to the database table happymall_category * * @mbggenerated Sun Oct 08 14:03:47 CST 2017 */ int insert(Category record); /** * This method was generated by MyBatis Generator. * This method corresponds to the database table happymall_category * * @mbggenerated Sun Oct 08 14:03:47 CST 2017 */ int insertSelective(Category record); /** * This method was generated by MyBatis Generator. * This method corresponds to the database table happymall_category * * @mbggenerated Sun Oct 08 14:03:47 CST 2017 */ Category selectByPrimaryKey(Integer id); /** * This method was generated by MyBatis Generator. * This method corresponds to the database table happymall_category * * @mbggenerated Sun Oct 08 14:03:47 CST 2017 */ int updateByPrimaryKeySelective(Category record); /** * This method was generated by MyBatis Generator. * This method corresponds to the database table happymall_category * * @mbggenerated Sun Oct 08 14:03:47 CST 2017 */ int updateByPrimaryKey(Category record); /** * 通过父类Id查看下一级子分类的情况 * @param parentId * @return */ List<Category> selectCategoryChildrenByParentId(Integer parentId);}
CategoryMapper.xml大部分都是自动生成的,自己写的部分也没有特别大的难度。
<?xml version="1.0" encoding="UTF-8" ?><!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" ><mapper namespace="top.winxblast.happymall.dao.CategoryMapper" > <resultMap id="BaseResultMap" type="top.winxblast.happymall.pojo.Category" > <!-- WARNING - @mbggenerated This element is automatically generated by MyBatis Generator, do not modify. This element was generated on Sun Oct 08 14:03:47 CST 2017. --> <constructor > <idArg column="id" jdbcType="INTEGER" javaType="java.lang.Integer" /> <arg column="parent_id" jdbcType="INTEGER" javaType="java.lang.Integer" /> <arg column="name" jdbcType="VARCHAR" javaType="java.lang.String" /> <arg column="status" jdbcType="BIT" javaType="java.lang.Boolean" /> <arg column="sort_order" jdbcType="INTEGER" javaType="java.lang.Integer" /> <arg column="create_time" jdbcType="TIMESTAMP" javaType="java.util.Date" /> <arg column="update_time" jdbcType="TIMESTAMP" javaType="java.util.Date" /> </constructor> </resultMap> <sql id="Base_Column_List" > <!-- WARNING - @mbggenerated This element is automatically generated by MyBatis Generator, do not modify. This element was generated on Sun Oct 08 14:03:47 CST 2017. --> id, parent_id, name, status, sort_order, create_time, update_time </sql> <select id="selectByPrimaryKey" resultMap="BaseResultMap" parameterType="java.lang.Integer" > <!-- WARNING - @mbggenerated This element is automatically generated by MyBatis Generator, do not modify. This element was generated on Sun Oct 08 14:03:47 CST 2017. --> select <include refid="Base_Column_List" /> from happymall_category where id = #{id,jdbcType=INTEGER} </select> <delete id="deleteByPrimaryKey" parameterType="java.lang.Integer" > <!-- WARNING - @mbggenerated This element is automatically generated by MyBatis Generator, do not modify. This element was generated on Sun Oct 08 14:03:47 CST 2017. --> delete from happymall_category where id = #{id,jdbcType=INTEGER} </delete> <insert id="insert" parameterType="top.winxblast.happymall.pojo.Category" > <!-- WARNING - @mbggenerated This element is automatically generated by MyBatis Generator, do not modify. This element was generated on Sun Oct 08 14:03:47 CST 2017. --> insert into happymall_category (id, parent_id, name, status, sort_order, create_time, update_time) values (#{id,jdbcType=INTEGER}, #{parentId,jdbcType=INTEGER}, #{name,jdbcType=VARCHAR}, #{status,jdbcType=BIT}, #{sortOrder,jdbcType=INTEGER}, now(), now()) </insert> <insert id="insertSelective" parameterType="top.winxblast.happymall.pojo.Category" > <!-- WARNING - @mbggenerated This element is automatically generated by MyBatis Generator, do not modify. This element was generated on Sun Oct 08 14:03:47 CST 2017. --> insert into happymall_category <trim prefix="(" suffix=")" suffixOverrides="," > <if test="id != null" > id, </if> <if test="parentId != null" > parent_id, </if> <if test="name != null" > name, </if> <if test="status != null" > status, </if> <if test="sortOrder != null" > sort_order, </if> <if test="createTime != null" > create_time, </if> <if test="updateTime != null" > update_time, </if> </trim> <trim prefix="values (" suffix=")" suffixOverrides="," > <if test="id != null" > #{id,jdbcType=INTEGER}, </if> <if test="parentId != null" > #{parentId,jdbcType=INTEGER}, </if> <if test="name != null" > #{name,jdbcType=VARCHAR}, </if> <if test="status != null" > #{status,jdbcType=BIT}, </if> <if test="sortOrder != null" > #{sortOrder,jdbcType=INTEGER}, </if> <if test="createTime != null" > now(), </if> <if test="updateTime != null" > now(), </if> </trim> </insert> <update id="updateByPrimaryKeySelective" parameterType="top.winxblast.happymall.pojo.Category" > <!-- WARNING - @mbggenerated This element is automatically generated by MyBatis Generator, do not modify. This element was generated on Sun Oct 08 14:03:47 CST 2017. --> update happymall_category <set > <if test="parentId != null" > parent_id = #{parentId,jdbcType=INTEGER}, </if> <if test="name != null" > name = #{name,jdbcType=VARCHAR}, </if> <if test="status != null" > status = #{status,jdbcType=BIT}, </if> <if test="sortOrder != null" > sort_order = #{sortOrder,jdbcType=INTEGER}, </if> <if test="createTime != null" > create_time = #{createTime,jdbcType=TIMESTAMP}, </if> <if test="updateTime != null" > now(), </if> </set> where id = #{id,jdbcType=INTEGER} </update> <update id="updateByPrimaryKey" parameterType="top.winxblast.happymall.pojo.Category" > <!-- WARNING - @mbggenerated This element is automatically generated by MyBatis Generator, do not modify. This element was generated on Sun Oct 08 14:03:47 CST 2017. --> update happymall_category set parent_id = #{parentId,jdbcType=INTEGER}, name = #{name,jdbcType=VARCHAR}, status = #{status,jdbcType=BIT}, sort_order = #{sortOrder,jdbcType=INTEGER}, create_time = #{createTime,jdbcType=TIMESTAMP}, update_time = now() where id = #{id,jdbcType=INTEGER} </update> <select id="selectCategoryChildrenByParentId" resultMap="BaseResultMap" parameterType="int"> SELECT <include refid="Base_Column_List"/> FROM happymall_category WHERE parent_id = #{parentId} </select></mapper>
接口测试
还是继续使用我们的chrome插件restlet client,这里我就上几张图给大家参考一下就好了,还是比较容易使用的,不过测试要尽可能覆盖一些特殊情况,虽然我们不是专业的测试,但是也要考虑的周到一些。
这次的4个接口都是使用GET方法就可以了,带默认参数的可以试试不传入参数。
get_category.do接口
add_category.do
set_category_name.do
get_deep_category.do
同时由于是使用GET方法提交参数,我们也不需要写HTML表单,可以直接在浏览器中输入相应的地址来查看返回值,这里json格式化的效果是由插件FE助手完成的,大家要是使用火狐浏览器的话可以浏览器直接支持格式化json的。
- 【实战】6-2 分类管理开发
- 【实战】6-1 分类管理模块
- 商城项目实战27:内容分类管理
- APP开发实战81-Android权限分类
- APP开发实战141-异常分类
- 手机开发实战22——GPRS移动性管理2
- 云计算实战之url 关键词及分类管理
- 【书摘】iPad应用开发实战:内存管理
- APP开发实战133-APP版本管理
- APP开发实战140-APP项目管理
- 手机开发实战18——GPRS移动台分类
- 手机开发实战42——手机功能分类
- java实战 ——分类模块的开发
- php 无限分类管理(2)
- RDIFramework.NET ━ .NET快速信息化系统开发框架 V3.2-模块管理按子系统进行分类管理
- 商城开发之商品分类表的设计、使用、管理
- asp.net mvc+jquery easyui开发实战教程之网站后台管理系统开发2-Model层建立
- 精益开发实战:用看板管理大型项目
- ST17H26只pwm波形特征
- Superflex动力服:穿上我,让你拥有超人般能力
- 滴滴优步合并尚存变数 政策监管或成主要障碍
- 腾讯“互联网+警务”强化打击力量,“麒麟”将助力反诈骗最后一公里
- 飞利浦的健康之路:比我们以为的要早一些
- 【实战】6-2 分类管理开发
- Uber CEO确认Uber中国与滴滴出行合并,从传言到证实全程回顾
- eclipse 配置scala问题-More than one scala library found in the build path
- 关于Petalinux自启问题
- 游戏分发这块大蛋糕,阿里的切法为何“似曾相识”
- 均衡器设计
- vivo X7Plus 凭什么成为年轻爱美的时尚白领首选
- 5700万美金切入内容分发,猎豹的意图何在?
- cocoapods新版本用法