java项目怎么把service层的异常信息返回到controller层?

一、代码描述(伪代码)

@Data
// controller层返回结果封装
public class Response<T>{
    private int code; // 正常响应数据是200,请求数据失败是300
    private String msg; // 如果有报错,则在这里添加错误信息的描述
    private T data; // 响应结果
}

@RestController
public class TestController{

    @Autowired
    private ITestService testService; 

    @GetMapping("/test")
    public Response test(){
        testService.getUserMsg();
        ......
        把响应结果封装到Response,然后返回
    }
}

@Service
public class TestServiceImpl implements ITestService{
    
    @Override
    // 返回类型先用Object代替
    public Object getUserMsg(){
        // 1、查数据库
        // 2、调别的接口获取数据
        // 3、封装结果返回
    }
}

二、问题描述

假如 getUserMsg() 中的某一步出错了,会抛异常或者导致查询结果为空,我需要把这个信息返回给前端(比如是我这边查询接口出问题导致报错了),即封装到Response的msg里面。
最开始我的设想是在service层那里,把 getUserMsg() 的返回数据类型设置为Response,这样不管哪一步出问题,我都能及时把msg set进去。但是给我review代码的领导的意思是不要在service层里用到像Response这种用于响应结果(controller层)的结构,即:controller拿到结果以后再把结果封装进Response里面。
1、请问从代码规范的角度来说,是否如此?

后来我想了个办法,其实效果和上面提到的差不多,就是让 getUserMsg() 返回一个Map<String, Object> map,这个map里面有查询结果和错误信息描述。
2、请问如果要实现我说的那种要求:能把service的错误信息传递到前端(不直接暴露异常信息,会在语言上优化),有没有好的实现方式?



阅读 6.5k
2 个回答

问题1:这个没有明确的规范/最佳实践,我觉得部门内/项目内统一就好。不用Response无非再定义个其它数据封装。不封装的话说实话对于异常信息的推广性比较差。
问题2:还有一种在service抛自定义异常然后在外层用切面统一捕捉封装返回前端的方式,关于这种方式的争论比较多,不过实际用起来真的香...性能影响也没有太大感觉。

主流做法一般是在外层创建一个 advice 来统一捕捉错误并处理成返回给前端的格式。

@RestControllerAdvice
public class ExceptionAdvice {

  @ExceptionHandler(RuntimeException.class)
  public Response handleRuntimeException(RuntimeException e) {
    // ...
  }

}

具体用法自己查相关资料吧,这样做的好处是 service 不会跟返回格式耦合,而在 controller 也不需要去单独 catch 错误来处理。

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题