3

在理想的世界中,您将 GWT 应用程序编译为 javascript,将其作为静态资源提供服务,并且在幕后您的后端代码在 JVM 上运行,并且一切顺利。但是那个理想的世界被称为运行时的生产。

但是,在开发期间,当您想使用 gwt 代码服务器时...

在运行时(源 + 类)需要 GWT 编译时依赖项,用于 GWT 模块的调试和重新编译目的。

同时,您可能希望有类似 spring-boot 1.3.5.RELEASE 的后端支持。

在这种情况下,遭受多次频繁发布的spring boot此时想要添加为托管依赖项,例如:

<hibernate-validator.version>5.2.4.Final</hibernate-validator.version>

当然,这是一件非常好的事情。事实上,它是春天的众多优点之一。

另一方面,Gwt 参见下面的链接, http://www.gwtproject.org/doc/latest/DevGuideValidation.html

仍然要求您使用:

        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-validator</artifactId>
            <version>4.1.0.Final</version>
            <scope>runtime</scope>              
        </dependency>

现在,如果您要说:我不关心生产性开发,只需编译一些在生产中正常工作的东西。

那么实际上,您可以通过以这种方式构建项目来轻松解决上述问题:

ROOT
--- Backend-api
--- Backend-Impl
--- Gwt-Front-end
---- War or stand alone Spring jar module to glue it all together

对于某些 RPC 服务和 DTO,您在哪里制作 Gwt-Front 取决于后端 API。pom.xml 依赖项大部分只能在前端模块中管理,与后端的依赖项无关。最终,您制作了一个 war 或 spring boot 可运行 jar,它将您的 gwt 代码作为静态资源携带,并携带您的后端代码及其所有依赖项,即 Hibernate 验证器最新版本。

但是,当您尝试获得可用于开发目的的 pom 时,据我所知,您不得不在全局范围内管理 ROOT 中后端和前端层之间常见的依赖关系pom.xml,并将您的依赖项降级到 gwt 所需的版本。

也就是说,在理想的世界场景中。您的 ROOT pom.xml 只是简单地声明了您的模块以及它们构建的顺序。你让你的后端实现有能力声明它想要从 spring-boot-starter pom.xml 继承依赖项,等等......

与理想情况相反,在开发期间实际上可以帮助您的 pom.xml 配置...好吧,您可能不得不重新访问 Root pom.xml。而且你必须在这个根 pom.xml 上添加托管依赖项,这样对于你的 GWT 前端和 Spring Boot 后端之间所有那些常见的冲突依赖项,你总是必须敲击 GWT 的版本并降级到位。

这将确保当您执行 gwt:run、开发模式重新编译等时...您最终不会让 gwt 编译器尝试 javascript 编译您的 Hibernate 版本 5,而是 GWT 4.1 final 确实支持的版本。当然,您最终可能会对后端代码感到惊讶,其中一个是通过实施这样的黑客...

有没有人知道如何正确组织一个多模块项目,其中允许后端和基于 gwt 的前端具有相互冲突的依赖要求?

最终,如果答案是否定的,我相信我更愿意通过拥有一个与纯 gwt 独立码头集成的纯独立 Spring Boot 后端来浪费网络并增加通信延迟,该码头上的后端无非只是愚蠢地将请求踢到实际的 spring-boot 后端。让 gwt jetty 后端被 UI 调用以执行 1+1 并将计算转发到第二个后端运行的 sprin boot 实际知道如何执行 1+1 ...但如果这是最有成效的工作方式,确保开发是富有成效的,并且生产将毫无意外地运行,那就这样吧。

感谢您的任何反馈,理想情况下,我希望看到一个多 pom 项目,您可以将其作为现有的 maven 项目导入到 eclipse 中,并演示如何实现这一点。

4

4 回答 4

2

是的,我想做的事其实是可以做到的,虽然不是微不足道的……一点也不。

为了设置一个可以高效使用的 maven 多模块 pom,您可以在无需选择 gwt 验证器依赖项或 springboot 验证器依赖项的情况下为后端和前端代码进行代码交换,基本上我组织我的项目如下。

你有:

