使用 Angular 7 前端启动 Spring-Boot 应用程序时无法加载资源错误(缺少资源)

Posted

技术标签:

【中文标题】使用 Angular 7 前端启动 Spring-Boot 应用程序时无法加载资源错误(缺少资源)【英文标题】:Failed to load resource error when starting Spring-Boot Application with Angular 7 Frontend (missing resources) 【发布时间】:2019-05-10 17:27:24 【问题描述】:

我想用 Angular 前端构建一个 Spring-Boot-Application。所以我使用 Spring-Boot-Initializer 构建了一个项目,并为/greet/world 添加了一个RestController。然后我通过执行ng new ui(包括routingcss)在我的src/main文件夹中创建了一个新的Angular-Project。

我将angular.json 中的output-Path 更新为以下内容:

"outputPath": "../resources/static"

然后我在app.component.ts 中添加了Http-Get-Request 并运行以下命令来构建jar

ng build --prod 来自我的 src/main/ui cd %back_to_project_root% mvn clean package cd target java -jar Jar-file

打开 http://localhost:8080 时,我看到了通常的 Angular-Startup-Page 和以下控制台日志:

将前端包含到后端时,我做错了什么?从我的src/main/ui 运行ng serve 效果很好。

我的app.component.ts

import  Component, OnInit  from '@angular/core';
import  HttpClient  from '@angular/common/http';

@Component(
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
)
export class AppComponent implements OnInit 
  title = 'ui';

  constructor(private http: HttpClient)   

  ngOnInit() 
    this.http.get('http://localhost:8080/greet/world').subscribe( (data) => 
    console.log('DATA', data);
      this.title = 'try';
    );
  


我的 HelloWorldController.java 包 com.demo.example.controller;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/hello")
public class HelloWorldController 

    @RequestMapping(value="/world")
    public String greetWorld() 
        return "Hello world";
    


我的 pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.1.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.hud</groupId>
    <artifactId>HelloWorld</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>jar</packaging>
    <name>HelloWorld</name>
    <description></description>

    <properties>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-rest</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-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.restdocs</groupId>
            <artifactId>spring-restdocs-mockmvc</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
            <plugin>
                <groupId>org.codehaus.mojo</groupId>
                <artifactId>exec-maven-plugin</artifactId>
                <executions>
                    <execution>
                        <phase>test</phase>
                        <goals>
                            <goal>exec</goal>
                        </goals>
                    </execution>
                </executions>
                <configuration>
                    <executable>ng</executable>
                    <workingDirectory>src/main/ui</workingDirectory>
                    <argument>
                        <argument>build</argument>
                    </argument>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

编辑 1

我将输出路径更改为../../../target/static,然后运行mvn clean packageng build --prod

然而,这并没有真正节省时间,因为在运行 mvn clean package 时,jar-文件中没有提供这些,但它暂时解决了这个问题。

编辑 2

我按照建议修改了我的代码并得到了以下内容:

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.1.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.test</groupId>
    <artifactId>HelloWorld</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>jar</packaging>
    <name>HelloWorld</name>
    <description></description>

    <properties>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-rest</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-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.restdocs</groupId>
            <artifactId>spring-restdocs-mockmvc</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
            <plugin>
                <groupId>com.github.eirslett</groupId>
                <artifactId>frontend-maven-plugin</artifactId>
                <version>1.6</version>
                <executions>
                    <execution>
                        <id>npm install</id>
                        <goals>
                            <goal>npm</goal>
                        </goals>
                        <configuration>
                            <arguments>install</arguments>
                        </configuration>
                    </execution>
                    <execution>
                        <id>npm build</id>
                        <goals>
                            <goal>npm</goal>
                        </goals>
                        <configuration>
                            <arguments>run build</arguments>
                        </configuration>
                    </execution>

                </executions>
                <configuration>
                        <nodeVersion>v10.14.1</nodeVersion>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-resources-plugin</artifactId>
                <executions>
                    <execution>
                        <id>default-copy-resources</id>
                        <phase>process-resources</phase>
                        <goals>
                            <goal>copy-resources</goal>
                        </goals>
                        <configuration>
                            <overwrite>true</overwrite>
                            <!-- It must match the resulting war-file name -->
                            <outputDirectory>$project.build.directory/$project.artifactId-$project.version/</outputDirectory>
                            <resources>
                                <resource>
                                    <directory>$project.basedir/dist</directory>
                                </resource>
                            </resources>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
</project>

从项目根目录执行mvn clean install 时出现以下错误:

