java - 使用 RestTemplate 异常处理的 Spring 端点到端点

标签 java spring rest exception

我们有一个微服务架构。每个服务都通过 Rest 公开数据。所有 Controller 都使用 Spring 设置:

@RestController
@RequestMapping(path = "foobar")
public class UiController {

      @PostMapping("foo")
      public ResponseEntity<Foo> addFoo(@RequestBody final FooDto fooDto) {

           Foo fromDb = adminService.addFoo(converterToModel.convert(fooDto);
           return ResponseEntity.ok(converterToDto.convert(fromDb));

      }

如果由于某种原因无法将 fooDto 添加到数据库中。抛出自定义异常:

@ResponseStatus(value = HttpStatus.CONFLICT)
public class FooAlreadyAssignedException extends RuntimeException {

    public FooAlreadyAssignedException(String msg) {
        super("The following foos are already assigned to foobar: " + msg);
    }

}

抛出上述异常后,在 Postman 中您会看到以下 JSON

{
    "timestamp": 1508247298817,
    "status": 409,
    "error": "Conflict",
    "exception": "com.foo.exception.FooCodeAlreadyExistsException",
    "message": "A foo with code: foo already exists",
    "path": "/foo/foobar"
}

我们有 4 种不同的服务,它们都以相同的方式设置。

我们的用户界面是在 Angular 4 中制作的,并对我们的网关进行 REST 调用。网关是微服务和 UI 之间的连接。它还公开了一个 REST 端点。它也是用 Spring 实现的。我添加了一张图片以进行说明:

architecture

“编辑:我看到我没有完成箭头。当然,所有数据都传回了 UI”

问题

网关使用 RestTemplate 调用微服务的 API 当在微服务中抛出自定义异常时,网关返回:

{
"timestamp": "2017-10-16T15:30:03.456Z",
"status": 500,
"error": "Internal Server Error",
"exception": "org.springframework.web.client.HttpClientErrorException",
"message": "409 null",
"path": "/v1/printstations"
}

我的原始响应 HttpStatus.conflict (status = 409) 似乎被网关包装在状态 500 消息中。我不想要这种行为,我希望它将原始消息传递给 UI。

关于如何控制这种行为的任何想法?

注意事项

我已经用 Postman 进行了测试,如果您直接访问微服务,它会返回 409 以及自定义异常中写入的消息

我已经尝试过重写 Springs ResponseErrorHandler,但无法通过这种方式找到合适的解决方案。

最佳答案

在 spring rest 模板调用您的微服务的网关代码中,我建议捕获 HttpClientErrorException 然后创建您自己的异常类,如 ApiException 如下例所示,这样您就可以传递从微服务:

catch (org.springframework.web.client.HttpClientErrorException e) {

            throw new ApiException(e.getMessage(), e, e.getRawStatusCode(), e.getResponseHeaders(),
                    e.getResponseBodyAsString(), fullURIPath, null);
        }

其中 ApiException 具有如下构造函数:

public ApiException(String message, Throwable throwable, int code, Map<String, List<String>> responseHeaders,
            String responseBody, String requestURI, String requestBody) {
        super(message, throwable);
        this.code = code;
        this.responseHeaders = responseHeaders;
        this.responseBody = responseBody;
        this.requestURI = requestURI;
        this.requestBody = requestBody;
    }

关于java - 使用 RestTemplate 异常处理的 Spring 端点到端点,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46774311/

相关文章:

java - 如何在 JavaCC 中处理文本 block 内的标记?

java - Spring 数据 JPA : Specification with "like" and Long

Spring Security 3.2 具有不同身份验证管理器的多个 http 标签

java - Spring 3.2 : Unit testing of @Scope ("request") no longer works

java - Tomcat:获取基于 Jersey 的 Rest 服务的短 URL

android - 我怎样才能摆脱 RxJava 调用链?

python - Django REST 框架——如何将外键解析为实际值,而不是索引?

java - 从 Eclipse 解密保存的密码

java - 如何从属性文件中读取值?

java - 使用 Jackson Exception 构建 RESTFul Web 服务