LEVEL 1: myproject-root
----- LEVEL 2: myproject-backend
---------- LEVEL 3: myproject-backend-api
---------- LEVEL 3: myproject-backend-impl
------ LEVEL 2: myproject-frontend
------ LEVEL 2: myproject-runner
-----------LEVEL 3: myproject-runner-jar
-----------LEVEL 3: myproject-runner-war

在 myproject-root 中,您自然而然地声明了子模块。您对一些无害的插件(例如surefire插件)进行依赖管理。您控制 java 源和目标编译语言。你做的远不止这些。如果您有一些可以交叉配置的插件,您不妨将它们放在插件管理中。

在 myproject-backend 中,您基本上可以通过添加到您的依赖项管理来使其继承 springboot 依赖项的依赖项管理:

<dependencyManagement>
        <dependencies>
            <!-- Inherit dependencies from spring boot dependency management pom -->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-parent</artifactId>
                <version>${version.spring.boot}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

你声明了这两个子模块,然后你就退出了。您没有在此处声明任何横切依赖项。您只使用依赖管理。前端组件将访问 api 子模块,并且您不想在后端 pom 中创建依赖磁铁,所以在这里您尽可能保守。

在 myproject-backend-api 中,首先让这个子模块成为一个 jar 子模块。下线,您将希望通过按入口点性质细分 api-s 来进一步分支 api 组件。首先,-api 组件将具有服务器和前端之间通信所需的 api,有点像文档中通常看到的“共享”。在这里,您尽可能小心,尽可能少地考虑依赖项元素中的元素。前端将使用这些 api,并且您不希望您的 api 包依赖于任何 spring boot api。

在后端实现中,您编写实际的业务逻辑,您可以自由地依赖完整的 Spring Boot 堆栈。规则是,确保没有人指向这个依赖磁铁,尤其是永远不要让 gwt 组件闻到 springboot 库的存在。永远不要参考它。

在 myproject-frontend 中,您不会将其分支到不同的子模块中,就像您可能对 api 组件所做的那样。在这里,您为 gwt 代码制作了一个单一组件,以便您可以更轻松地让 gwt maven 插件为您进行热代码重新编译。在这个组件中,您依赖于 myproject-api,以及任何相关的 gwt 库,例如 gwt-user、具有 gwt 所需旧版本的休眠验证器等...... myproject-frontend 的规则是声明组件中的每个依赖项都是可选的。您不想对组件采取任何传递依赖。在生产中,您只需要 myproject-frontend.jar/META-INF/resources/MyProjectModule.html... 以及 springboot 必须检测和服务的所有此类静态资源。但是,当您处于开发模式时,

<noServer>true</noServer>

关键是,如果运行这个码头服务器,它的类路径中唯一的东西就是前端代码和 api,绝对不是 impl 代码。其次,你不想使用 gwt jetty,你要么想使用 springboot tomcat 要么使用 springboot jetty。将 springboot 的嵌入式容器与适当的 websocket 库等一起使用会更好。

(b) 使用 springboot,您希望从 META-INF/resources/ 或公共文件夹中提供静态资源。我更喜欢这些资源,因为它通常也是您放置 JSF 组件的地方。无论如何,由于静态资源的来源很特殊,您需要调整 gwt 插件以将您的 java 源代码编译到 write 文件夹中。

<webappDirectory>${project.build.directory}/classes/META-INF/resources</webappDirectory>

所以像上面一样。

最后,这是我的主要错误,您没有从编写前端代码的地方运行代码。那是错误的,因为这会迫使你的前端代码需要 springboot 依赖,这会因为库冲突而给你带来极大的痛苦。

因此,为了避免这个问题,您创建了 myproject-runner 组件,如果您想要非常详细,您可以将其设置为 pom 父组件,以便您可以将您的包装分叉到 jar 或 war 中。我个人更喜欢可执行 jar,而不是 war 选项。我永远不会想在像重量级 weblogic 这样的东西中部署一个 sprinboot 应用程序......但不管你的船如何。

在任何情况下,spring boot runner 都是你的终极依赖磁铁。该组件将取决于您拥有的每个模块及其传递依赖项。但是因为你将你的运行器组件与前端代码分开,并且你使前端代码中的所有依赖项都是可选的......嗯,你基本上只捆绑了 springboot 和你的 gwt 静态资源。

