自定义业务异常处理类加入全局处理器中

自定义业务异常处理类并将其加入全局异常处理器,从而避免业务层直接处理异常造成代码污染,达到业务清晰简洁。

 描述

在进行分类模块开发时,删除某个分类时当分类关联了菜品和套餐时,是不允许删除的。我们在管理端删除的时候会提示异常,我们使用自定义业务异常处理类并将其加入全局异常处理器,从而避免业务层直接处理异常造成代码污染,达到业务清晰简洁。

删除分类

删除分类需要注意的是当分类关联了菜品和套餐时,不允许删除。

1 基础删除,不检查关联的菜品

请求:

自定义业务异常处理类加入全局处理器中_第1张图片

  • 如果忘了加注解@JsonFormat注解,会发生js获取主键时丢失精度,js只能读17位,而雪花算法Long类型是19位。

  • @JsonFormat(shape = JsonFormat.Shape.STRING)
    

自定义业务异常处理类加入全局处理器中_第2张图片

代码:

    @DeleteMapping
    public R page(Long ids){
        boolean success = categoryService.removeById(ids);
        if(success)return R.success("删除成功");
        else return R.error("删除失败");
    }


2 菜品和套餐的实体类,别忘了@JsonFormat

套餐:

/**
 * 套餐
 */
@Data
public class Setmeal implements Serializable {
 
    private static final long serialVersionUID = 1L;
    @JsonFormat(shape = JsonFormat.Shape.STRING)
    private Long id;
 
 
    //分类id
    @JsonFormat(shape = JsonFormat.Shape.STRING)
    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)
    @JsonFormat(shape = JsonFormat.Shape.STRING)
    private Long createUser;
 
 
    @TableField(fill = FieldFill.INSERT_UPDATE)
    @JsonFormat(shape = JsonFormat.Shape.STRING)
    private Long updateUser;
 
}

菜品:

/**
 菜品
 */
@Data
public class Dish implements Serializable {
 
    private static final long serialVersionUID = 1L;
    @JsonFormat(shape = JsonFormat.Shape.STRING)
    private Long id;
 
 
    //菜品名称
    private String name;
 
 
    //菜品分类id
    @JsonFormat(shape = JsonFormat.Shape.STRING)
    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)
    @JsonFormat(shape = JsonFormat.Shape.STRING)
    private Long createUser;
 
 
    @TableField(fill = FieldFill.INSERT_UPDATE)
    @JsonFormat(shape = JsonFormat.Shape.STRING)
    private Long updateUser;
 
}

3 菜品和套餐的dao和service

建议自己写,很快,复制粘贴总会把实体类之类的写错。

@Mapper
public interface DishMapper extends BaseMapper {
}
@Mapper
public interface SetmealMapper extends BaseMapper {
}
public interface DishService extends IService {
}
public interface SetmealService extends IService {
}
@Service
@Slf4j
public class DishServiceImpl extends ServiceImpl implements DishService {
}
 
@Service
@Slf4j
public class SetmealServiceImpl extends ServiceImpl implements SetmealService {
}

4 检查后删除,业务异常捕获

目标:当分类关联了菜品和套餐时,不允许删除。

跟进到IService的remove方法,通过比较器wrapper删除,参数改成Integer的话算重载,可以改:

代码实现:

我前面自己写的时候,没有用异常捕获,是在业务层根据不同情况返回不同数字,然后controller根据数字R.error("错误原因") 。用异常捕获也能实现,两种效果都一样,用异常捕获更规范

service:

    @Override
    public Integer remove(Long id){
        LambdaQueryWrapper wrapper1=new LambdaQueryWrapper<>();
        wrapper1.eq(Setmeal::getCategoryId,id);
        LambdaQueryWrapper wrapper2=new LambdaQueryWrapper<>();
        wrapper2.eq(Dish::getCategoryId,id);
        log.info("套餐查询:{}",setmealService.getMap(wrapper1));log.info("菜品查询:{}",dishService.getMap(wrapper2));
        //查到有菜品或套餐使用这个分类
        if(setmealService.count(wrapper1)>0) return -1;
        if(dishService.count(wrapper2)>0) return -2;
        return categoryDao.deleteById(id)>0?1:0;
    }

    @DeleteMapping
    public R remove(Long ids){
        log.info("要删除的id:{}",ids);
        int success = -3;success=categoryService.remove(ids);
        log.info("删除状态:{}",success);
        if(success==1)return R.success("删除成功");
        else if(success==0) return R.error("网络原因删除失败");
        else if(success==-1) return R.error("有套餐正在使用此分类");
        else if(success==-2)return R.error("有菜品正在使用此分类");
        else return R.error("未知错误");
    }

异常捕获方案:

service

@Service
public class CategoryServiceImpl extends ServiceImpl implements CategoryService{
 
    @Autowired
    private DishService dishService;
 
    @Autowired
    private SetmealService setmealService;
 
    /**
     * 根据id删除分类,删除之前需要进行判断
     * @param id
     */
    @Override
    public void remove(Long id) {
        LambdaQueryWrapper dishLambdaQueryWrapper = new LambdaQueryWrapper<>();
        //添加查询条件,根据分类id进行查询
        dishLambdaQueryWrapper.eq(Dish::getCategoryId,id);
        int count1 = dishService.count(dishLambdaQueryWrapper);
 
        //查询当前分类是否关联了菜品,如果已经关联,抛出一个业务异常
        if(count1 > 0){
            //已经关联菜品,抛出一个业务异常
            throw new CustomException("当前分类下关联了菜品,不能删除");
        }
 
        //查询当前分类是否关联了套餐,如果已经关联,抛出一个业务异常
        LambdaQueryWrapper setmealLambdaQueryWrapper = new LambdaQueryWrapper<>();
        //添加查询条件,根据分类id进行查询
        setmealLambdaQueryWrapper.eq(Setmeal::getCategoryId,id);
        int count2 = setmealService.count();
        if(count2 > 0){
            //已经关联套餐,抛出一个业务异常
            throw new CustomException("当前分类下关联了套餐,不能删除");
        }
 
        //正常删除分类
        super.removeById(id);
    }
}

controller

    @DeleteMapping
    public R delete(Long id){
        log.info("删除分类,id为:{}",id);
 
        //categoryService.removeById(id);
        if(categoryService.remove(ids)) return R.success("删除成功");
        //这里也可以throw业务异常,但不建议,一般都是service抛出异常,controller返回R.error();
        else return R.error("删除失败");
    }

业务异常类:

/**
 * 自定义业务异常类
 */
public class CustomException extends RuntimeException {
    //带参构造方法,重新设置异常信息
    public CustomException(String message){
        super(message);
    }
}

全局异常处理:

@RestControllerAdvice
//@ControllerAdvice(annotations = {RestController.class, Controller.class})
//@ResponseBody
@Slf4j
public class GlobalExceptionHandler {
 
    /**
     * 异常处理方法
     * @return
     */
    @ExceptionHandler(SQLIntegrityConstraintViolationException.class)
    public R exceptionHandler(SQLIntegrityConstraintViolationException ex){
        log.error(ex.getMessage());
 
        if(ex.getMessage().contains("Duplicate entry")){
            String[] split = ex.getMessage().split(" ");
            String msg = split[2] + "已存在";
            return R.error(msg);
        }
 
        return R.error("未知错误");
    }
 
    /**
     * 异常处理方法
     * @return
     */
    @ExceptionHandler(CustomException.class)
    public R exceptionHandler(CustomException ex){
        log.error(ex.getMessage());
 
        return R.error(ex.getMessage());
    }
 
}

你可能感兴趣的:(项目2(外卖),java,intellij-idea)