1.通用返回结果类
-
通用返回结果类,业务中的方法有返回值,都会封装成 R 对象进行返回
-
返回成功的方法中的参数 使用了泛型 success(T object) ,让代码更具有通用性,既可以传对象,也可以传字符串。
比如用户登录的时候 return R.success(user);
主要是要和前端保持一致,如果不需要返回数据 就可以返回字符串
比如操作成功 return R.success(“操作成功”); 操作失败 return R.error(“操作失败”)。
/**
* 通用返回结果类,业务中的方法有返回值,都会封装成R对象进行返回
*/
@Data
public class R<T> implements Serializable {
private Integer code; //编码:1成功,0和其它数字为失败
private String msg; //错误信息
private T data; //数据
public static <T> R<T> success(T object) {
R<T> r = new R<T>();
r.data = object;
r.code = 1;
return r;
}
public static <T> R<T> error(String msg) {
R r = new R();
r.msg = msg;
r.code = 0;
return r;
}
}
2. 全局异常捕获类
- 采用了 AOP 的思想,AOP(面向切面编程)是基于动态代理的。将公共的代码抽出来作为一个切面类,在这个切面类里做功能增强。主要是用来降低耦合,公共的代码不要和业务的代码写在一起。
新增员工时,用户已经存在,会抛出异常。我们有2种处理的方式:
-
1 . 用 try catch 处理异常,如果有很多这样的异常需要处理,就要写很多 try catch 代码看起来也不简洁,所以不是很推荐这样写
-
2 . 定义 全局异常捕获类 处理异常
先定义一个注解 @ControllerAdvice ,就是一个通知,annotations 里面写上要管理的 Controller
-
在项目里会定义一些自定义的 业务异常 继承 RuntimeException 运行时异常
/** * 自定义业务异常类 */ public class CustomException extends RuntimeException{ public CustomException(String message){ super(message); } }
-
删除分类时,由于关联了菜品,所以不能删除并给出错误信息
//查询当前分类是否关联了菜品,如果已经关联,直接抛出一个业务异常
if( dishCount > 0 ){
//已经关联了菜品,抛出一个业务异常
throw new CustomException("当前分类关联了菜品,不能删除");
}
- 全局异常捕获类 处理这个自定义的异常,将异常信息在页面展现出来
/**
* 全局异常处理
*/
@ControllerAdvice(annotations = {RestController.class, Controller.class})
@ResponseBody
@Slf4j
public class GlobalExceptionHandler {
/**
* 异常处理方法 SQLIntegrityConstraintViolationException
* @return
*/
@ExceptionHandler(SQLIntegrityConstraintViolationException.class)
public R<String> exceptionHandler(SQLIntegrityConstraintViolationException ex){
log.error(ex.getMessage());
if(ex.getMessage().contains("Duplicate entry")){
String[] splitErrorMessage = ex.getMessage().split(" ");//空格切割Duplicate entry 'zhangsan' for key 'idx_username'
String msg = splitErrorMessage[2]+"已存在";
return R.error(msg);
}
return R.error("未知错误");
}
/**
* 自定义的异常处理方法 CustomException
* @return
*/
@ExceptionHandler(CustomException.class)
public R<String> exceptionHandler(CustomException ex){
log.error(ex.getMessage());
//这里拿到的message是业务类抛出的异常信息,我们把它显示到前端
return R.error(ex.getMessage());
}
}
3. Mybatis Plus 提供的公共字段自动填充功能
-
公共字段:有很多表中都有的字段字段,如创建时间、创建人、修改时间、修改人。如果对于每个表的每次操作都要填充这些字段就很麻烦。
-
实现步骤:
1.在实体类上加@TableField注解
@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;
- 自定义元数据对象处理器,实现MetaObjectHandler接口
/**
* 自定义元数据对象处理器
*/
@Slf4j
@Component //注意:这个要记得交给spring容器管理,不然这个功能就没法用
public class MyMetaObjecthandler implements MetaObjectHandler {
@Override
public void insertFill(MetaObject metaObject) {
metaObject.setValue("createTime", LocalDateTime.now());
metaObject.setValue("updateTime", LocalDateTime.now());
//不论是新增还是更新记录,即createUser还是updateUser应该都是当前用户,那么如何获取当前用户的id呢?(通过ThreadLocal动态获取员工id)
metaObject.setValue("createUser", BaseContext.getCurrentId()); //这里的id是不能直接获取的,通过ThreadLocal动态获取员工id
metaObject.setValue("updateUser",BaseContext.getCurrentId());
}
@Override
public void updateFill(MetaObject metaObject) {
long id = Thread.currentThread().getId();
log.info("线程id为:{}",id);
metaObject.setValue("updateTime",LocalDateTime.now());
metaObject.setValue("updateUser",BaseContext.getCurrentId());
}
}