在web后台使用controller、service、dao模式开发时。controller负责调用业务方法和返回前台数据,service层负责处理业务逻辑返回数据到controller,dao负责访问数据库。因为service返回的数据需要在controller层包装下才能返回到前台。而service的返回值只有一种。对于复杂的异常情况(非程序异常)来说是不够的,所以返回的都是正常业务的数据。
对于此种情况可以使用自定义异常来处理。
基本思路:
1、自定义一个异常类。
2、编写全局的异常处理类,捕获自定义异常统一处理,生成前台可识别的消息返回给前台。
3、service层处理业务逻辑遇到异常情况时throw自定义异常。
代码实现:
1、自定义异常类
public class ExpectedException extends RuntimeException {
private static final long serialVersionUID = 4061732202885069884L;
/**
* 错误码
*/
private int code;
/**
* 错误描述
*/
private String msg;
public ExpectedException(int code, String msg) {
super(msg);
this.code = code;
this.msg = msg;
}
public ExpectedException(String msg) {
super(msg);
//通用错误码,可以使用常量或枚举
this.code = 500;
this.msg = msg;
}
/**
* 重写堆栈填充,不填充错误堆栈信息,提高性能
*/
@Override
public Throwable fillInStackTrace() {
return this;
}
}
因为该异常不是程序异常,所以没有必要记录异常栈信息,所以重写fillInStackTrace方法。且记录异常栈信息非常影响性能。
2、异常处理类,使用spingboot的@RestControllerAdvice注解来实现。
@RestControllerAdvice
@Slf4j
public class MyExceptionHandler extends BaseController {
@ExceptionHandler(value = Exception.class)
@ResponseBody
public Response defaultExceptionHandler(Exception exception) throws Exception {
Response result = new Response();
result.setSuccess(false);
try {
throw exception;
} catch (ExpectedException e) {
//自定义异常处理,返回前台能识别的状态码和描述
log.error(e.getMessage());
result.setCode(e.getCode());
result.setMessage(e.getMsg());
} catch (Exception e) {
//其他异常统一处理,上面也可以加上一些特别的异常处理
log.error(e.getMessage(), e);
result.setCode(WebError.SYS_ERROR_CODE);
result.setMessage(WebError.SYS_ERROR_MSG);
}
log.info(result.toString());
return result;
}
}
3、service层业务逻辑异常时throw自定义异常
public User getUser(String id){
User user = userDao.get(id);
if (user == null) {
throw new ExpectedException("该用户不存在");
}
return user;
}