Java微服务系统中错误检查位置:Service还是Controller?
错误检查的最佳实践:Service vs Controller
这是个很常见的职责划分问题,答案其实是两者都要参与,但各有侧重,核心就是遵循单一职责原则,让每层只做自己该做的事。
1. Service层:负责业务层面的错误检查与异常转化
Service的核心职责之一就是封装外部调用和业务逻辑,所以这里必须先处理外部HTTP调用的错误:
- 发起外部调用后,立刻检查返回结果(比如非2xx状态码、错误格式的响应体),把这些底层的技术错误转化为业务层面的异常或明确的错误对象——比如把HTTP 404转化为
ResourceNotFoundException,把5xx系列状态码转化为ExternalServiceUnavailableException。 - 这么做的好处很明显:Controller不需要关心外部服务的具体细节(比如对方返回的状态码含义、接口格式),只需要处理业务相关的异常类型;同时,后续如果替换外部服务或者调整调用逻辑,错误处理的代码只需要在Service层修改,不用动Controller。
- 举个伪代码示例(Java风格):
public ExternalData getExternalInfo(String requestParam) { ResponseEntity<ExternalData> response = restTemplate.getForEntity(EXTERNAL_API_URL, ExternalData.class); if (!response.getStatusCode().is2xxSuccessful()) { switch(response.getStatusCode()) { case NOT_FOUND: throw new ResourceNotFoundException("请求的外部资源不存在"); case SERVICE_UNAVAILABLE: case INTERNAL_SERVER_ERROR: throw new ExternalServiceUnavailableException("外部服务暂时无法访问,请稍后重试"); default: throw new BusinessException("外部调用失败,状态码:" + response.getStatusCodeValue()); } } return response.getBody(); }
2. Controller层:负责将错误转化为用户友好的网页响应
Controller的职责是处理请求、协调Service、返回面向用户的视图(网页),所以它的错误处理侧重在呈现:
- 捕获Service层抛出的各类业务异常,以及未被Service覆盖的意外异常;
- 根据不同的异常类型,返回对应的错误网页——比如给用户显示“资源不存在”的404页面、“服务暂时不可用”的提示页,或者通用的系统错误页;
- 也可以用全局异常处理器(比如Spring的
@ControllerAdvice)来统一处理,避免在每个Controller方法里重复写捕获逻辑。 - 伪代码示例:
@GetMapping("/show-info") public String showInfoPage(Model model, @RequestParam String param) { try { ExternalData data = externalService.getExternalInfo(param); model.addAttribute("info", data); return "info-detail-page"; } catch (ResourceNotFoundException e) { model.addAttribute("errorMessage", e.getMessage()); return "404-error-page"; } catch (ExternalServiceUnavailableException e) { model.addAttribute("errorMessage", e.getMessage()); return "service-unavailable-page"; } catch (Exception e) { model.addAttribute("errorMessage", "系统出现未知错误,请稍后再试"); return "general-error-page"; } }
总结
简单来说:Service管业务逻辑层面的错误识别与转化,把底层技术错误包装成上层能理解的业务异常;Controller管面向用户的错误响应呈现,把异常转化为用户能看懂的网页。这样分工既保证了代码的内聚性,也让错误处理逻辑清晰易维护。
内容的提问来源于stack exchange,提问作者Vito Lipari
相关产品推荐
相关产品推荐

