问题
I have 2 projects. An Angular2 app which I build with Angular-cli and a Spring Boot app which will only serve the Angular2 app. I build the Angular2 app with ng build
which generates a dist
folder. I then put the content of the dist
folder in the Spring Boot app inside src/main/resources/static
.
My spring boot app has two files.
The Spring boot application class :
@SpringBootApplication
public class SpringBoot extends SpringBootServletInitializer {
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(SpringBoot.class);
}
public static void main(String[] args) throws Exception {
SpringApplication.run(SpringBoot.class, args);
}
}
And the application.properties file:
server.contextPath=/
server.port=80
It works well but if I go to an url and hit the refresh button, I get the Whitelabel Error Page
. I know it's because the URLs are not serving the index.html
when they don't match a resource file.
How can I configure my Spring Boot app to serve index.html
if the url doesn't match a resource file?
回答1:
You are correct that index.html
needs to be served back for endpoints unknown to Spring. Then arrange for the Angular app to manage unknown routes.
I handle this situation with a WebMvcConfigurerAdapter
. Also put static content file types in here.
Add a config
directory and in it add a Java file WebMvcConfig
(for example) with this content:
package com.yourdomain.yourapp.config;
import org.springframework.boot.autoconfigure.web.ResourceProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.Resource;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import org.springframework.web.servlet.resource.PathResourceResolver;
import java.io.IOException;
import javax.inject.Inject;
@Configuration
@EnableConfigurationProperties({ ResourceProperties.class })
public class WebMvcConfig extends WebMvcConfigurerAdapter {
@Inject
private ResourceProperties resourceProperties = new ResourceProperties();
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
Integer cachePeriod = resourceProperties.getCachePeriod();
final String[] staticLocations = resourceProperties.getStaticLocations();
final String[] indexLocations = new String[staticLocations.length];
for (int i = 0; i < staticLocations.length; i++) {
indexLocations[i] = staticLocations[i] + "index.html";
}
registry.addResourceHandler(
"/**/*.css",
"/**/*.html",
"/**/*.js",
"/**/*.json",
"/**/*.bmp",
"/**/*.jpeg",
"/**/*.jpg",
"/**/*.gif",
"/**/*.ico",
"/**/*.png",
"/**/*.ttf",
"/**/*.wav",
"/**/*.mp3",
"/**/*.eot",
"/**/*.svg",
"/**/*.woff",
"/**/*.woff2",
"/**/*.map"
)
.addResourceLocations(staticLocations)
.setCachePeriod(cachePeriod);
registry.addResourceHandler("/**")
.addResourceLocations(indexLocations)
.setCachePeriod(cachePeriod)
.resourceChain(true)
.addResolver(new PathResourceResolver() {
@Override
protected Resource getResource(String resourcePath, Resource location) throws IOException {
return location.exists() && location.isReadable() ? location : null;
}
});
}
}
I think you will also have to specify the config package for component scan. Maybe try without first and see if it works.
@SpringBootApplication
@ComponentScan( basePackages = { "com.yourdomain.yourapp.config" })
public class SpringBoot extends SpringBootServletInitializer {
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(SpringBoot.class);
}
public static void main(String[] args) throws Exception {
SpringApplication.run(SpringBoot.class, args);
}
}
In case your missing dependencies. This is what I have in my build.gradle
:
dependencies {
compile group: 'org.springframework.boot', name: 'spring-boot-starter-web'
compile group: 'javax.inject', name: 'javax.inject', version: '1'
optional group: 'org.springframework.boot', name: 'spring-boot-configuration-processor'
providedRuntime group: 'org.springframework.boot', name: 'spring-boot-starter-tomcat'
testCompile group: 'org.springframework.boot', name: 'spring-boot-starter-test'
}
Hope this helps :-)
回答2:
Here you can find my Spring Boot 2 and Angular 6 starter project.
Spring Boot application is created using SPRING INITIALIZR, Angular application is created using Angular CLI.
来源:https://stackoverflow.com/questions/42599176/angular-cli-with-spring-boot