一个大型项目异常怎么处理才对

2018-06-15 22:39:11 +08:00
 victorwu34

我们的技术栈是 spring+mybatis+mysql,一共分为 4 层 请求-->rest-->manager-->领域(业务)-->service(增删改查服务)--->mapper--数据库 对于异常处理讨论出了非常奇怪的结果,比如一个情景,如果 mapper 访问数据库出现了异常,service 层拿到这个异常,记录错误日志,再包装成 service 层的异常抛向上一层,到了领域层,它重复 service 的任务(记录错误日志,再包装成领域的异常,再把新的异常抛向上一层),rest 层返回手动在 rest 层定义的错误代码给前端。一个错误被包装了好几次,生成多条错误日志,这样做的理论依据是什么呢?

4263 次点击
所在节点    Java
13 条回复
Athrob
2018-06-15 23:11:30 +08:00
感觉这样挺合适的, 不用去关心其他层怎样处理, 自己这层有异常了处理好再往上抛就行.
neoblackcap
2018-06-15 23:21:29 +08:00
异常不都这样吗?能处理就处理,不能处理就中断,挂掉防止进一步出错吗?
gzq527
2018-06-15 23:22:33 +08:00
spring mvc 有统一异常处理机制。
gzq527
2018-06-15 23:24:02 +08:00
在 rest 层捕获异常,其它层都往上抛
serical
2018-06-16 02:03:35 +08:00
统一异常处理 RestControllerAdvice
lrh3321
2018-06-16 06:46:20 +08:00
统一处理异常,ControllerAdvice。service 碰到不知道怎么处理的异常,就根据业务 /异常类型封装成自己定义的异常,直接往上抛。
loongwang
2018-06-16 09:30:16 +08:00
统一异常处理+1.
自定义错误码,实现 HandlerExceptionResolver
如果是自定义异常,从资源文件解析错误码对应的错误信息。
如果非自定义,log+默认错误码。
前端也需要一套捕捉机制
loongwang
2018-06-16 09:31:30 +08:00
贴一下我司的实现


@Override
public ModelAndView resolveException(HttpServletRequest request,
HttpServletResponse response, Object handler, Exception e) {
BusinessException exception;
ErrorRes errorRes;
if (e instanceof BusinessException) {
exception = (BusinessException) e;
errorRes = new ErrorRes("" + exception.getErrorCode(),
exception.getMessage(), exception.getErrorParameters());
logger.warn(
errMsgLogid
+ String.format(
"warn code:%s, errorMessage:%s, errorParameters:%s",
exception.getErrorCode(),
exception.getMessage(),
exception.getErrorParameters()), e);
} else {
exception = new BusinessException(ErrorCode.SYSTEM_ERROR, e);
errorRes = new ErrorRes("" + exception.getErrorCode(),
exception.getMessage());
// 获取异常名称
String exceptionName = e.getClass().getName();
if ("org.apache.catalina.connector.ClientAbortException"
.equalsIgnoreCase(exceptionName)) {
logger.warn(errMsgLogid + "system warn:", e);
} else if ("javax.ws.rs.ClientErrorException"
.equalsIgnoreCase(exceptionName)) {
logger.warn(errMsgLogid + "system warn:", e);
} else {
logger.error(errMsgLogid + "system error:", e);
}
}
PrintWriter responseWriter = null;
try {
response.setContentType("application/json;");
response.setCharacterEncoding("UTF-8");
response.setStatus(Response.SC_OK);
responseWriter = response.getWriter();
responseWriter.write(JSON.toJSONString(errorRes));
responseWriter.flush();
} catch (IOException e1) {
logger.error(errMsgLogid, e1);
} finally {
if (responseWriter != null) {
responseWriter.close();
}
}
return new ModelAndView();
}
swim2sun
2018-06-17 14:34:34 +08:00
出现数据库这种异常,一层一层捕获再往上抛是不妥的,直接抛个运行时异常,再使用 Spring MVC 的全局异常处理就行了。太多处理异常的代码会导致代码可维护性和可读性都大打折扣
victorwu34
2018-06-20 10:30:20 +08:00
@Athrob 实际是系统中每一层都不处理异常,而是把异常的 stacktrack+自己写的上下文放进一个自定义的,继承与 runtime exception 的异常中,直到 rest 层再把自定义异常中的信息取出来,返回给前端的 json 中(异常实际上处理方式都是返回前端)。你不觉得这些异常包装都是空架子吗,最多提供了点儿上下文
victorwu34
2018-06-20 10:32:14 +08:00
@gzq527 我们没用 mvc,这样不是多加了依赖吗
victorwu34
2018-06-21 22:30:05 +08:00
@loongwang 很复杂,还没看明白
loongwang
2018-06-22 10:28:46 +08:00
@victorwu34

@swim2sun 说的很正确,我上面贴的代码就是这个意思.

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/463497

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX