Spring 启动应用程序不提供静态内容
Spring Boot app not serving static content
我正在使用 Spring Boot,并试图在部署时使我的静态资源(CSS、JS、字体)可用。源代码可供您查看或从 https://github.com/joecracko/StaticResourceError.
克隆
现在我的 CSS、JS 和字体文件对我部署的网站不可见。
这是我的项目目录结构:
这是已编译 JAR 的根目录: 我向您保证这些文件存在于它们各自的文件夹中。
这是我看到的网络错误:
这里是 chrome 工具提供的资源。 请注意,bar.css 在这里显示为空。你可以看看我的源代码,看看它不是空的。
这是我的homepage.html
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" />
<title>Insert title here</title>
<!-- Main Styles -->
<link rel="stylesheet" href="/css/bar.css" />
<script src="/js/foo.js"></script>
</head>
<body>
<div>Welcome to Foo!</div>
</body>
</html>
这是我的 Web App Initializer (FooWebAppInitializer.java)
public class FooWebAppInitializer implements WebApplicationInitializer {
@Override
public void onStartup(ServletContext container) {
AnnotationConfigWebApplicationContext rootContext = new AnnotationConfigWebApplicationContext();
rootContext.register(ServletConfig.class);
// Manage the lifecycle of the root application context
container.addListener(new ContextLoaderListener(rootContext));
//Spring Security
container.addFilter("springSecurityFilterChain", new DelegatingFilterProxy("springSecurityFilterChain"))
.addMappingForUrlPatterns(null, false, "/*");
// Register and map the dispatcher servlet
ServletRegistration.Dynamic dispatcher = container.addServlet("dispatcherServlet", new DispatcherServlet(rootContext));
dispatcher.setLoadOnStartup(1);
dispatcher.addMapping("/*");
dispatcher.addMapping("*.css");
dispatcher.addMapping("*.eot");
dispatcher.addMapping("*.svg");
dispatcher.addMapping("*.ttf");
dispatcher.addMapping("*.woff");
dispatcher.addMapping("*.map");
dispatcher.addMapping("*.js");
dispatcher.addMapping("*.ico");
}
}
这是我的 Servlet 配置 (ServletConfig.java)
@Configuration
@EnableWebMvc
@ComponentScan({"com.foo"})
public class ServletConfig extends WebMvcAutoConfiguration{
@Bean
MultipartResolver multipartResolver() {
return new StandardServletMultipartResolver();
}
@Bean
public ResourceBundleMessageSource messageSource() {
ResourceBundleMessageSource source = new ResourceBundleMessageSource();
source.setBasename("messages");
return source;
}
}
为了好玩,我的 Spring 安全配置 (WebSecurityConfig.java)
@Configuration
@EnableWebMvcSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.anyRequest().permitAll();
}
@Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/resources/**"); // #3
}
}
将静态资源放在目录下:
/src/main/resources/static
您也可以使用 public
或 resources
代替 static
作为文件夹名称。
说明:您的构建工具(Maven 或Gradle)将从应用程序classpath[中的/src/main/resources/
复制所有内容 并且,如 Spring Boot's docs 中所写,类路径中名为 /static
(或 /public
或 /resources
)的目录中的所有内容将作为静态内容提供.
这个目录也可以,但不鼓励:
/src/main/webapp/
Do not use the src/main/webapp directory if your application will be
packaged as a jar. Although this directory is a common standard, it
will only work with war packaging and it will be silently ignored by
most build tools if you generate a jar.
有两件事需要考虑 (Spring Boot v1.5.2.RELEASE)-
1)检查所有Controller classes是否有@EnableWebMvc注解,有则去掉
2) 检查控制器classes 使用了注解——@RestController 或@Controller。不要将 Rest API 和 MVC 行为混合在一个 class 中。对于 MVC 使用 @Controller,对于 REST API 使用 @RestController
做以上两件事解决了我的问题。现在我的 spring 启动正在加载静态资源,没有任何问题。
@Controller => 加载 index.html => 加载静态文件。
@Controller
public class WelcomeController {
// inject via application.properties
@Value("${welcome.message:Hello}")
private String message = "Hello World";
@RequestMapping("/")
public String home(Map<String, Object> model) {
model.put("message", this.message);
return "index";
}
}
index.html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>Hello</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<link rel="stylesheet/less" th:href="@{/webapp/assets/theme.siberia.less}"/>
<!-- The app's logic -->
<script type="text/javascript" data-main="/webapp/app" th:src="@{/webapp/libs/require.js}"></script>
<script type="text/javascript">
require.config({
paths: { text:"/webapp/libs/text" }
});
</script>
<!-- Development only -->
<script type="text/javascript" th:src="@{/webapp/libs/less.min.js}"></script>
</head>
<body>
</body>
</html>
我正在使用 Spring Boot,并试图在部署时使我的静态资源(CSS、JS、字体)可用。源代码可供您查看或从 https://github.com/joecracko/StaticResourceError.
克隆现在我的 CSS、JS 和字体文件对我部署的网站不可见。
这是我的项目目录结构:
这是已编译 JAR 的根目录: 我向您保证这些文件存在于它们各自的文件夹中。
这是我看到的网络错误:
这里是 chrome 工具提供的资源。 请注意,bar.css 在这里显示为空。你可以看看我的源代码,看看它不是空的。
这是我的homepage.html
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" />
<title>Insert title here</title>
<!-- Main Styles -->
<link rel="stylesheet" href="/css/bar.css" />
<script src="/js/foo.js"></script>
</head>
<body>
<div>Welcome to Foo!</div>
</body>
</html>
这是我的 Web App Initializer (FooWebAppInitializer.java)
public class FooWebAppInitializer implements WebApplicationInitializer {
@Override
public void onStartup(ServletContext container) {
AnnotationConfigWebApplicationContext rootContext = new AnnotationConfigWebApplicationContext();
rootContext.register(ServletConfig.class);
// Manage the lifecycle of the root application context
container.addListener(new ContextLoaderListener(rootContext));
//Spring Security
container.addFilter("springSecurityFilterChain", new DelegatingFilterProxy("springSecurityFilterChain"))
.addMappingForUrlPatterns(null, false, "/*");
// Register and map the dispatcher servlet
ServletRegistration.Dynamic dispatcher = container.addServlet("dispatcherServlet", new DispatcherServlet(rootContext));
dispatcher.setLoadOnStartup(1);
dispatcher.addMapping("/*");
dispatcher.addMapping("*.css");
dispatcher.addMapping("*.eot");
dispatcher.addMapping("*.svg");
dispatcher.addMapping("*.ttf");
dispatcher.addMapping("*.woff");
dispatcher.addMapping("*.map");
dispatcher.addMapping("*.js");
dispatcher.addMapping("*.ico");
}
}
这是我的 Servlet 配置 (ServletConfig.java)
@Configuration
@EnableWebMvc
@ComponentScan({"com.foo"})
public class ServletConfig extends WebMvcAutoConfiguration{
@Bean
MultipartResolver multipartResolver() {
return new StandardServletMultipartResolver();
}
@Bean
public ResourceBundleMessageSource messageSource() {
ResourceBundleMessageSource source = new ResourceBundleMessageSource();
source.setBasename("messages");
return source;
}
}
为了好玩,我的 Spring 安全配置 (WebSecurityConfig.java)
@Configuration
@EnableWebMvcSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.anyRequest().permitAll();
}
@Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/resources/**"); // #3
}
}
将静态资源放在目录下:
/src/main/resources/static
您也可以使用 public
或 resources
代替 static
作为文件夹名称。
说明:您的构建工具(Maven 或Gradle)将从应用程序classpath[中的/src/main/resources/
复制所有内容 并且,如 Spring Boot's docs 中所写,类路径中名为 /static
(或 /public
或 /resources
)的目录中的所有内容将作为静态内容提供.
这个目录也可以,但不鼓励:
/src/main/webapp/
Do not use the src/main/webapp directory if your application will be packaged as a jar. Although this directory is a common standard, it will only work with war packaging and it will be silently ignored by most build tools if you generate a jar.
有两件事需要考虑 (Spring Boot v1.5.2.RELEASE)- 1)检查所有Controller classes是否有@EnableWebMvc注解,有则去掉 2) 检查控制器classes 使用了注解——@RestController 或@Controller。不要将 Rest API 和 MVC 行为混合在一个 class 中。对于 MVC 使用 @Controller,对于 REST API 使用 @RestController
做以上两件事解决了我的问题。现在我的 spring 启动正在加载静态资源,没有任何问题。 @Controller => 加载 index.html => 加载静态文件。
@Controller
public class WelcomeController {
// inject via application.properties
@Value("${welcome.message:Hello}")
private String message = "Hello World";
@RequestMapping("/")
public String home(Map<String, Object> model) {
model.put("message", this.message);
return "index";
}
}
index.html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>Hello</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<link rel="stylesheet/less" th:href="@{/webapp/assets/theme.siberia.less}"/>
<!-- The app's logic -->
<script type="text/javascript" data-main="/webapp/app" th:src="@{/webapp/libs/require.js}"></script>
<script type="text/javascript">
require.config({
paths: { text:"/webapp/libs/text" }
});
</script>
<!-- Development only -->
<script type="text/javascript" th:src="@{/webapp/libs/less.min.js}"></script>
</head>
<body>
</body>
</html>