无法使用 Spring Boot 和 Jersey 2 提供静态内容
Can't serve static content with Spring Boot and Jersey 2
有没有什么方法可以让 Spring Boot with Jersey 提供静态内容?我浏览了一系列关于将 Swagger 集成到 Spring Boot 应用程序的教程和代码示例。我可以让它提供基本的 swagger.json,但我不能让 Swagger UI 工作。
我什至不能让它传送一个简单的 hello.txt
静态文件。
我的 pom.xml 的相关部分是:
<!--Spring Boot-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<!-- Jersey -->
<dependency>
<groupId>org.glassfish.jersey.core</groupId>
<artifactId>jersey-client</artifactId>
<version>${jersey.version}</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.ext</groupId>
<artifactId>jersey-spring3</artifactId>
<version>${jersey.version}</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.ext</groupId>
<artifactId>jersey-bean-validation</artifactId>
<version>${jersey.version}</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-container-servlet</artifactId>
<version>${jersey.version}</version>
</dependency>
<!-- Swagger -->
<dependency>
<groupId>io.swagger</groupId>
<artifactId>swagger-jersey2-jaxrs</artifactId>
<version>1.5.7</version>
</dependency>
还有我的代码:
@Configuration
@EnableAutoConfiguration
@ComponentScan({"com.xxxx"})
public class AdminApplication {
public static void main(String[] args) {
ConfigurableApplicationContext applicationContext = new SpringApplicationBuilder(AdminApplication.class)
.run(args);
}
@Bean
public ServletRegistrationBean jerseyServlet() {
ServletRegistrationBean registration = new ServletRegistrationBean(new ServletContainer(), "/*");
registration.addInitParameter(ServletProperties.JAXRS_APPLICATION_CLASS, JerseyConfig.class.getName());
return registration;
}
}
package com.xxxxxx.admin.config;
import com.xxxxxx.admin.resource.Status;
import org.glassfish.jersey.filter.LoggingFilter;
import org.glassfish.jersey.server.ResourceConfig;
import org.glassfish.jersey.server.ServerProperties;
import org.glassfish.jersey.server.spring.scope.RequestContextFilter;
import io.swagger.jaxrs.config.BeanConfig;
public class JerseyConfig extends ResourceConfig {
public JerseyConfig() {
register(RequestContextFilter.class);
packages("com"); // TODO needs more detailed level
register(LoggingFilter.class);
// Validation
this.property(ServerProperties.BV_SEND_ERROR_IN_RESPONSE, true);
this.property(ServerProperties.RESPONSE_SET_STATUS_OVER_SEND_ERROR, true);
configureSwagger();
}
private void configureSwagger() {
register(io.swagger.jaxrs.listing.ApiListingResource.class);
register(io.swagger.jaxrs.listing.SwaggerSerializers.class);
BeanConfig beanConfig = new BeanConfig();
beanConfig.setVersion("1.0.0");
beanConfig.setSchemes(new String[]{"http"});
beanConfig.setHost("localhost:8080");
beanConfig.setBasePath("/"); // tried other things like "/api", but doesn't change anything
beanConfig.setResourcePackage("com.xxxxxx.admin");
beanConfig.setPrettyPrint(true);
beanConfig.setScan(true);
}
}
//other imports
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
@Service
@Path("/status")
@Api(value = "status", description = "Check status")
public class Status {
@GET
@Produces(MediaType.APPLICATION_JSON)
@ApiOperation("Return status")
public Response status() {
return Response.ok("Up").build();
}
}
我还尝试将 Jersey 运行 作为过滤器(使用 spring.jersey.type=filter
)并按照 中所述更改 Jersey 的 servlet 模式,但这似乎没有任何影响。
@ApplicationPath("/rootPath")
public class JerseyConfig extends ResourceConfig {
我在 /src/main/resources/public 下有一个 hello.txt 文件,在 /src/main/resources/public/swagger.
下有一个 Swagger UI 的静态文件
正如我所说,我的应用程序运行良好,GET http://localhost:8080/swagger.json shows me the plain json documentation, but both http://localhost:8080/hello.txt and http://localhost:8080/swagger/index.html return 404.
我正在使用 Jersey 2.8 和 Spring Boot 1.3.0
I also tried changing Jersey's servlet pattern
@ApplicationPath("/rootPath")
public class JerseyConfig extends ResourceConfig {
您配置应用程序的方式与 @ApplicationPath
无关。它适用于 的原因是因为 Spring 引导自动配置在从您的资源配置中提取 @ApplicationPath
值时设置了 servlet 映射。
您目前没有使用 Spring Boot 提供的 ServletRegistrationBean
来完成此操作。如果您的目标是使用您自己的 ServletRegistrationBean
,以便您可以注册您的 ResourceConfig
,您也可以通过
来完成相同的操作
- 用
@Component
注释你的 ResourceConfig
使其成为 Spring bean,或者
在您的配置中将其设为 Spring bean class
@Bean
public ResourceConfig config() {
return new JerseyConfig();
}
Spring Boot 然后会将您的 ResourceConfig
注入 JerseyAutoConfiguration
,它将在 ResourceConfig
上获得 @ApplicationPath
值(如果存在) , 并用它来注册自己的 ServletRegistrationBean
.
当您让 Spring Boot 处理配置时,您可以看到 JerseyAutoConfiguration
了解您免费获得的一切。
如果你想保持当前的 SpringRegistrationBean
,只需更改你正在使用的路径。您正在使用 /*
,这是链接答案中提到的问题。因此,如果您需要,只需更改为 /rooPath/*
。
它看起来与使用 Spring MVC 时的常见问题相同。每个 servlet 规范都需要一个 servlet 容器来实现具有最低优先级的默认服务器,该服务器能够为位于 WEB-INF 文件夹之外的静态内容提供服务。
不幸的是,您正在将 Jersey servlet 映射到 "/*"
,这意味着每个 URL 都将提交给 Jersey,而 Jersey 不知道如何处理静态 URLs.
那么可以(轻松)完成哪些工作?
将 Jersey servlet 映射到一个子路径(比如 /api
)并将所有控制器移动到那里:
ServletRegistrationBean registration =
new ServletRegistrationBean(new ServletContainer(), "/api/*");
...
beanConfig.setBasePath("/api/");
并询问GET http://localhost:8080/api/swagger.json
仅将 servlet 映射到 *.json
URLs:
ServletRegistrationBean registration =
new ServletRegistrationBean(new ServletContainer(), "*.json");
有没有什么方法可以让 Spring Boot with Jersey 提供静态内容?我浏览了一系列关于将 Swagger 集成到 Spring Boot 应用程序的教程和代码示例。我可以让它提供基本的 swagger.json,但我不能让 Swagger UI 工作。
我什至不能让它传送一个简单的 hello.txt
静态文件。
我的 pom.xml 的相关部分是:
<!--Spring Boot-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<!-- Jersey -->
<dependency>
<groupId>org.glassfish.jersey.core</groupId>
<artifactId>jersey-client</artifactId>
<version>${jersey.version}</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.ext</groupId>
<artifactId>jersey-spring3</artifactId>
<version>${jersey.version}</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.ext</groupId>
<artifactId>jersey-bean-validation</artifactId>
<version>${jersey.version}</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-container-servlet</artifactId>
<version>${jersey.version}</version>
</dependency>
<!-- Swagger -->
<dependency>
<groupId>io.swagger</groupId>
<artifactId>swagger-jersey2-jaxrs</artifactId>
<version>1.5.7</version>
</dependency>
还有我的代码:
@Configuration
@EnableAutoConfiguration
@ComponentScan({"com.xxxx"})
public class AdminApplication {
public static void main(String[] args) {
ConfigurableApplicationContext applicationContext = new SpringApplicationBuilder(AdminApplication.class)
.run(args);
}
@Bean
public ServletRegistrationBean jerseyServlet() {
ServletRegistrationBean registration = new ServletRegistrationBean(new ServletContainer(), "/*");
registration.addInitParameter(ServletProperties.JAXRS_APPLICATION_CLASS, JerseyConfig.class.getName());
return registration;
}
}
package com.xxxxxx.admin.config;
import com.xxxxxx.admin.resource.Status;
import org.glassfish.jersey.filter.LoggingFilter;
import org.glassfish.jersey.server.ResourceConfig;
import org.glassfish.jersey.server.ServerProperties;
import org.glassfish.jersey.server.spring.scope.RequestContextFilter;
import io.swagger.jaxrs.config.BeanConfig;
public class JerseyConfig extends ResourceConfig {
public JerseyConfig() {
register(RequestContextFilter.class);
packages("com"); // TODO needs more detailed level
register(LoggingFilter.class);
// Validation
this.property(ServerProperties.BV_SEND_ERROR_IN_RESPONSE, true);
this.property(ServerProperties.RESPONSE_SET_STATUS_OVER_SEND_ERROR, true);
configureSwagger();
}
private void configureSwagger() {
register(io.swagger.jaxrs.listing.ApiListingResource.class);
register(io.swagger.jaxrs.listing.SwaggerSerializers.class);
BeanConfig beanConfig = new BeanConfig();
beanConfig.setVersion("1.0.0");
beanConfig.setSchemes(new String[]{"http"});
beanConfig.setHost("localhost:8080");
beanConfig.setBasePath("/"); // tried other things like "/api", but doesn't change anything
beanConfig.setResourcePackage("com.xxxxxx.admin");
beanConfig.setPrettyPrint(true);
beanConfig.setScan(true);
}
}
//other imports
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
@Service
@Path("/status")
@Api(value = "status", description = "Check status")
public class Status {
@GET
@Produces(MediaType.APPLICATION_JSON)
@ApiOperation("Return status")
public Response status() {
return Response.ok("Up").build();
}
}
我还尝试将 Jersey 运行 作为过滤器(使用 spring.jersey.type=filter
)并按照
@ApplicationPath("/rootPath")
public class JerseyConfig extends ResourceConfig {
我在 /src/main/resources/public 下有一个 hello.txt 文件,在 /src/main/resources/public/swagger.
下有一个 Swagger UI 的静态文件正如我所说,我的应用程序运行良好,GET http://localhost:8080/swagger.json shows me the plain json documentation, but both http://localhost:8080/hello.txt and http://localhost:8080/swagger/index.html return 404.
我正在使用 Jersey 2.8 和 Spring Boot 1.3.0
I also tried changing Jersey's servlet pattern
@ApplicationPath("/rootPath") public class JerseyConfig extends ResourceConfig {
您配置应用程序的方式与 @ApplicationPath
无关。它适用于 @ApplicationPath
值时设置了 servlet 映射。
您目前没有使用 Spring Boot 提供的 ServletRegistrationBean
来完成此操作。如果您的目标是使用您自己的 ServletRegistrationBean
,以便您可以注册您的 ResourceConfig
,您也可以通过
- 用
@Component
注释你的ResourceConfig
使其成为 Spring bean,或者 在您的配置中将其设为 Spring bean class
@Bean public ResourceConfig config() { return new JerseyConfig(); }
Spring Boot 然后会将您的 ResourceConfig
注入 JerseyAutoConfiguration
,它将在 ResourceConfig
上获得 @ApplicationPath
值(如果存在) , 并用它来注册自己的 ServletRegistrationBean
.
当您让 Spring Boot 处理配置时,您可以看到 JerseyAutoConfiguration
了解您免费获得的一切。
如果你想保持当前的 SpringRegistrationBean
,只需更改你正在使用的路径。您正在使用 /*
,这是链接答案中提到的问题。因此,如果您需要,只需更改为 /rooPath/*
。
它看起来与使用 Spring MVC 时的常见问题相同。每个 servlet 规范都需要一个 servlet 容器来实现具有最低优先级的默认服务器,该服务器能够为位于 WEB-INF 文件夹之外的静态内容提供服务。
不幸的是,您正在将 Jersey servlet 映射到 "/*"
,这意味着每个 URL 都将提交给 Jersey,而 Jersey 不知道如何处理静态 URLs.
那么可以(轻松)完成哪些工作?
将 Jersey servlet 映射到一个子路径(比如
/api
)并将所有控制器移动到那里:ServletRegistrationBean registration = new ServletRegistrationBean(new ServletContainer(), "/api/*"); ... beanConfig.setBasePath("/api/");
并询问
GET http://localhost:8080/api/swagger.json
仅将 servlet 映射到
*.json
URLs:ServletRegistrationBean registration = new ServletRegistrationBean(new ServletContainer(), "*.json");