功能开发-分类管理
一、公共字段自动填充
1.1、问题分析
1.2、代码实现
1.2.1、需求分析
难点:怎么获取当前使用者的id
1.2.2、代码实现
BaseContext
package com.xxxit.reggie.common;
/**
* 基于ThreadLocal封装的工具类,用来保存和获取当前用户的id
*/
public class BaseContext {
// 因为是工具类方法,属性都可以写静态的,类.方法/属性,不用对象.方法/属性
// 泛型第一个写了类型,第二个<>自动识别
private static ThreadLocal<Long> threadLocal = new ThreadLocal<>();
/**
* 设置值
* @param id
*/
public static void setCurrentId(Long id){
threadLocal.set(id);
}
/**
* 获取值
* @return
*/
public static Long getCurrentId(){
return threadLocal.get();
}
}
LoginCheckFilter修改已登录放行时设置id
// 4、已经登录直接放行
if(request.getSession().getAttribute("employee") != null){
Long empId = (Long) request.getSession().getAttribute("employee");
log.info("当前已经登录可进行操作,放行{}",empId);
BaseContext.setCurrentId(empId);
filterChain.doFilter(request,response);
return;
}
MyMetaObjectHandler
package com.xxxit.reggie.common;
import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.reflection.MetaObject;
import org.springframework.stereotype.Component;
import java.time.LocalDateTime;
/**
* 公共字段自动填充
* 难点:获取当前用户id,利用线程,编写BaseContext类
*/
@Slf4j
@Component
public class MyMetaObjectHandler implements MetaObjectHandler {
@Override
public void insertFill(MetaObject metaObject) {
log.info("公共字段自动填充【insert】");
log.info(metaObject.toString());
metaObject.setValue("createTime", LocalDateTime.now());
metaObject.setValue("updateTime", LocalDateTime.now());
metaObject.setValue("createUser",BaseContext.getCurrentId());
metaObject.setValue("updateUser",BaseContext.getCurrentId());
}
@Override
public void updateFill(MetaObject metaObject) {
log.info("公共字段自动填充【update】");
log.info(metaObject.toString());
metaObject.setValue("updateTime", LocalDateTime.now());
metaObject.setValue("updateUser",BaseContext.getCurrentId());
}
}
修改Controller自设置的公共字段
1.2.3、测试
二、新增分类功能
2.1、需求分析
2.2、数据模型
2.3、代码开发
2.3.1、创建实体类Category
package com.xxxit.reggie.entity;
import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.TableField;
import lombok.Data;
import java.io.Serializable;
import java.time.LocalDateTime;
/**
* 分类
*/
@Data
public class Category implements Serializable {
private static final long serialVersionUID = 1L;
private Long id;
//类型 1 菜品分类 2 套餐分类
private Integer type;
//分类名称
private String name;
//顺序
private Integer sort;
//创建时间
@TableField(fill = FieldFill.INSERT)
private LocalDateTime createTime;
//更新时间
@TableField(fill = FieldFill.INSERT_UPDATE)
private LocalDateTime updateTime;
//创建人
@TableField(fill = FieldFill.INSERT)
private Long createUser;
//修改人
@TableField(fill = FieldFill.INSERT_UPDATE)
private Long updateUser;
//是否删除
private Integer isDeleted;
}
2.3.2、搭建Mapper,Service,Controller
Mapper
package com.xxxit.reggie.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.xxxit.reggie.entity.Category;
import org.apache.ibatis.annotations.Mapper;
@Mapper //声明mapper代理开发
public interface CategoryMapper extends BaseMapper<Category> {
}
Service
package com.xxxit.reggie.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.xxxit.reggie.entity.Category;
public interface CategoryService extends IService<Category> {
}
ServiceImpl
package com.xxxit.reggie.service.Impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xxxit.reggie.entity.Category;
import com.xxxit.reggie.mapper.CategoryMapper;
import com.xxxit.reggie.service.CategoryService;
import org.springframework.stereotype.Service;
@Service
public class CategoryServiceImpl extends ServiceImpl<CategoryMapper, Category> implements CategoryService {
}
Controller
package com.xxxit.reggie.controller;
import com.xxxit.reggie.service.CategoryService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/Category")
@Slf4j
public class CategoryController {
@Autowired
private CategoryService categoryService;
}
2.3.3、CategoryController功能编写
package com.xxxit.reggie.controller;
import com.xxxit.reggie.common.R;
import com.xxxit.reggie.entity.Category;
import com.xxxit.reggie.service.CategoryService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/category")
@Slf4j
public class CategoryController {
@Autowired
private CategoryService categoryService;
/**
* 新增分类
* @param category
* @return
*/
@PostMapping
public R<String> save(@RequestBody Category category){
log.info("新增分类:{}",category);
categoryService.save(category);
return R.success("新增分类成功");
}
}
三、分类信息分页查询
3.1、需求分析
3.2、代码编写
package com.xxxit.reggie.controller;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.xxxit.reggie.common.R;
import com.xxxit.reggie.entity.Category;
import com.xxxit.reggie.service.CategoryService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/category")
@Slf4j
public class CategoryController {
@Autowired
private CategoryService categoryService;
/**
* 新增分类
* @param category
* @return
*/
@PostMapping
public R<String> save(@RequestBody Category category){
log.info("新增分类:{}",category);
categoryService.save(category);
return R.success("新增分类成功");
}
/**
* 分类分页查询
* @param page
* @param pageSize
* @return
*/
@GetMapping("/page")
public R<Page> page(int page, int pageSize){
// 分页构造器
Page<Category> pageInfo = new Page<>(page,pageSize);
// 编制查询条件(排序)
LambdaQueryWrapper<Category> lambdaQueryWrapper = new LambdaQueryWrapper<>();
lambdaQueryWrapper.orderByAsc(Category::getSort);
// 查询
categoryService.page(pageInfo,lambdaQueryWrapper);
return R.success(pageInfo);
}
}
四、删除分类功能
4.1、需求分析
4.2、构建实体类,Mapper,Service,Controller
4.2.1、Dish和Setmeal实体类
Dish
package com.xxxit.reggie.entity;
import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import lombok.Data;
import java.io.Serializable;
import java.math.BigDecimal;
import java.time.LocalDateTime;
/**
菜品
*/
@Data
public class Dish implements Serializable {
private static final long serialVersionUID = 1L;
private Long id;
//菜品名称
private String name;
//菜品分类id
private Long categoryId;
//菜品价格
private BigDecimal price;
//商品码
private String code;
//图片
private String image;
//描述信息
private String description;
//0 停售 1 起售
private Integer status;
//顺序
private Integer sort;
@TableField(fill = FieldFill.INSERT)
private LocalDateTime createTime;
@TableField(fill = FieldFill.INSERT_UPDATE)
private LocalDateTime updateTime;
@TableField(fill = FieldFill.INSERT)
private Long createUser;
@TableField(fill = FieldFill.INSERT_UPDATE)
private Long updateUser;
//是否删除
private Integer isDeleted;
}
Setmeal
package com.xxxit.reggie.entity;
import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import lombok.Data;
import java.io.Serializable;
import java.math.BigDecimal;
import java.time.LocalDateTime;
/**
* 套餐
*/
@Data
public class Setmeal implements Serializable {
private static final long serialVersionUID = 1L;
private Long id;
//分类id
private Long categoryId;
//套餐名称
private String name;
//套餐价格
private BigDecimal price;
//状态 0:停用 1:启用
private Integer status;
//编码
private String code;
//描述信息
private String description;
//图片
private String image;
@TableField(fill = FieldFill.INSERT)
private LocalDateTime createTime;
@TableField(fill = FieldFill.INSERT_UPDATE)
private LocalDateTime updateTime;
@TableField(fill = FieldFill.INSERT)
private Long createUser;
@TableField(fill = FieldFill.INSERT_UPDATE)
private Long updateUser;
//是否删除
private Integer isDeleted;
}
4.2.2、Mapper
DishMapper
package com.xxxit.reggie.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.xxxit.reggie.entity.Dish;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface DishMapper extends BaseMapper<Dish> {
}
SetmealMapper
package com.xxxit.reggie.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.xxxit.reggie.entity.Setmeal;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface SetmealMapper extends BaseMapper<Setmeal> {
}
4.2.3、Service
DishService
package com.xxxit.reggie.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.xxxit.reggie.entity.Dish;
public interface DishService extends IService<Dish> {
}
SetmealService
package com.xxxit.reggie.service;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.xxxit.reggie.entity.Setmeal;
public interface SetmealService extends BaseMapper<Setmeal> {
}
4.2.4、ServiceImpl
DishServiceImpl
package com.xxxit.reggie.service.Impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xxxit.reggie.entity.Dish;
import com.xxxit.reggie.mapper.DishMapper;
import com.xxxit.reggie.service.DishService;
import org.springframework.stereotype.Service;
@Service
public class DishServiceImpl extends ServiceImpl<DishMapper, Dish> implements DishService {
}
SetmealServiceImpl
package com.xxxit.reggie.service.Impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xxxit.reggie.entity.Setmeal;
import com.xxxit.reggie.mapper.SetmealMapper;
import com.xxxit.reggie.service.SetmealService;
import org.springframework.stereotype.Service;
@Service
public class SetmealServiceImpl extends ServiceImpl<SetmealMapper, Setmeal> implements SetmealService {
}
4.3、定义业务异常(分类关联菜品或套餐不能删除)
注意:抛出业务异常的时候还是交给全局异常处理
CustomException
package com.xxxit.reggie.common;
/**
* 自定义业务异常
*/
public class CustomException extends RuntimeException{
public CustomException(String msg){
super(msg);
}
}
GlobalExceptionHandler
package com.xxxit.reggie.common;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import java.sql.SQLIntegrityConstraintViolationException;
@Slf4j
@ControllerAdvice(annotations = {Controller.class, RestController.class})
@ResponseBody
public class GlobalExceptionHandler {
/**
* 异常处理方法
* @param ex
* @return
*/
@ExceptionHandler(SQLIntegrityConstraintViolationException.class)
public R<String> exceptionHandler(SQLIntegrityConstraintViolationException ex){
// 输出异常信息
log.info(ex.getMessage());
// 查看是否Duplicate entry,切分语句Duplicate entry 'zhangsan' for key 'employee.idx_username'
// 返回{username}已存在
if (ex.getMessage().contains("Duplicate entry")){
String[] split = ex.getMessage().split(" ");
String msg = split[2]+"已存在";
return R.error(msg);
}
return R.error("未知错误");
}
/**
* 异常处理方法
* @param ex
* @return
*/
@ExceptionHandler(CustomException.class)
public R<String> exceptionHandler(CustomException ex){
// 输出异常信息
log.info(ex.getMessage());
return R.error(ex.getMessage());
}
}
4.4、重写CategoryServiceImpl的remove
package com.xxxit.reggie.service.Impl;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xxxit.reggie.common.CustomException;
import com.xxxit.reggie.entity.Category;
import com.xxxit.reggie.entity.Dish;
import com.xxxit.reggie.entity.Setmeal;
import com.xxxit.reggie.mapper.CategoryMapper;
import com.xxxit.reggie.service.CategoryService;
import com.xxxit.reggie.service.DishService;
import com.xxxit.reggie.service.SetmealService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class CategoryServiceImpl extends ServiceImpl<CategoryMapper, Category> implements CategoryService {
@Autowired
private DishService dishService;
@Autowired
private SetmealService setmealService;
@Override
public void remove(Long id) {
// 判断分类下没有关联菜品
LambdaQueryWrapper<Dish> lambdaQueryWrapper1 = new LambdaQueryWrapper<>();
lambdaQueryWrapper1.eq(Dish::getCategoryId,id);
int count1 = dishService.count(lambdaQueryWrapper1);
if (count1 > 0){
// 已关联菜品,返回一个业务异常
throw new CustomException("分类下关联了菜品");
}
// 判断分类下没有关联菜品
LambdaQueryWrapper<Setmeal> lambdaQueryWrapper2 = new LambdaQueryWrapper<>();
lambdaQueryWrapper2.eq(Setmeal::getCategoryId,id);
int count2 = setmealService.count(lambdaQueryWrapper2);
if (count2 > 0){
// 已关联套餐,返回一个业务异常
throw new CustomException("分类下关联了菜单");
}
super.removeById(id);
}
}
4.5、CategoryController
package com.xxxit.reggie.controller;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.xxxit.reggie.common.R;
import com.xxxit.reggie.entity.Category;
import com.xxxit.reggie.service.CategoryService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/category")
@Slf4j
public class CategoryController {
@Autowired
private CategoryService categoryService;
/**
* 新增分类
* @param category
* @return
*/
@PostMapping
public R<String> save(@RequestBody Category category){
log.info("新增分类:{}",category);
categoryService.save(category);
return R.success("新增分类成功");
}
/**
* 分类分页查询
* @param page
* @param pageSize
* @return
*/
@GetMapping("/page")
public R<Page> page(int page, int pageSize){
// 分页构造器
Page<Category> pageInfo = new Page<>(page,pageSize);
// 编制查询条件(排序)
LambdaQueryWrapper<Category> lambdaQueryWrapper = new LambdaQueryWrapper<>();
lambdaQueryWrapper.orderByAsc(Category::getSort);
// 查询
categoryService.page(pageInfo,lambdaQueryWrapper);
return R.success(pageInfo);
}
/**
* 删除分类
* 路径?后参数必须与方法形参同名或者使用注解绑定
* @param ids
* @return
*/
@DeleteMapping
public R<String> delete(Long ids){
log.info("当前删除的分类id:{}",ids);
categoryService.remove(ids);
return R.success("删除成功");
}
}
4.6、测试
五、分类修改功能
5.1、需求分析
5.2、代码编写
package com.xxxit.reggie.controller;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.xxxit.reggie.common.R;
import com.xxxit.reggie.entity.Category;
import com.xxxit.reggie.service.CategoryService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/category")
@Slf4j
public class CategoryController {
@Autowired
private CategoryService categoryService;
/**
* 新增分类
* @param category
* @return
*/
@PostMapping
public R<String> save(@RequestBody Category category){
log.info("新增分类:{}",category);
categoryService.save(category);
return R.success("新增分类成功");
}
/**
* 分类分页查询
* @param page
* @param pageSize
* @return
*/
@GetMapping("/page")
public R<Page> page(int page, int pageSize){
log.info("分类查询分页功能");
// 分页构造器
Page<Category> pageInfo = new Page<>(page,pageSize);
// 编制查询条件(排序)
LambdaQueryWrapper<Category> lambdaQueryWrapper = new LambdaQueryWrapper<>();
lambdaQueryWrapper.orderByAsc(Category::getSort);
// 查询
categoryService.page(pageInfo,lambdaQueryWrapper);
return R.success(pageInfo);
}
/**
* 删除分类
* 路径?后参数必须与方法形参同名或者使用注解绑定
* @param ids
* @return
*/
@DeleteMapping
public R<String> delete(Long ids){
log.info("当前删除的分类id:{}",ids);
categoryService.remove(ids);
return R.success("删除成功");
}
/**
* 分类修改
* @param category
* @return
*/
@PutMapping
public R<String> update(@RequestBody Category category){
log.info("修改分类信息:{}",category.getId());
categoryService.updateById(category);
return R.success("修改成功");
}
}