前言
在编写业务代码的时候,时常需要定义不同的状态码来表示不同的执行结果。而一般主流的做法主要有以下两种:一、业务方法中定义统一的返回体,外层统一的返回体做全局处理;二、业务方法中抛出自定义异常, 外层做统一的异常处理。这里不对这两者进行对比,感兴趣的同学,可以去了解一下。这里主要讲的是第二种方式,也是本快速开发框架使用的方式。
错误码定义及规范
错误码枚举
仅一个错误码字段可能还不足以描述一个错误码,所以一般会单独定义枚举类来描述错误码。这里如下定义:
属性 | 类型 | 说明 |
---|---|---|
value | int | 错误码值 |
name | String | 错误码名称或描述 |
错误码注解
错误码定义好后,需要添加自定义注解说明,方便系统启动后扫描加载到内存并提供渲染页查看。
属性 | 类型 | 说明 |
---|---|---|
name | String | 模块名-英文 |
value | String | 错误码说明 |
bizCode | int | 业务码 |
min | int | 最小值 |
max | int | 最大值 |
错误码规范
不同的业务,错误码就不一样,所以一般每做一个业务,需要提前申请或者定义一下错误码范围。在这里使用8位数字组成的错误码。如:80000001、99990401等。一般来说,建议一个业务类,对应一个错误码枚举类。不过如果需要判断的业务不多,可以一个模块中的多个业务类共用一个错误码枚举类。
返回结果样例
成功
http status: 200
{
"code": 0,
"data": {
},
"msg": "操作成功"
}
错误
http status: 200
{
"code": 80009001,
"msg": "用户不存在"
}
开始编码
目录结构
只罗列需要新增或修改的文件
├── mldong-admin 管理端接口
├── emuns
src/main/java
└──com.mldong.modules.sys
└── controller 控制层
└── SysUserController.java
├── enums
└── SysErrEnum.java
└── service 服务层
├── impl
└── SysUserServiceImpl
└── SysUserService.java
├── mldong-common 工具类及通用代码
├── src/main/java
├── com.mldong.common.base
└── CommonError.java
├── com.mldong.common.base.constant
└── GlobalErrEnum.java
├── com.mldong.common.annotation
└── ErrEnum.java
└──com.mldong.common.exception
├── BizException.java
└── DefaultExceptionHandler.java
└── pom.xml
├── mldong-generator 代码生成器
└── mldong-mapper 持久层
文件说明
mldong-common/com/mldong/common/base/CommonError.java
package com.mldong.common.base;
/**
* 错误码接口-所有的错误码都要实现该接口
* @author mldong
*
*/
public interface CommonError {
int getValue();
String getName();
}
mldong-common/com/mldong/annotation/ErrEnum.java
package com.mldong.common.annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 错误码枚举注解,方便收集错误码描述,统一查看的
* @author mldong
*
*/
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface ErrEnum {
/**
* 名称
* @return
*/
String name();
/**
* 说明
* @return
*/
String value();
/**
* 业务码
* @return
*/
int bizCode();
/**
* 最小值
* @return
*/
int min();
/**
* 最大值
* @return
*/
int max();
}
mldong-common/com/mldong/common/annotation/GlobalErrEnum.java
package com.mldong.common.base.constant;
import com.mldong.common.annotation.ErrEnum;
import com.mldong.common.base.CommonError;
/**
* 全局错误码
* @author mldong
*
*/
@ErrEnum(name="global",value="全局错误码",bizCode=9999,min=0,max=1000)
public enum GlobalErrEnum implements CommonError {
/**
* 参数异常
*/
GL99990100(99990100, "参数异常"),
/**
* 无访问权限
*/
GL99990401(99990401, "无访问权限"),
/**
* 未知异常
*/
GL99990500(99990500, "未知异常"),
/**
* 无权访问
*/
GL99990403(99990403, "无权访问"),
/**
* 找不到指定资源
*/
GL99990404(99990404, "找不到指定资源"),
/**
* 注解使用错误
*/
GL99990001(99990001, "注解使用错误"),
/**
* 微服务不在线,或者网络超时
*/
GL99990002(99990002, "微服务不在线,或者网络超时"),
/**
* 没有数据
*/
GL99990003(99990003, "没有数据"),
/**
* 演示账号,无写权限
*/
GL99990004(99990004, "演示账号,无写权限"),
/**
* 数据库插入异常
*/
GL99990005(99990005, "数据库插入异常"),
/**
* 文件后辍不允许
*/
GL99990006(99990006, "文件后辍不允许"),
;
private GlobalErrEnum(int value, String name){
this.value = value;
this.name = name;
}
private String name;
private int value;
public int getValue() {
return value;
}
public String getName() {
return name;
}
}
mldong-common/com/mldong/common/exception/BizException.java
package com.mldong.common.exception;
import com.mldong.common.base.CommonError;
/**
* 业务错码异常类
* @author mldong
*
*/
public class BizException extends RuntimeException{
private static final long serialVersionUID = -8059304617449091328L;
/**
* 错误
*/
private CommonError error;
public BizException(CommonError error) {
super("[" + error.getValue() + "]" + error.getName());
this.error = error;
}
public CommonError getError() {
return error;
}
public void setError(CommonError error) {
this.error = error;
}
}
mldong-common/com/mldong/common/exception/DefaultExceptionHandler.java
新增BizException异常处理
package com.mldong.common.exception;
import java.util.stream.Collectors;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import com.mldong.common.base.CommonError;
import com.mldong.common.base.CommonResult;
/**
* 全局异常处理类
* @author mldong
*
*/
@ControllerAdvice
public class DefaultExceptionHandler {
private static Logger log = LoggerFactory.getLogger(DefaultExceptionHandler.class);
/**
* 服务层异常
* @param e
* @return
*/
@ExceptionHandler(BizException.class)
@ResponseBody
public CommonResult<CommonError> serviceExceptionHandler(BizException e) {
log.error("服务层异常:", e);
return CommonResult.fail(e.getError());
}
/**
* 控制层参数校验异常
* @param e
* @return
*/
@ExceptionHandler(MethodArgumentNotValidException.class)
@ResponseBody
public CommonResult<?> methodArgumentNotValidExceptionHandler(MethodArgumentNotValidException e){
log.error("参数校验异常:{}", e.getMessage());
;
String errorMsg = String.join(",", e.getBindingResult().getAllErrors().stream().map(item->{
return item.getDefaultMessage();
}).collect(Collectors.toList()));
return CommonResult.fail(errorMsg, e.getBindingResult());
}
/**
* 其他异常
* @param e
* @return
*/
@ExceptionHandler(Exception.class)
@ResponseBody
public CommonResult<?> excetionHandler(Exception e){
log.error("未捕获异常:", e);
return CommonResult.fail(e.getMessage(), null);
}
}
mldong-admin/com/mldong/modules/sys/emuns/SysErrEnum.java
package com.mldong.modules.sys.enums;
import com.mldong.common.annotation.ErrEnum;
import com.mldong.common.base.CommonError;
/**
* 8000 9001-9999
* sys模块错误码定义
* @author mldong
*
*/
@ErrEnum(name="sys",value="系统管理",bizCode=8000,min=9001,max=9999)
public enum SysErrEnum implements CommonError {
/**
* 用户不存在
*/
SYS80000001(80009001, "用户不存在"),
/**
* 用户名或者密码错误
*/
SYS80000002(80009002, "用户名或者密码错误"),
/**
* 登录次数太多
*/
SYS80000003(80009003, "登录次数太多"),
/**
* 用户已被锁定
*/
SYS80000004(80009004, "用户已被锁定"),
/**
* 两密码不一致
*/
SYS80000005(80009005,"两密码不一致"),
/**
* 旧密码错误
*/
SYS80000006(80009006,"旧密码错误"),
/**
* 用户名已存在
*/
SYS80000007(80009007, "用户名已存在")
;
public final int value;
public final String name;
SysErrEnum(int value,String name) {
this.value = value;
this.name = name;
}
@Override
public int getValue() {
return this.value;
}
@Override
public String getName() {
return this.name;
}
}
mldong-admin/com/mldong/modules/sys/service/impl/SysUserServiceImpl.java
业务层使用样例
package com.mldong.modules.sys.service.impl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.mldong.common.base.CommonPage;
import com.mldong.common.exception.BizException;
import com.mldong.modules.sys.entity.SysUser;
import com.mldong.modules.sys.enums.SysErrEnum;
import com.mldong.modules.sys.mapper.SysUserMapper;
import com.mldong.modules.sys.service.SysUserService;
@Service
public class SysUserServiceImpl implements SysUserService{
@Autowired
private SysUserMapper sysUserMapper;
@Override
public int save(SysUser param) {
SysUser q = new SysUser();
q.setUserName(param.getUserName());
SysUser user = sysUserMapper.selectOne(q);
if(null!=user) {
// 用户已存在
throw new BizException(SysErrEnum.SYS80000007);
}
return sysUserMapper.insertSelective(param);
}
@Override
public int update(SysUser param) {
return sysUserMapper.updateByPrimaryKeySelective(param);
}
@Override
public int delete(Long id) {
return sysUserMapper.deleteByPrimaryKey(id);
}
@Override
public SysUser get(Long id) {
return sysUserMapper.selectByPrimaryKey(id);
}
@Override
public CommonPage<SysUser> list(SysUser t, int pageNum, int pageSize) {
Page<SysUser> page = PageHelper.startPage(pageNum, pageSize,true);
sysUserMapper.select(t);
return CommonPage.toPage(page);
}
}
启动运行项目
MldongAdminApplication.java
右键->Run As -> Java Application
访问演示
略
项目源码地址
- 后端
- 前端