Gar*_*hes 5 java war servlet-3.0 spring-boot
当我的SpringBoot应用程序从可执行JAR运行时,下面显示的以下REST端点可以按预期工作。即,它将文本“我的测试响应”返回给客户端。但是,当我打包与WAR相同的应用程序并部署到Tomcat(8.0.29)时,它将引发以下异常:
发生意外错误(类型=内部服务器错误,状态= 500)。必须在Servlet上以及对异步请求处理中涉及的所有过滤器启用异步支持。这是通过Java代码使用Servlet API或通过在Web.xml中的Servlet和过滤器声明中添加“ true”来完成的。
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();
};
}
}
Run Code Online (Sandbox Code Playgroud)
从这里和其他地方我的理解是,SpringBoot在SpringBoot注册的所有过滤器和servlet上启用了异步支持。从带有嵌入式Tomcat容器的独立JAR运行时,肯定会出现这种情况。
部署为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);
}
}
Run Code Online (Sandbox Code Playgroud)
如此配置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");
}
};
}
}
Run Code Online (Sandbox Code Playgroud)
最后,使用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>
Run Code Online (Sandbox Code Playgroud)
那么你解析的异常说明了一切:
出现意外错误(类型=内部服务器错误,状态=500)。必须在 servlet 和异步请求处理中涉及的所有过滤器上启用异步支持。这是使用 Servlet API 在 Java 代码中完成的,或者通过向 web.xml 中的 servlet 和过滤器声明添加“true”来完成。
因此,您需要在 web.xml 中启用它,或者(并且因为您使用的是 spring-boot 应用程序)您必须配置一个特定的 bean。
也许您 AppConfig 的这个代码片段会有所帮助
@Bean
public ServletRegistrationBean dispatcherServlet() {
ServletRegistrationBean registration = new ServletRegistrationBean(new DispatcherServlet(), "/");
registration.setAsyncSupported(true);
return registration;
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
5482 次 |
| 最近记录: |