更新:
与新增类似,请求参数中多加一个id,用来当做判断条件。
用传入更新的名称参数去查询表获取对象,如果对象不是空,代表有重名,不一定要报错因为有可能只是对层级进行修改,这时候要用到id去判断我们查到的的id与传入的id是不是一样,如果一样就要扔出异常,用我们的异常枚举就好。
Controller:
@ApiOperation("后台更新目录") @PostMapping("admin/category/update") @ResponseBody public ApiRestResponse updateCategory(@Valid @RequestBody UpdateCategoryReq updateCategoryReq, HttpSession session) { User currentUser = (User) session.getAttribute(Constant.Demo_User); if (currentUser == null) { return ApiRestResponse.error(SpringLearnExceptionEnum.NEED_LOGIN); } //校验是否是管理员 boolean adminRole = userService.checkAdminRole(currentUser); if (adminRole) { //是管理员,执行操作 Category category = new Category(); BeanUtils.copyProperties(updateCategoryReq, category); categoryService.update(category); return ApiRestResponse.success(); } else { return ApiRestResponse.error(SpringLearnExceptionEnum.NEED_ADMIN); } }
Service:
void update(Category updateCategory);
@Override public void update(Category updateCategory) { if (updateCategory.getName() != null) { Category categoryOld = categoryMapper.selectByName(updateCategory.getName()); if (categoryOld != null && !categoryOld.getId().equals(updateCategory.getId())) { throw new SpringLearnException(SpringLearnExceptionEnum.NAME_EXISTED); } } int count = categoryMapper.updateByPrimaryKeySelective(updateCategory); if (count == 0) { throw new SpringLearnException(SpringLearnExceptionEnum.UPDATE_FAILED); } }
Req:
/** * 描述: UpdateCategoryReq */ public class UpdateCategoryReq { @NotNull(message = "id不能为null") private Integer id; @Size(min = 2, max = 5) private String name; @Max(3) private Integer type; private Integer parentId; private Integer orderNum; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Integer getType() { return type; } public void setType(Integer type) { this.type = type; } public Integer getParentId() { return parentId; } public void setParentId(Integer parentId) { this.parentId = parentId; } public Integer getOrderNum() { return orderNum; } public void setOrderNum(Integer orderNum) { this.orderNum = orderNum; } }
完成后开发删除目录接口,这个比较简单,只需要传入参数为id,调用系统自动生成的Mapper完成即可,这里因为都是后台操作,需要验证管理员登录,考虑把验证管理员登录做成过滤器。
在过滤器包中新建一个类
/** * 描述: 管理员校验过滤器 * 写好过滤器要去配置,在config包中进行配置 * 将相同的校验抽到外面去非常方便 */ public class AdminFilter implements Filter {//javax.servlet.Filter, @Autowired UserService userService; @Override public void init(FilterConfig filterConfig) throws ServletException { } @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { //通过request拿到session,将servletRequest转为HttpServletRequest HttpServletRequest request = (HttpServletRequest) servletRequest; HttpSession session = request.getSession(); User currentUser = (User) session.getAttribute(Constant.Demo_User); if (currentUser == null) { PrintWriter out = new HttpServletResponseWrapper( (HttpServletResponse) servletResponse).getWriter(); out.write("{\n" + " \"status\": 10007,\n" + " \"msg\": \"NEED_LOGIN\",\n" + " \"data\": null\n" + "}"); out.flush(); out.close(); return;//退出,不进入下一个过滤器 } //校验是否是管理员 boolean adminRole = userService.checkAdminRole(currentUser); if (adminRole) { filterChain.doFilter(servletRequest, servletResponse);//放行,继续到下一个过滤器 } else { //由于方法返回值是void不能返回Api统一响应类,使用Writer()写一个格式相同的返回 PrintWriter out = new HttpServletResponseWrapper( (HttpServletResponse) servletResponse).getWriter(); out.write("{\n" + " \"status\": 10009,\n" + " \"msg\": \"NEED_ADMIN\",\n" + " \"data\": null\n" + "}"); out.flush(); out.close();//由于方法到这里就结束可以不计return } } @Override public void destroy() { } }
配置写在config包中
/** * 描述: Admin过滤器的配置 */ @Configuration public class AdminFilterConfig { //定义AdminFilter ,让Spring可以识别出来 @Bean public AdminFilter adminFilter() { return new AdminFilter(); } @Bean(name = "adminFilterConf") public FilterRegistrationBean adminFilterConfig() { FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean(); filterRegistrationBean.setFilter(adminFilter()); filterRegistrationBean.addUrlPatterns("/admin/category/*"); filterRegistrationBean.setName("adminFilterConf");//名字不能与类名一样 return filterRegistrationBean; } }
可以发现/admin/category/*,以后只要Mapping符合就会进行管理员验证
Controller:
@ApiOperation("后台删除目录") @PostMapping("admin/category/delete") @ResponseBody public ApiRestResponse deleteCategory(@RequestParam Integer id) { categoryService.delete(id); return ApiRestResponse.success(); }
Service:
@Override public void delete(Integer id) { Category categoryOld = categoryMapper.selectByPrimaryKey(id); //查不到记录,无法删除,删除失败 if (categoryOld == null) { throw new SpringLearnException(SpringLearnExceptionEnum.DELETE_FAILED); } int count = categoryMapper.deleteByPrimaryKey(id); if (count == 0) { throw new SpringLearnException(SpringLearnExceptionEnum.DELETE_FAILED); } }
void delete(Integer id);
删除功能就完成了
后台目录的分页功能:
因为要经分页所以我们要用到PageHelper工具
引入依赖
<dependency> <groupId>com.github.pagehelper</groupId> <artifactId>pagehelper-spring-boot-starter</artifactId> <version>1.2.13</version> </dependency>
mapper:
mapper中新写一个select返回值是List泛型是目录实体类
List<Category> selectList();
xml:
<select id="selectList" resultMap="BaseResultMap"> select <include refid="Base_Column_List"/> from imooc_mall_category </select>
查询目录表中的所有信息。
Service:
@Override public PageInfo listForAdmin(Integer pageNum, Integer pageSize) { //PageHelper工具来进行分类,需要引入依赖 PageHelper.startPage(pageNum, pageSize, "type, order_num");//(页数,几条,排序规则) List<Category> categoryList = categoryMapper.selectList(); PageInfo pageInfo = new PageInfo(categoryList); return pageInfo; }
PageInfo listForAdmin(Integer pageNum, Integer pageSize);
Controller:
@ApiOperation("后台目录列表") @PostMapping("admin/category/list") @ResponseBody public ApiRestResponse listCategoryForAdmin(@RequestParam Integer pageNum,@RequestParam Integer pageSize) { PageInfo pageInfo = categoryService.listForAdmin(pageNum, pageSize); return ApiRestResponse.success(pageInfo); }
返回前段的分类数:
列表不像后端是按id排列的而有层级的,根据parentid将有相同父类的目录信息放在一起。
Controller:
@ApiOperation("前台目录列表") @PostMapping("category/list") @ResponseBody public ApiRestResponse listCategoryForCustomer() { List<CategoryVo> categoryVOS = categoryService.listCategoryForCustomer(); return ApiRestResponse.success(categoryVOS); }
Service:
@Override //创建包vo,用以存储进过一定的转换之后返回给前端的类 public List<CategoryVo> listCategoryForCustomer() { ArrayList<CategoryVo> categoryVOList = new ArrayList<>(); recursivelyFindCategories(categoryVOList, 0); return categoryVOList; } private void recursivelyFindCategories(List<CategoryVo> categoryVOList, Integer parentId) { //递归获取所有子类别,并组合成为一个“目录树” //用户比管理员多且分类变化不频繁,考虑做一层redis缓存 List<Category> categoryList = categoryMapper.selectCategoriesByParentId(parentId); if (!CollectionUtils.isEmpty(categoryList)) {//先判断是否为空 for (int i = 0; i < categoryList.size(); i++) {//递归遍历 Category category = categoryList.get(i); CategoryVo categoryVO = new CategoryVo();//每得到一个就拿他作为源数据去生成一个Vo BeanUtils.copyProperties(category, categoryVO);//拷贝 categoryVOList.add(categoryVO);//将拷贝好的vo添加到参数列表 recursivelyFindCategories(categoryVO.getChildCategory(), categoryVO.getId()); } } }
List<CategoryVo> listCategoryForCustomer();
Vo:
public class CategoryVo { private Integer id; private String name; private Integer type; private Integer parentId; private Integer orderNum; private Date createTime; private Date updateTime; private List<CategoryVo> childCatgory = new ArrayList<>(); public List<CategoryVo> getChildCategory() { return childCatgory; } public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name == null ? null : name.trim(); } public Integer getType() { return type; } public void setType(Integer type) { this.type = type; } public Integer getParentId() { return parentId; } public void setParentId(Integer parentId) { this.parentId = parentId; } public Integer getOrderNum() { return orderNum; } public void setOrderNum(Integer orderNum) { this.orderNum = orderNum; } public Date getCreateTime() { return createTime; } public void setCreateTime(Date createTime) { this.createTime = createTime; } public Date getUpdateTime() { return updateTime; } public void setUpdateTime(Date updateTime) { this.updateTime = updateTime; } }
利用postman测试,将json复制后缩小
可以看出是按照层级进行输出的。