Angular 与 Spring boot 静态不起作用
有角度的前端
我有一个 Spring Boot 应用程序,其中包含一个像这样的
: src/main/resources/static/zanori2
在 zanori2 中,我有 ng build 的结果,例如:
index.html、index.html。 js,favico.ico 等
我尝试了这个resourceHandle:
@Configuration
@EnableWebMvc
public class WebMvcConfig implements WebMvcConfigurer {
/*@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {*/
//registry.addResourceHandler("/**/*")
/*.addResourceLocations("classpath:/static/zanori2/")
.resourceChain(true)
.addResolver(new PathResourceResolver() {
@Override
protected Resource getResource(String resourcePath,
Resource location) throws IOException {
Resource requestedResource = location.createRelative(resourcePath);
return requestedResource.exists() && requestedResource.isReadable() ? requestedResource
: new ClassPathResource("/static/zanori2/index.html");
}
});
}
}
但是当我转到: localhost:8080/zanori2/index.html
它返回我localhost:8080
并且 js 文件有效。
然而,这很奇怪,因为我不允许共享网址,因为如果我直接访问 localhost:8080 我会得到一个未找到的页面。
使用其他配置:
@Configuration
@EnableWebMvc
public class WebMvcConfig implements WebMvcConfigurer {
@Autowired
private Environment env;
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
/* Caching strategy */
boolean prodMode = Arrays.asList(env.getActiveProfiles()).contains("pro");
Integer cachePeriod = prodMode ? null : 0;
boolean useResourceCache = prodMode;
VersionResourceResolver versionResourceResolver = new VersionResourceResolver();
versionResourceResolver.addContentVersionStrategy("/**/*.js", "/**/*.css");
AppCacheManifestTransformer transformer = new AppCacheManifestTransformer();
/* robots.txt */
registry.addResourceHandler("/robots.txt")
.addResourceLocations("classpath:/static/robots.txt");
/* All other resources */
registry.addResourceHandler("/**")
.addResourceLocations("classpath:/static/zanori2")
.setCachePeriod(cachePeriod)
.resourceChain(useResourceCache)
.addResolver(versionResourceResolver)
.addTransformer(transformer);
}
@Override
public void addViewControllers(ViewControllerRegistry registry) {
/* Make sure Thymeleaf views are not accessible directly as static resources */
registry.addRedirectViewController("/app/*.html", "/");
/* Default mapping */
registry.addRedirectViewController("/", "/app/index.html");
/* Application entry */
registry.addViewController("/app/index.html").setViewName("index");
}
}
我转到 localhost:8080/zanori2/index.html 并保留相同的网址,但是找不到我的 js 文件,因此也不起作用。
我没有找到任何可以正常工作的例子。
I have an spring boot app, which contains an angular front
like this:
src/main/resources/static/zanori2
Where in zanori2 I have the result of ng build
some like:
index.html, index.js, favico.ico and so on
I tried this resourceHandle:
@Configuration
@EnableWebMvc
public class WebMvcConfig implements WebMvcConfigurer {
/*@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {*/
//registry.addResourceHandler("/**/*")
/*.addResourceLocations("classpath:/static/zanori2/")
.resourceChain(true)
.addResolver(new PathResourceResolver() {
@Override
protected Resource getResource(String resourcePath,
Resource location) throws IOException {
Resource requestedResource = location.createRelative(resourcePath);
return requestedResource.exists() && requestedResource.isReadable() ? requestedResource
: new ClassPathResource("/static/zanori2/index.html");
}
});
}
}
However when I go to: localhost:8080/zanori2/index.html
it return me to localhost:8080
and the js files works.
However it is weird because I am not allowed to share the url because if I go directly to localhost:8080 I get a not found page.
And with this other configuration:
@Configuration
@EnableWebMvc
public class WebMvcConfig implements WebMvcConfigurer {
@Autowired
private Environment env;
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
/* Caching strategy */
boolean prodMode = Arrays.asList(env.getActiveProfiles()).contains("pro");
Integer cachePeriod = prodMode ? null : 0;
boolean useResourceCache = prodMode;
VersionResourceResolver versionResourceResolver = new VersionResourceResolver();
versionResourceResolver.addContentVersionStrategy("/**/*.js", "/**/*.css");
AppCacheManifestTransformer transformer = new AppCacheManifestTransformer();
/* robots.txt */
registry.addResourceHandler("/robots.txt")
.addResourceLocations("classpath:/static/robots.txt");
/* All other resources */
registry.addResourceHandler("/**")
.addResourceLocations("classpath:/static/zanori2")
.setCachePeriod(cachePeriod)
.resourceChain(useResourceCache)
.addResolver(versionResourceResolver)
.addTransformer(transformer);
}
@Override
public void addViewControllers(ViewControllerRegistry registry) {
/* Make sure Thymeleaf views are not accessible directly as static resources */
registry.addRedirectViewController("/app/*.html", "/");
/* Default mapping */
registry.addRedirectViewController("/", "/app/index.html");
/* Application entry */
registry.addViewController("/app/index.html").setViewName("index");
}
}
I go to localhost:8080/zanori2/index.html
and I keep in the same url however my js files are not found so is not working too.
I do not found any example of this working properly.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
静态资源的映射
Spring 将自动在多个位置搜索与 Web 配置中的任何控制器或其他设置不匹配的路径。当前默认情况下会检查这些位置:
您可以通过设置
应用程序属性来覆盖此行为。
从一个干净的项目开始并添加:
到您的application.properties将使Spring搜索静态资源的预期路径。
将单页前端中的路径映射到
/
请记住,在下面的所有内容中,到静态资源的映射已被上面的内容更改,因此在下面,路径
/a/b
将真正获取/static/zanori2/a/b
。另请记住,Spring 控制器始终优先于静态资源,因此如果您定义的 Spring 控制器会干扰静态路径,则会使用它。如果您还支持单页前端使用内部路由,您需要向
WebMvcConfigurer
添加一些配置。技巧是仍然从其真实位置加载所有静态内容,但将单页应用程序内的所有路径转发到/
。假设应用程序内的路径永远不会有以句点 (.) 开头的文件后缀(通常来自后端的所有真实静态文件都有这种后缀),这可以通过向WebMvcConfigurer
添加一些内容来完成。添加取决于哪种 模式SpringMVC中使用了匹配。
路径模式匹配
使用路径模式匹配(这是最新 Spring Boot 中的新默认值):
使用路径模式匹配,没有简单的方法可以对任意数量的路径级别执行此操作因此,您必须为前端内部路径应支持的每一级嵌套添加这些语句之一。这是因为路径模式仅允许在模式末尾匹配多个路径级别 (
**
)。上面最多支持三级所以直接在浏览器地址栏输入时:
这是怎么回事?如前所述,这些是路径模式,您可以阅读这里:
{pathX}
匹配一个路径段,并将路径存储在变量pathX
中(我们不这样做)不在乎)。匹配
Ant 模式与 ant 模式 匹配,这曾经是默认的,适用类似的规则,但有一些差异。路径模式匹配通常更有效,但如前所述,它不允许您在最后的任何其他位置匹配任意数量的路径级别 (
**
)。使用 ant 模式匹配,前面的配置可以简化为
现在,我们在最后一个路径之前匹配任意数量的路径级别,产生以下结果:
因此,根据您应用程序其余部分的需要,我会选择以下之一这些解决方案,最好是带有蚂蚁图案的解决方案。
Mapping of static assets
Spring will automatically search in a number of places for paths which aren't matched by any controllers or other settings in the web config. These locations are currently checked by default:
You can override this behaviour by setting the
application property.
Starting from a clean project and adding:
to your
application.properties
will make Spring search the intended path for static resources.Mapping paths in single-page frontends to
/
Remember in all of the below that the mapping to static assets has already been changed by the above so in the below, the path
/a/b
will REALLY fetch/static/zanori2/a/b
. Also remember that a Spring controller will always have precedence over static assets so if you define a Spring controller which interferes with a static path, it will be used instead.If you also support a single-page frontend with internal routing, you need to add some configuration to the
WebMvcConfigurer
. The trick is to still load all static content from its real location but to forward all the paths inside the single-page app to/
. Assuming that paths inside the app will never have a file suffix preceded by a period (.), which typically all real static files from the backend have, this can be done by some additionss to yourWebMvcConfigurer
.The additions depend on which kind of pattern matching is used in SpringMVC.
Path pattern matching
With path pattern matching (which is the new default in up-to-date Spring Boot):
With path pattern matching, there is no easy way to do this for an arbitrary number of path levels so you have to add one of these statements for every level of nesting your frontend internal paths should support. This is because path patterns only allow matching of multiple path levels (
**
) at the end of a pattern.The above supports up to three levels so when directly entering in the browser address bar:
What's going on here? As said, these are path patterns which you can read about here:
{pathX}
matches a path segment and stores the path in the variablepathX
(which we don't care about).Ant pattern matching
With ant pattern matching, which used to be the default, similar rules apply but with some differences. Path pattern matching is generally more potent but as previously said, it does not allow you to match an arbitrary number of path levels (
**
) at no other place then at the end.With ant pattern matching, the previous config can be simplified into
Now, we match an arbitrary number of path levels before the last path, yielding the following results:
So depending on what you need in the rest of your app, I would choose one of these solutions, preferably the one with ant patterns.