自定义异常的教程社区上有很多,今天抽空研究了一下把自定义的异常信息写到配置文件中,自我感觉这样便于使用与维护,下面简单分享一下
1,springboot常用的pom依赖就不列出来了,这里我加了一个依赖
commons-configuration
commons-configuration
1.8
2,SpringBoot中有一个@ControllerAdvice的注解,使用该注解表示开启了全局异常的捕获,我们只需在自定义一个方法使用@ExceptionHandler注解然后定义捕获异常的类型即可对这些捕获的异常进行统一的处理。
但是还要得加上@ResponseBody注解,所以这里我使用的是@RestControllerAdvice注解,这样就不需要在每个方法上添加@ResponseBody注解了。这里使用的是springboot集成mybatis完成数据库操作的业务逻辑。
3,代码分析:
自定义异常类
public class BizException extends RuntimeException implements java.io.Serializable {
private static final long serialVersionUID = 1L;
/**
* 错误码
*/
protected String errorCode;
/**
* 错误信息
*/
protected String errorMsg;
public BizException() {
super();
}
/**
* 根据key构造带参数或不带参数的异常信息
* @param key
* @param values
*/
public BizException(String key, String... values) {
String content = getExContent(key);
if (StringUtils.isNotBlank(content)) {
String[] messageArr = content.split(":");
this.errorCode = messageArr[0];
if(values != null) {
//配置文件中使用%s占位,使用String.format转换
this.errorMsg = String.format(messageArr[1], values);
}
}else{
this.errorCode = "-1";
this.errorMsg = "未定义异常!";
}
}
public String getErrorCode() {
return errorCode;
}
public void setErrorCode(String errorCode) {
this.errorCode = errorCode;
}
public String getErrorMsg() {
return errorMsg;
}
public void setErrorMsg(String errorMsg) {
this.errorMsg = errorMsg;
}
/**
* 从配置文件中获取自定义异常的内容
* @param key
* @return
*/
private String getExContent(String key){
PropertiesConfiguration configuration = null;
try {
configuration = new PropertiesConfiguration("src/main/resources/exception/define-err.properties");
} catch (ConfigurationException e) {
e.printStackTrace();
}
return configuration.getString(key);
}
}
自定义数据格式
public class ResponseVo {
private String code;
private String msg;
private Object data;
public ResponseVo() {
}
public ResponseVo(String code, String msg) {
this.code = code;
this.msg = msg;
}
public ResponseVo(String code, String msg, Object data) {
this.code = code;
this.msg = msg;
this.data = data;
}
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
public Object getData() {
return data;
}
public void setData(Object data) {
this.data = data;
}
/**
* 成功
* @return
*/
public static ResponseVo success() {
return success(null);
}
/**
* 成功
* @param data
* @return
*/
public static ResponseVo success(Object data) {
ResponseVo rv = new ResponseVo();
rv.setCode("0");
rv.setMsg("操作成功");
rv.setData(data);
return rv;
}
/**
* 失败
* @param code
* @param msg
* @return
*/
public static ResponseVo error(String code, String msg) {
ResponseVo rv = new ResponseVo();
rv.setCode(code);
rv.setMsg(msg);
rv.setData(null);
return rv;
}
/**
* 失败
* @param msg
* @return
*/
public static ResponseVo error(String msg) {
ResponseVo rv = new ResponseVo();
rv.setCode("-1");
rv.setMsg(msg);
rv.setData(null);
return rv;
}
}
自定义全局异常处理类
@RestControllerAdvice
public class BaseExceptionHandler {
protected Logger logger = LoggerFactory.getLogger(BaseExceptionHandler.class);
/**
* 处理自定义的业务异常
* @param e
* @return
*/
@ExceptionHandler(value = BizException.class)
public ResponseVo bizExceptionHandler(BizException e){
logger.error("发生业务异常!原因是:",e.getErrorMsg());
return ResponseVo.error(e.getErrorCode(),e.getErrorMsg());
}
/**
* 处理其他异常
* @param e
* @return
*/
@ExceptionHandler(value =Exception.class)
public ResponseVo exceptionHandler(Exception e){
logger.error("未知异常!原因是: ",e);
return ResponseVo.error("系统内部错误");
}
}
define-err.properties异常配置文件
sys.err.with.username.exist=000001:用户%s已存在
sys.err.with.username.lack=000002:缺失用户名
service接口和实现类的相关代码(mapper和实体是使用mybatis逆向工程自动生成的这里就不贴出来了,只展示拓展的mapper,用来自定义SQL的),这里以新增方法为例子
@Repository
public interface SysUserExpMapper {
SysUser findUserByUserName(@Param("userName") String userName);
}
public interface SysUserService {
SysUser insertSysUser(SysUser sysUser);
}
@Service
@Transactional
public class SysUserServiceImpl implements SysUserService{
@Autowired
private SysUserMapper sysUserMapper;
@Autowired
private SysUserExpMapper sysUserExpMapper;
@Override
public SysUser insertSysUser(SysUser sysUser) {
if (StringUtils.isBlank(sysUser.getUserName())){
throw new BizException("sys.err.with.username.lack");
}
SysUser haveUser = sysUserExpMapper.findUserByUserName(sysUser.getUserName());
if (haveUser != null){
throw new BizException("sys.err.with.username.exist", sysUser.getUserName());
}
String id = IdGenerateUtil.generateId();
sysUser.setId(id);
sysUser.setCreateBy("system");
sysUser.setCreateDate(new Date());
sysUser.setEnabled("Y");
sysUser.setDeleteFlag("N");
sysUserMapper.insert(sysUser);
return sysUser;
}
}
controller的代码比较干净一般只做服务调用就好,逻辑尽量都写在service实现类里面
@Api(tags = {"用户管理"})
@RestController
@RequestMapping("/system")
public class SysUserController {
@Autowired
private SysUserService sysUserServiceImpl;
@ApiOperation(value="新增用户", notes = "返回用户信息")
@RequestMapping(value = "/insertSysUser", method = RequestMethod.POST)
public ResponseVo insertSysUser(@RequestBody @ApiParam SysUser sysUser) {
SysUser user = sysUserServiceImpl.insertSysUser(sysUser);
ResponseVo responseVo = ResponseVo.success(user);
return responseVo;
}
}