当你在开发时,你所做的就是......一旦你知道它......很简单。(A) 你通过触发主文件来启动你的 spring boot jar 应用程序。如果您真的想部署一个war文件,那是您的选择,您也可以构建一个war文件并将其部署到tomcat或其他任何东西......

(b) 你去你的前端组件,右键单击它,选择作为 Maven Build 运行,然后选择 gwt:run。gwt 运行将启动 gwt 代码服务器,这将对您的后端代码完全视而不见,它在眼前看到的唯一东西是您在前端组件中拥有的代码以及您所有的 gwt 依赖项已添加为可选。

如果您正在使用 springboot dev,您最终可以在后端热交换代码。一旦你启动了 gwt 插件,你终于可以在那个单一的前端组件中热交换代码。

结论,这是可能的,但它是一团糟。很高兴这个问题已经解决了。

于 2016-05-21T19:51:32.827 回答
2

找出在编译 GWT 代码时要排除的传递依赖项。

    <dependency>
        <groupId>spring-dependency-with-hibernate</groupId>
        <artifactId>some-spring-boot-starter</artifactId>
        <exclusions>
            <exclusion>
               <groupId>org.hibernate</groupId>
               <artifactId>hibernate-validator</artifactId>
            </exclusion>
        </exclusions>
    </dependency>

这样,只有 GWT 提供的hibernate版本在运行时可用。

于 2016-05-18T12:25:03.027 回答
0

我相信我在使用 Eclipse IDE、GWT Google Plugin、SpringBoot 和 Maven 时遇到了类似的问题并发现了以下问题。食谱并不简单,但它对我的团队有用。

GWT-dev 和 Jetty 服务器不适用于 SpringBoot。由于 Jetty 和 gwt-dev 硬编码依赖项,您必须修复类路径,只有 gwt-dev 和 Jetty 构建的依赖项才会起作用。

我不得不将 GWT UI 项目拆分为两个 Maven 工件。一个工件是一个只能在 Eclipse 中运行的 WebApp,所有 SpringBoot 库都被排除在类路径之外。另一个工件是可部署的 SpringBoot JAR,它具有“war”maven 打包类型和 Eclipse 专用工件的 WAR 覆盖,仅包括 GWT 特定内容。

我希望这有帮助

于 2020-01-04T12:37:51.403 回答
0

只需为运行 GWT 代码服务器创建专用 maven 配置文件并仅在此处添加“gwt-dev”依赖项

<profiles>
    <profile>
        <id>gwt-dev</id>
        <dependencies>
            <dependency>
                <groupId>com.google.gwt</groupId>
                <artifactId>gwt-dev</artifactId>
            </dependency>
        </dependencies>
        <build>
            <plugins>
                <plugin>
                    <groupId>org.codehaus.mojo</groupId>
                    <artifactId>gwt-maven-plugin</artifactId>
                    <version>${gwt.version}</version>
                    <executions>
                        <execution>
                            <id>run-codeserver</id>
                            <goals>
                                <goal>run-codeserver</goal>
                            </goals>
                        </execution>
                    </executions>
                    <configuration>
                        <sourceLevel>${java.version}</sourceLevel>
                        <module>kn.iopm.documentserver.IDocServer</module>
                        <extraJvmArgs>-Xmx1G -Xms512M -Xss1G -Dlog.root=${project.build.directory}/log
                        </extraJvmArgs>
                        <runTarget>index.html</runTarget>
                        <persistentunitcachedir>${project.build.directory}</persistentunitcachedir>
                        <webappDirectory>${project.build.outputDirectory}/public</webappDirectory>
                        <deploy>${project.build.directory}/gwt-deploy</deploy>
                        <codeServerWorkDir>${project.build.directory}/gwt</codeServerWorkDir>
                        <launcherDir>${project.build.outputDirectory}/static</launcherDir>
                    </configuration>
                </plugin>
            </plugins>
        </build>
    </profile>
</profiles>
于 2021-10-07T09:14:06.613 回答