Skip to content

多个返回值和错误码

使用透明RPC开发服务提供者,开发者很容易理解一个接口只有一个返回值类型。使用REST风格(Spring MVC 或者 JAXRS),很多场景会碰到多个返回值和错误码的情况。Java Chassis要求接口定义的返回值和错误码都 必须显示的声明,即通过代码生成的swagger,必须包含所有的错误码描述和返回值类型描述。 在Java Chassis,无法使用隐藏参数、未声明 的错误码。这样设计的直接好处是接口定义更加明确,不需要额外的文档帮助使用者理解接口的使用方法。

建议在进行API设计的时候,一个API只包含一个返回值类型,因为站在使用者的角度,不管使用RPC风格还是REST风格访问,都非常简洁和直观。保留多个返回值和错误码设计,更多的是为了API接口设计兼容的需要。

在前面的开发指导里面,主要介绍了一个返回值和一个错误码的情况(200)。 下面介绍如何使用多个错误码和返回值,同时会介绍如何返回额外的header参数。

Java Chassis将错误码进行了分类:2xx错误码认为是一个正常的响应,一个接口只允许存在一个正常响应错误码; 其他错误码认为是一个异常的响应,一个接口可以定义多个异常的响应,并且需要采用InvocationException的式将异常抛出,每个错误码可以指定不同的响应类型。

  • 采用ApiResponse定义多个返回值和错误码
@Path("/errorCode")
@POST
@ApiResponses({
  @ApiResponse(code = 200, response = MultiResponse200.class, message = ""),
  @ApiResponse(code = 400, response = MultiResponse400.class, message = ""),
  @ApiResponse(code = 500, response = MultiResponse500.class, message = "")})
public MultiResponse200 errorCode(MultiRequest request) {
    if (request.getCode() == 400) {
      MultiResponse400 r = new MultiResponse400();
      r.setCode(400);
      r.setMessage("bad request");
      throw new InvocationException(javax.ws.rs.core.Response.Status.BAD_REQUEST, r);
    } else if (request.getCode() == 500) {
      MultiResponse500 r = new MultiResponse500();
      r.setCode(500);
      r.setMessage("internal error");
      throw new InvocationException(javax.ws.rs.core.Response.Status.INTERNAL_SERVER_ERROR, r);
    } else {
      MultiResponse200 r = new MultiResponse200();
      r.setCode(200);
      r.setMessage("success result");
      return r;
    }
}
  • 采用 org.apache.servicecomb.swagger.invocation.Response 响应类型

采用 org.apache.servicecomb.swagger.invocation.Response 响应类型,除了可以定义多个错误码和响应类型,还可以通过 ResponseHeader 定义额外的响应头。

@Path("/errorCode")
@POST
@ApiResponses({
  @ApiResponse(code = 200, response = MultiResponse200.class, message = ""),
  @ApiResponse(code = 400, response = MultiResponse400.class, message = ""),
  @ApiResponse(code = 500, response = MultiResponse500.class, message = "")})
@ResponseHeaders({@ResponseHeader(name = "x-code", response = String.class)})
public Response errorCodeWithHeader(MultiRequest request) {
    Response response = new Response();
    if (request.getCode() == 400) {
      MultiResponse400 r = new MultiResponse400();
      r.setCode(400);
      r.setMessage("bad request");
      response.setStatus(Status.BAD_REQUEST);
      response.setResult(new InvocationException(Status.BAD_REQUEST, r));
      response.setHeader("x-code", "400");
    } else if (request.getCode() == 500) {
      MultiResponse500 r = new MultiResponse500();
      r.setCode(500);
      r.setMessage("internal error");
      response.setStatus(Status.INTERNAL_SERVER_ERROR);
      response.setResult(new InvocationException(Status.INTERNAL_SERVER_ERROR, r));
      response.setHeader("x-code", "500");
    } else {
      MultiResponse200 r = new MultiResponse200();
      r.setCode(200);
      r.setMessage("success result");
      response.setStatus(Status.OK);
      response.setResult(r);
      response.setHeader("x-code", "200");
    }
    return response;
}
  • 采用 javax.ws.rs.core.Response 响应类型

采用 javax.ws.rs.core.Response 响应类型,除了可以定义多个错误码和响应类型,还可以通过 ResponseHeader 定义额外的响应头。

@Path("/errorCodeWithHeaderJAXRS")
@POST
@ApiResponses({
  @ApiResponse(code = 200, response = MultiResponse200.class, message = ""),
  @ApiResponse(code = 400, response = MultiResponse400.class, message = ""),
  @ApiResponse(code = 500, response = MultiResponse500.class, message = "")})
public javax.ws.rs.core.Response errorCodeWithHeaderJAXRS(MultiRequest request) {
    javax.ws.rs.core.Response response;
    if (request.getCode() == 400) {
      MultiResponse400 r = new MultiResponse400();
      r.setCode(request.getCode());
      r.setMessage(request.getMessage());
      response = javax.ws.rs.core.Response.status(Status.BAD_REQUEST)
          .entity(new InvocationException(Status.BAD_REQUEST, r))
          .header("x-code", "400")
          .build();
    } else if (request.getCode() == 500) {
      MultiResponse500 r = new MultiResponse500();
      r.setCode(request.getCode());
      r.setMessage(request.getMessage());
      response = javax.ws.rs.core.Response.status(Status.INTERNAL_SERVER_ERROR)
          .entity(new InvocationException(Status.INTERNAL_SERVER_ERROR, r))
          .header("x-code", "500")
          .build();
    } else {
      MultiResponse200 r = new MultiResponse200();
      r.setCode(request.getCode());
      r.setMessage(request.getMessage());
      // If error code is OK family(like 200), we can use the target type.
      response = javax.ws.rs.core.Response.status(Status.OK)
          .entity(r)
          .header("x-code", "200")
          .build();
    }
    return response;
}