2016-12-27 255 views
3

我試圖用java.util.concurrent.Callable執行簡單的異步REST控制器:春天開機MVC異步執行

@RequestMapping("/AsyncRequest") 
public Callable asyncRequest() { 
    return() -> { 
     Thread.sleep(3000); 
     return "reply"; 
    }; 
} 

然後我在瀏覽器中運行http://localhost/AsyncRequest兩次。 我在3秒內得到的第一個答案,但在6秒後的第二個答案。 似乎這些請求不是異步處理的。 爲什麼會發生這種情況?

+0

它看起來是處理這兩個請求的同一個線程。 –

+0

@Christopher Schneider,我查了線索ID,他們不一樣。 – Andrew

+0

不知道......我只是寫了一些功能相同的東西,無法重現您的結果。這是與Java 7和Pivotal tc服務器3.1.3 –

回答

2

Spring Boot的行爲真的取決於版本和配置。

下面的配置和代碼爲我工作:

入門

package com.stackoverflow.spring.boot.async; 

import org.springframework.boot.SpringApplication; 
import org.springframework.boot.autoconfigure.SpringBootApplication; 
import org.springframework.boot.builder.SpringApplicationBuilder; 
import org.springframework.context.annotation.Import; 

@Import(WebConfig.class) 
@SpringBootApplication 
public class WebMain { 
    private final SpringApplication application; 

    public WebMain() { 
    final SpringApplicationBuilder applicationBuilder = new SpringApplicationBuilder(WebMain.class); 
    application = applicationBuilder.build(); 
    } 

    public SpringApplication getApplication() { return application; } 

    public static void main(final String[] args) { 
    new WebMain().getApplication().run(args); 
    } 
} 

配置

package com.stackoverflow.spring.boot.async; 


import org.springframework.boot.context.embedded.ConfigurableEmbeddedServletContainer; 
import org.springframework.boot.context.embedded.EmbeddedServletContainerCustomizer; 
import org.springframework.context.annotation.Configuration; 
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; 

@Configuration 
public class WebConfig extends WebMvcConfigurerAdapter implements EmbeddedServletContainerCustomizer 
{ 
    public void customize(final ConfigurableEmbeddedServletContainer container) {} 
} 

控制器

我已將睡眠時間更改爲6秒,並在響應中添加了一些有效負載。

package com.stackoverflow.spring.boot.async; 

import org.springframework.stereotype.Controller; 
import org.springframework.web.bind.annotation.RequestMapping; 
import org.springframework.web.bind.annotation.RequestMethod; 
import org.springframework.web.bind.annotation.ResponseBody; 

import java.util.Date; 
import java.util.concurrent.Callable; 

@Controller 
public class AsyncController { 
    @RequestMapping(path = "/AsyncRequest", method = RequestMethod.GET) 
    @ResponseBody 
    public Callable<String> asyncRequest() { 
    return() -> { 
     final long currentThread = Thread.currentThread().getId(); 
     final Date requestProcessingStarted = new Date(); 

     Thread.sleep(6000L); 

     final Date requestProcessingFinished = new Date(); 

     return String.format(
      "request: [threadId: %s, started: %s - finished: %s]" 
      , currentThread, requestProcessingStarted, requestProcessingFinished); 
    }; 
    } 
} 

的pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
      xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> 

     <modelVersion>4.0.0</modelVersion> 

     <groupId>com.stackoverflow.spring.boot</groupId> 
     <artifactId>async</artifactId> 
     <packaging>jar</packaging> 
     <version>1.0-SNAPSHOT</version> 

     <properties> 
     <java.version>1.8</java.version> 
     <spring-boot.version>1.4.1.RELEASE</spring-boot.version> 
     </properties> 

     <dependencies> 
     <dependency> 
      <groupId>org.springframework.boot</groupId> 
      <artifactId>spring-boot-dependencies</artifactId> 
      <version>${spring-boot.version}</version> 
      <type>pom</type> 
      <scope>import</scope> 
     </dependency> 

     <dependency> 
      <groupId>org.springframework.boot</groupId> 
      <artifactId>spring-boot</artifactId> 
      <version>${spring-boot.version}</version> 
     </dependency> 

     <dependency> 
      <groupId>org.springframework.boot</groupId> 
      <artifactId>spring-boot-starter-web</artifactId> 
      <version>${spring-boot.version}</version> 
     </dependency> 

     <dependency> 
      <groupId>org.springframework.boot</groupId> 
      <artifactId>spring-boot-starter-actuator</artifactId> 
      <version>${spring-boot.version}</version> 
     </dependency> 
     </dependencies> 

     <build> 
     <plugins> 
      <plugin> 
      <groupId>org.apache.maven.plugins</groupId> 
      <artifactId>maven-compiler-plugin</artifactId> 
      <version>3.5.1</version> 
      <inherited>true</inherited> 
      <configuration> 
       <source>${java.version}</source> 
       <target>${java.version}</target> 
      </configuration> 
      </plugin> 

      <plugin> 
      <groupId>org.springframework.boot</groupId> 
      <artifactId>spring-boot-maven-plugin</artifactId> 
      <version>${spring-boot.version}</version> 
      <executions> 
       <execution> 
       <goals> 
        <goal>repackage</goal> 
       </goals> 
       <configuration> 
        <classifier>exec</classifier> 
       </configuration> 
       </execution> 
      </executions> 
      </plugin> 
     </plugins> 
     </build> 

    </project> 

測試

java -version 
java version "1.8.0_111" 
Java(TM) SE Runtime Environment (build 1.8.0_111-b14) 
Java HotSpot(TM) 64-Bit Server VM (build 25.111-b14, mixed mode) 

-- 
mvn spring-boot:run 
... 
-- 
# start following command from different consoles: 
curl http://localhost:8080/AsyncRequest 

結果

request: [threadId: 33, started: 15:50:28 - finished: 15:50:34] 
request: [threadId: 35, started: 15:50:29 - finished: 15:50:35] 
request: [threadId: 37, started: 15:50:30 - finished: 15:50:36] 
+1

謝謝你的答案。它幫助我找出問題所在。我的問題的原因是谷歌鉻:它優化了相同的網址的請求。在你的回答中你使用了捲曲。我試着用它來測試服務器,我得到了正確的結果。 – Andrew