[ERROR] Failed to execute goal com.github.eirslett:frontend-maven-plugin:1.6:npm (npm install) on project HelloWorld: Failed to run task: 'npm install' failed. 
java.io.IOException: Cannot run program "c:\Dev\wsp_test\HelloWorld\node\node.exe" (in directory "c:\Dev\wsp_test\HelloWorld"): CreateProcess error=2, System cannot find the file (<- this is translated, so might be different wording)-> [Help 1]

【问题讨论】:

您的控制器映射适用于/hello/world,而不是/greet/world @RoddyoftheFrozenPeas 你是对的,多么愚蠢的错误......谢谢! 【参考方案1】:

打开您的angular.json 文件,将"outputPath" 设置为../../../dist

在您的package.json 中,您应该有一个build 脚本,例如:

"scripts": 
   [..]
   "build": "ng build --prod",

编辑您的pom.xml 以添加frontend-maven-plugin 插件以使用maven 构建角度,并maven-resources-plugin 以复制它们(How to setup angular 4 inside a maven based java war project) :

<build>
    <plugins>
        <plugin>
            <groupId>com.github.eirslett</groupId>
            <artifactId>frontend-maven-plugin</artifactId>
            <version>1.6</version>
            <executions>
                <execution>
                    <id>install node and npm</id>
                    <goals>
                        <goal>install-node-and-npm</goal>
                    </goals>
                    <phase>generate-resources</phase>
                </execution>
                <execution>
                    <id>npm install</id>
                    <goals>
                        <goal>npm</goal>
                    </goals>
                    <configuration>
                        <arguments>install</arguments>
                    </configuration>
                </execution>
                <execution>
                    <id>npm build</id>
                    <goals>
                        <goal>npm</goal>
                    </goals>
                    <configuration>
                        <arguments>run build</arguments>
                    </configuration>
                </execution>
                <configuration>
                    <nodeVersion>v8.9.0</nodeVersion>
                </configuration>
            </executions>
        </plugin>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-resources-plugin</artifactId>
            <version>2.4.2</version>
            <executions>
                <execution>
                    <id>default-copy-resources</id>
                    <phase>process-resources</phase>
                    <goals>
                        <goal>copy-resources</goal>
                    </goals>
                    <configuration>
                        <overwrite>true</overwrite>
                        <!-- It must match the resulting war-file name -->
                        <outputDirectory>$project.build.directory/$project.artifactId-$project.version/</outputDirectory>
                        <resources>
                            <resource>
                                <directory>$project.basedir/dist</directory>
                            </resource>
                        </resources>
                    </configuration>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>

【讨论】:

静态资产所在的通常路径在src/main/resources/static(据我所知)。我当前的输出路径配置为:"outputPath": "../resources/static",,因为我的角度根在src/main/ui 中(所以在执行mvn package 时,我正在从src/main/ui 执行ng build,并将输出扔到src/main/resources/static。显示应用程序,所以这似乎可以正常工作。我最近在重新加载页面时遇到了一些路由问题。这就是我上面提到的错误。 可以分享配置角度静态资源路径的java代码吗? 我不完全确定我是否理解正确,所以让我试着澄清一下我应该提供什么:静态资源有一个静态目录。由于我的应用程序是带有 Angular 前端的 Spring-Boot 应用程序,因此该目录是 src/main/resources/static(我猜默认情况下?)。所以我需要确保我的ng build-output 放在那个目录中,Spring-Boot 和/或 Maven 正在为我做剩下的事情,对吧(或者我是否误解了这一点?)。所以你想让我提供什么让我的 Angular 进入static-文件夹?或者什么执行ng build 我更新了我的帖子并提供了我正在做/尝试做的可复制描述 是的,它起作用了,我不知道它为什么起作用或我做了什么不同,但我尝试了一个新项目,而且我的 pom.xml 不再起作用,所以我可能做错了什么.在编辑中,我从头开始尝试并遇到了同样的错误(也是通过手动构建而不是使用pom.xml)。

以上是关于使用 Angular 7 前端启动 Spring-Boot 应用程序时无法加载资源错误(缺少资源)的主要内容,如果未能解决你的问题,请参考以下文章

Spring / Angular 7 POST方法请求参数为空

Angular 6(前端)+ Spring:配置路由

如何在使用 Angular 7 和 Spring Boot 构建的 Web 应用程序中使浏览器缓存无效

如何将凭据从 Angular 前端传递到 Spring 后端(Spring Security 的基本身份验证)

Keycloak Spring boot 后端和 Angular 前端,CORS 错误

如何使用 Angular + Spring + JSON 自定义登录/身份验证