Angular 与 Spring boot 静态不起作用

Luc*_*cke 5 static static-files spring-boot angular

我有一个 Spring Boot 应用程序,其中包含有角度的前端

像这样:

src/main/resources/static/zanori2

ng build在 zanori2 中,我得到了类似的结果:

index.html、index.js、favico.ico 等

我尝试了这个资源句柄:

@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");
            }
        });
    }
}
Run Code Online (Sandbox Code Playgroud)

但是,当我转到:时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");
    }
}
Run Code Online (Sandbox Code Playgroud)

我访问localhost:8080/zanori2/index.html并保留相同的网址,但是找不到我的 js 文件,因此也不起作用。

我没有找到任何可以正常工作的例子。

问题示例: 在此输入图像描述

fas*_*xes 2

静态资产映射

Spring 将自动在多个位置搜索与 Web 配置中的任何控制器或其他设置不匹配的路径。当前默认检查这些位置:

classpath:/META-INF/resources/
classpath:/resources/
classpath:/static/
classpath:/public/
Run Code Online (Sandbox Code Playgroud)

您可以通过设置来覆盖此行为

spring.web.resources.static-locations
Run Code Online (Sandbox Code Playgroud)

应用程序属性。

从一个干净的项目开始并添加:

spring.web.resources.static-locations=classpath:/static/zanori2/
Run Code Online (Sandbox Code Playgroud)

根据您的意愿,application.propertiesSpring 会搜索静态资源的预期路径。

将单页前端中的路径映射到/

请记住,在下面的所有内容中,到静态资源的映射已被上面的内容更改,因此在下面,路径/a/b将真正获取/static/zanori2/a/b。另请记住,Spring 控制器始终优先于静态资源,因此如果您定义的 Spring 控制器会干扰静态路径,则会使用它。

如果您还支持具有内部路由的单页前端,则需要向WebMvcConfigurer. 技巧是仍然从其真实位置加载所有静态内容,但将单页应用程序内的所有路径转发到/. 假设应用程序内的路径永远不会有以句点 (.) 开头的文件后缀(通常来自后端的所有真实静态文件都有这种后缀),这可以通过在WebMvcConfigurer.

添加的内容取决于SpringMVC 中使用的模式匹配类型。

路径模式匹配

使用路径模式匹配(这是最新 Spring Boot 中的新默认值):

classpath:/META-INF/resources/
classpath:/resources/
classpath:/static/
classpath:/public/
Run Code Online (Sandbox Code Playgroud)

对于路径模式匹配,没有简单的方法可以对任意数量的路径级别执行此操作,因此您必须为前端内部路径应支持的每个嵌套级别添加这些语句之一。**这是因为路径模式只允许在模式末尾匹配多个路径级别 ( )。

上面最多支持三级,所以直接在浏览器地址栏输入时:

/
/* / is served */

/a 
/* / is served which can then route internally to /a */

/a/b 
/* / is served which can then route internally to /a/b */

/a/b/c 
/* / is served which can then route internally to /a/b/c */

/a/b/c/d
/* will NOT work, tries to serve actual /a/b/c/d */

/a/b/c.txt 
/* / will NOT work, tries to serve actual /a/b/c.txt since contains a period */
Run Code Online (Sandbox Code Playgroud)

这里发生了什么?如前所述,这些是您可以在此处阅读的路径模式:

  • 每个都{pathX}匹配一个路径段并将路径存储在变量中pathX(我们不关心)。
  • 每个变量在其匹配模式中必须有唯一的名称。
  • 在最后一个路径段中,我们匹配数字、字母和下划线的非空序列。如果您愿意,您可以修改此正则表达式,但您可以执行的操作非常有限。目标是不匹配任何带有句点的路径,因为这些可能是真正的静态文件。
  • 还有其他有用的路径模式,但它们可能不会与我们最终的正则表达式模式组合。

蚂蚁模式匹配

对于过去默认的蚂蚁模式匹配,也适用类似的规则,但有一些差异。路径模式匹配通常更有效,但如前所述,它不允许您在**最后的任何其他位置匹配任意数量的路径级别 ( )。

通过ant模式匹配,前面的配置可以简化为

spring.web.resources.static-locations
Run Code Online (Sandbox Code Playgroud)

现在,我们在最后一条路径之前匹配任意数量的路径级别,产生以下结果:

/
/* / is served */

/a 
/* / is served which can then route internally to /a */

/a/b 
/* / is served which can then route internally to /a/b */

/a/b/c 
/* / is served which can then route internally to /a/b/c */

/a/b/c/d
/* / is served which can then route internally to /a/b/c/d */

/a/b/c.txt 
/* / will NOT work, tries to serve actual /a/b/c.txt since contains a period */
Run Code Online (Sandbox Code Playgroud)

因此,根据您应用程序其余部分的需求,我会选择这些解决方案之一,最好是具有蚂蚁模式的解决方案。