Следующая конечная точка REST, показанная ниже, работает так, как ожидается, когда приложение SpringBoot запускается из исполняемого JAR. То есть, он возвращает клиенту текст «Мой тестовый ответ». Тем не менее, когда я упаковываю то же приложение, что и WAR, и развертываю его в Tomcat (8.0.29), он выдает следующее исключение:Как включить поддержку async в приложении Springboot, упакованном и развернутом как WAR
Произошла непредвиденная ошибка (тип = Внутренняя ошибка сервера, статус = 500). Поддержка Async должна быть включена на сервлете и для всех фильтров, участвующих в обработке запроса async. Это делается в Java-коде с использованием API-интерфейса Servlet или добавлением «true» в объявления сервлетов и фильтров в web.xml.
package my.rest.controllers;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.io.OutputStream;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.mvc.method.annotation.StreamingResponseBody;
@RestController
@RequestMapping("/api/file")
public class FileContentRestController {
static final int BUFFER = 2048;
@RequestMapping(value = "/content", method = RequestMethod.GET)
@ResponseBody
public StreamingResponseBody getFileContent(HttpServletResponse response) {
response.setContentType("text/plain");
response.setCharacterEncoding("UTF-8");
final InputStream portalFileStream = new ByteArrayInputStream("My test response".getBytes());
return (OutputStream outputStream) -> {
int n;
byte[] buffer = new byte[1024];
while ((n = portalFileStream.read(buffer)) > -1) {
outputStream.write(buffer, 0, n);
}
portalFileStream.close();
};
}
}
Мое понимание от here и в других местах, что SpringBoot обеспечивает поддержку асинхронной всех фильтров и сервлетов зарегистрированных SpringBoot. Вероятно, это будет случай, когда вы запускаете автономный JAR со встроенным контейнером Tomcat.
Как я могу обеспечить поддержку async при развертывании в качестве WAR?
Мое приложение SpringBoot настроен таким образом:
package my;
import com.fasterxml.jackson.core.JsonProcessingException;
import org.springframework.boot.Banner;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.support.SpringBootServletInitializer;
import org.springframework.scheduling.annotation.EnableAsync;
@SpringBootApplication
@EnableAsync
public class MyRestApp extends SpringBootServletInitializer {
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
return configureApplication(builder);
}
public static void main(String[] args) throws JsonProcessingException {
configureApplication(new SpringApplicationBuilder()).run(args);
}
private static SpringApplicationBuilder configureApplication(SpringApplicationBuilder builder) {
return builder.sources(MyRestApp.class).bannerMode(Banner.Mode.OFF);
}
}
с MVC сконфигурирован таким образом:
package my;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.task.AsyncTaskExecutor;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.web.servlet.config.annotation.AsyncSupportConfigurer;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
@Configuration
@EnableWebMvc
@EnableAsync
public class MyMvcConfiguration extends WebMvcConfigurerAdapter {
@Override
public void configureAsyncSupport(AsyncSupportConfigurer configurer) {
configurer.setDefaultTimeout(-1);
configurer.setTaskExecutor(asyncTaskExecutor());
}
@Bean
public AsyncTaskExecutor asyncTaskExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(2);
executor.setMaxPoolSize(2);
executor.setQueueCapacity(500);
executor.setThreadNamePrefix("SpringAsyncThread-");
executor.initialize();
return executor;
}
@Bean
public WebMvcConfigurer corsConfigurer() {
return new WebMvcConfigurerAdapter() {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedMethods("GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS");
}
};
}
}
Наконец, приложение построен и упаковывают с использованием Maven со следующим POM:
<?xml version="1.0" encoding="UTF-8"?>
<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/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.acme</groupId>
<artifactId>my-rest-app</artifactId>
<version>1.0.0-SNAPSHOT</version>
<packaging>war</packaging>
<name>my-rest-app</name>
<description></description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.4.1.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<resources>
<resource>
<directory>${project.basedir}/src/main/resources</directory>
</resource>
<resource>
<directory>${project.build.directory}/generated-resources</directory>
</resource>
</resources>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
Приложение 'springboot', вероятно, не имеет файла' web.xml' – pleft
Jep, только что отредактировал мой ответ – smsnheck
Что это значит сделать, это создать сервлет диспетчера, настроенный с внешним XML-файлом, поэтому я получаю: java.io. FileNotFoundException: Не удалось открыть ресурс ServletContext [/WEB-INF/dispatcherServlet-servlet.xml] . –