0

我已经使用 spring 框架和 REST 开发了一些异步 Web 服务,我已经从使用 spring class 创建的客户端使用它AsyncRestTemplate。类返回一个对象ListenableFuture<ResponseEntity<T>>(使用方法getForEntity),它带来 Web 服务返回的值(使用方法.get():<T>)。它工作得很好,但是当 web 服务需要很长时间时isDone()ListenableFuture类的方法会返回一个 value true,即使 web 服务还没有完成工作。

如果我尝试使用get()客户端中的方法恢复 Web 服务响应并且它已经晚了很多时间,我总是会收到以下消息:

   "timestamp": "2018-05-29T22:42:26.978+0000",
   "status": 500,
   "error": "Internal Server Error",
   "message": "java.util.concurrent.ExecutionException: org.springframework.web.client.HttpServerErrorException: 503 null",
   "path": "/client/result"

有人知道我该如何解决这个问题吗?我希望客户端向我显示 Web 服务响应,即使 Web 服务需要很长时间(我想增加超时)。

服务器代码如下:

配置类:

@Configuration
@EnableAsync
public class ConfigurationClass {
    @Bean
    public Executor threadPoolTaskExecutor() {
        return new ThreadPoolTaskExecutor();
    }
}

控制器类:

@RestController
@RequestMapping("/server")
public class ControllerClass {

    @GetMapping("/start")
    @Async
    public CompletableFuture<String>  callService() throws InterruptedException{
        Thread.sleep(100000L);
        return CompletableFuture.completedFuture("OK");
    }
}

客户端代码(消费者)如下:

@RestController
@RequestMapping("/client")
public class ControllerClass {

    private ListenableFuture<ResponseEntity<String>> entity;

    @GetMapping("/start")
    @Async
    public void callService() throws InterruptedException {
        AsyncRestTemplate restTemplate = new AsyncRestTemplate();
        entity = restTemplate.getForEntity("http://localhost:8080/server/start",
                 String.class);
    }

    @GetMapping("/state")
    public boolean getState() {
        try {
            return entity.isDone();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    @GetMapping("/result")
    public ResponseEntity<String> getResult() {
        try {
            return entity.get();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}

我试图增加 application.property 文件中的属性超时,但它不起作用。

# SPRING MVC (WebMvcProperties)
spring.mvc.async.request-timeout= 500000 # Amount of time before asynchronous request handling times out.

感谢您的帮助,问候。

4

1 回答 1

0

为了更好的维护,你可以配置一个 AsyncRestTemplate bean:

@Bean
public AsyncRestTemplate asyncRestTemplate() {
    SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory();
    factory.setTaskExecutor(new SimpleAsyncTaskExecutor());
    factory.setConnectTimeout(1000);//milliseconds
    factory.setReadTimeout(2000);//milliseconds
    return new AsyncRestTemplate(factory);
}

然后,自动装配这个 bean:

@Autowired
private AsyncRestTemplate restTemplate;

之后,更新您的 callService:

@GetMapping("/start")
public void callService() throws InterruptedException {
    entity = restTemplate.getForEntity("http://localhost:8080/server/start",
             String.class);
}

您可以删除@Async注释,因为它AsyncRestTemplate是异步的。

于 2019-01-30T10:05:50.097 回答