当前位置: 首页 > 知识库问答 >
问题:

使用RestTemplate检索状态代码为9xx的资源时,为什么流会关闭?

和飞翔
2023-03-14
@RequestMapping(value = "/users", method = RequestMethod.POST) throws UsernameExistsException, EmailExistsException
public UserProxy addUser(@RequestBody UserProxy userProxy) {
  ...
}
@EnableWebMvc
@ControllerAdvice
public class ControllerExceptionHandler {

  @ExceptionHandler(EmailExistsException.class)
  public ResponseEntity<String> handleEmailExistsException() {
    return ResponseEntity
            .status(UsersStatusCodes.EMAIL_EXISTS) // status code 912
            .body("Email already exists");
  }

  @ExceptionHandler(UsernameExistsException.class)
  public ResponseEntity<String> handleUsernameExistsException() {
    return ResponseEntity
            .status(UsersStatusCodes.USERNAME_EXISTS) // status code 911
            .body("Username already exists");
  }
}
org.springframework.web.client.ResourceAccessException: I/O error on POST request for "http://192.168.99.100:8080/users": stream is closed; nested exception is java.io.IOException: stream is closed
at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:673)
at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:620)
at org.springframework.web.client.RestTemplate.postForObject(RestTemplate.java:387)
at com.cheetahrunner.users.mongo.client.UsersClient.createUser(UsersClient.java:44)
at com.cheetahrunner.users.UsersServiceTest.addUser(UsersServiceTest.java:102)
at com.cheetahrunner.users.UsersServiceTest.testAddRemoveUser(UsersServiceTest.java:47)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:564)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
15:37:44.517 [main] DEBUG org.springframework.web.client.RestTemplate - POST request for "http://192.168.99.100:8080/users" resulted in 911 (null)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
    at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
    at org.apache.maven.surefire.junit4.JUnit4Provider.execute(JUnit4Provider.java:283)
    at org.apache.maven.surefire.junit4.JUnit4Provider.executeWithRerun(JUnit4Provider.java:173)
    at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:153)
    at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:128)
    at org.apache.maven.surefire.booter.ForkedBooter.invokeProviderInSameClassLoader(ForkedBooter.java:203)
    at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:155)
    at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:103)
Caused by: java.io.IOException: stream is closed
    at java.base/sun.net.www.protocol.http.HttpURLConnection$HttpInputStream.ensureOpen(HttpURLConnection.java:3417)
    at java.base/sun.net.www.protocol.http.HttpURLConnection$HttpInputStream.read(HttpURLConnection.java:3422)
    at java.base/java.io.FilterInputStream.read(FilterInputStream.java:83)
    at java.base/java.io.PushbackInputStream.read(PushbackInputStream.java:136)
    at org.springframework.web.client.MessageBodyClientHttpResponseWrapper.hasEmptyMessageBody(MessageBodyClientHttpResponseWrapper.java:102)
    at org.springframework.web.client.HttpMessageConverterExtractor.extractData(HttpMessageConverterExtractor.java:82)
    at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:662)
    ... 30 more
rest.exchange(host + "/users", HttpMethod.POST, new HttpEntity<UserProxy>(user), UserProxy.class)

可通过邮递员到达endpoint,在邮递员处收到状态文本为“用户名已存在”的911响应。

共有1个答案

冀阳文
2023-03-14

实现org.springframework.web.client.responseerrorhandler并将其设置为您的rest模板:

rest.setErrorHandler(errorHandler);

ResponseErrorHandler有两个方法:

/**
     * Indicate whether the given response has any errors.
     * <p>Implementations will typically inspect the
     * {@link ClientHttpResponse#getStatusCode() HttpStatus} of the response.
     * @param response the response to inspect
     * @return {@code true} if the response has an error; {@code false} otherwise
     * @throws IOException in case of I/O errors
     */
    boolean hasError(ClientHttpResponse response) throws IOException;

    /**
     * Handle the error in the given response.
     * <p>This method is only called when {@link #hasError(ClientHttpResponse)}
     * has returned {@code true}.
     * @param response the response with the error
     * @throws IOException in case of I/O errors
     */
    void handleError(ClientHttpResponse response) throws IOException;

在第二个中,您应该实现错误处理逻辑。

@Override
public boolean hasError(ClientHttpResponse response) throws IOException {
    HttpStatus code = response.getStatusCode();
    return code != HttpStatus.OK && code != HttpStatus.NO_CONTENT && code != HttpStatus.NOT_MODIFIED;
}
 类似资料:
  • 如上所示,使用cdn.bootcdn.net资源,但是每次请求都会从cdn服务器上重新获取资源,非常耗时,白屏很差长时间,查询发现Cache-Control值是no-cache, no-store, must-revalidate导致的,需要怎么修改呢?

  • 我正在为面向对象编程的秋季考试做准备,其中一种任务是提供代码输出,这通常包括一些异常处理问题。 现在我的问题是什么时候用资源尝试关闭它的资源,因为我的输出严格依赖于实现AutoCloseable的类的输出。 在提供的代码中,我不明白为什么“close 1”输出在“close 40”之前,或者为什么对象A(40)在这个块的末尾被关闭。是因为A(50)和A(40)是同一类型的吗? 我的主要问题是,Au

  • 我和我的团队正在尝试决定使用什么状态代码,我们通过Swagger生成的API客户端有一个< code>204 (No Content)条件,在本例中它比< code>404更有意义。 我们希望显示响应是成功的,但是没有返回< code>Object。 假设它是一个购物车:客户单击购物车并将您带到页面,请求发送到endpoint ,但购物车中没有项目,我们不希望它通过 API 客户端的 路径运行,但

  • 问题内容: 我正在学习EJB3,只是好奇何时可以方便地使用SFSB?当SFSB确实可以轻松解决一些复杂问题时,我找不到任何很好的示例。 实际上,我看到SLSB可以用作Web服务,这很方便。但我不知道何时使用SFSB。我只看到它的问题,因为我们应该学习一些有关它的知识,我们应该编写由批注组成的代码,其内容要少于完全注释,我们应该使用烦人的查找方法……而我们得到的任何回报都没有。 例如,我们不能使用S

  • PUT请求通常通过在更新之前隐式创建来对抗资源的不存在 成功的PUT请求通常将生成200或204(如果资源被更新--有或没有返回实际内容),以及201(如果资源被创建)

  • 问题内容: 大多数情况下,我看到的finally块仅用于 我的问题是,如果f的范围以封闭块结尾,为什么我们需要在finally中将其关闭? 问题答案: 因为垃圾回收与资源清理 不是 一回事。 例如,如果您有一个超出范围的JDBC连接对象,则没有信号发送到数据库服务器以指示不再需要打开的游标和连接。没有这些消息,您最终将耗尽可用的游标和连接数。 与文件句柄和任何其他资源相同。自己清理后。