当前位置: 首页 > 工具软件 > GrailsUI > 使用案例 >

grails创建程序_将Grails 2应用程序升级到Grails 3

燕正卿
2023-12-01

grails创建程序

我是Grails的忠实粉丝。 对我而言,在Grails中构建内容的唯一真正的缺点是文档的移动速度往往比代码慢得多。 对于参考文档以外的学习资料尤其如此。 到目前为止,我仅能找到两本专门针对Grails 3的书: 实用Grails 3:Grails的动手指南 (也可能称为Grails 3:应用程序开发的实用指南 )和Grails 3 Step。一步一步 。 而且由于我有很多Grails 2应用程序需要移至Grails 3,所以我真正需要的是Grails 2开发人员指南。

我最接近该指南的是Grails 3.0.x升级指南 ,该指南非常简短,不幸的是,由于Grails 3.3.x继续从Grails 3.0.x继续发展,因此仅涵盖了必要的广泛操作。

因此,花了令人沮丧但最终成功的十天时间,完成了我的第一个Grails 3升级,我认为继续我学到的一些课程可能会很有用。

创建并填充Grails 3应用程序文件夹

让我们从Grails 3.0.x升级指南中概述的基本步骤开始。 这需要仔细彻底地阅读和重新阅读,尤其是“ 文件位置差异”“ Grails 2.x中不存在的新文件”“ Grails 3.x中不存在的文件”部分 。 第一次我过快地浏览了这部分内容(说实话,前三到四次),我错过了两件事:



   
   
grails-app/conf/UrlMappings.groovy has moved to grails-app/controllers
grails-app/conf/BootStrap.groovy has moved to grails-app/init

如果我没有注意到文档中的这些变化,我将让发现这些变化的过程留给读者自由想象……

此页面的下一部分标题为3.1升级插件 。 据我所知,这意味着帮助插件用户将这些插件从Grails 2升级到Grails 3,而不是帮助插件开发人员。 因此,这不适用于我,因为现在有我使用的三个非标准插件( Spring Security CoreSpring Security UIMail )的Grails 3.3.x版本。 不过,这里有一些关于Grails 3如何使用Gradle (基于Groovy的漂亮构建工具)的良好基本信息,因此无论如何我建议阅读它。

最后,患者阅读器到达3.2升级应用程序 。 这就是乐趣的开始。 该文档指出,一个好的开始方法是首先“使用'web profile创建一个新的Grails 3应用程序。”嗯,我听说您在想什么是“ web profile”? 为了回答这个问题,我建议阅读有关Application Profiles的最新Grails快速参考部分

好吧,您从该页面回来了,您感到有些困惑吗? 我敢打赌,您不会一直阅读到6.4理解配置文件……好吧,您也阅读了,现在您甚至不知所措? 为了减少愚蠢性,我想将Grails 3“网络配置文件”视为最接近旧标准Grails 2配置的配置。 尤其是,此配置文件生成了我们所有Grails的前辈都知道的GSP(Groovy服务器页面)视图。

返回升级说明…,提示以下内容:



   
   
grails create-app myapp
cd myapp

我对它说:“等一下。” 假设您正在升级由Ancientware.com的好伙伴使用Groovy 2编写的旧CMS(客户管理系统)(在我写此文件时,它不是注册域名)。 该应用程序可能是使用诸如以下命令创建的:


grails create-app com.ancientware.cms 

这将创建一个名为cms的项目文件夹,并且所有域和控制器类都将出现在


cms/grails-app/domain/com/ancientware/cms 


cms/grails-app/controllers/com/ancientware/cms 

分别(还有服务,标签库等)。 关键是“ cms”包是在“ ancientware.com”域中创建的(这是由于在StackOverflow上的注释以阐明这种做法),然后所有类都在该Groovy / Java包结构中定义。

因此,请使用相同的create命令来生成相同的包结构。 或者,如果您像我一样,但又不喜欢原始的软件包名称,那么这也是开始过渡的好时机。 假设您注意到客户管理系统如今被称为“客户关系管理”系统或CRM。 因此,您将使用以下命令创建新版本:


grails create-app com.ancientware.crm 

接下来,我们接下来将看到升级指南建议按以下方式迁移资源:



   
   
# first the sources
cp -rf .. / old_app / src / groovy / src / main / groovy
cp -rf .. / old_app / src / java / src / main / groovy
cp -rf .. / old_app / grails-app / grails-app
# then the tests
cp -rf .. / old_app / test / unit / src / test / groovy
mkdir -p src / integration-test / groovy
cp -rf .. / old_app / test / integration / src / integration-test / groovy

在本例中,“ old_app”为“ cms”。 敏锐的读者可能还注意到上面的说明创建了一个太深的文件结构。 对于我们的假设示例,我们应该执行以下操作(在发出create-app命令之后):



   
   
cd crm
# first the sources
cp -rf ../old_app/src/groovy/* src/main/groovy
cp -rf ../old_app/src/java/* src/main/groovy
cp -rf ../old_app/grails-app/* grails-app
# then the tests
cp -rf ../old_app/test/unit/* src/test/groovy
mkdir -p src/integration-test/groovy
cp -rf ../old_app/test/integration/* src/integration-test/groovy

请注意上面的文件夹名称后面的星号。

这是将UrlMappings.groovyBootStrap.groovy移至各自新家的好时机。

build.gradle文件和JQuery

升级指南中的第3步很简单,即使有些简洁。 基本上,是时候看看Grails 2 BuildConfig.groovy文件(例如,插件)中的内容,并弄清楚需要放入build.gradle中的内容了 。 根据我的经验,我建议在此处添加尽可能少的内容。 如果您知道需要一个插件(例如Spring Security Core),则必须添加它。 但是像famfamfam这样的事情 ,也许不是。 我最终更改了版本号(尽管也许应该将其保留为“ 0.1”),并在依赖项部分添加了以下几行:



   
   
    compile 'org.grails.plugins:spring-security-core:3.2.1'
    compile 'org.grails.plugins:spring-security-ui:3.1.2'
    compile 'org.grails.plugins:grails-markdown:3.0.0'
    compile fileTree(dir:'lib', include:'*.jar')

要意识到的一件非常重要的事情是,Grails 3不使用JQuery和JQuery-UI的插件。 相反,实际的JQuery内容由Grails 3资产管道管理。 而且,如果您的Grails 2足够老,可以使用资源而不是资产管道,那么还有另一件事需要学习

这篇StackOverflow文章对如何使JQuery与Grails 3.0一起使用提供了很好的建议。 基本上,建议将这两行包含在您的GSP标头中:



   
   
    <asset:javascript src="application.js"/>
    <asset:stylesheet src="application.css"/>

并且application.js和application.css将包含相关JavaScript和CSS。

好吧,差不多。 我需要同时安装JQuery和JQuery-UI,所以我的grails-app / assets / javascripts / application.js文件如下所示:



   
   
// This is a manifest file that'll be compiled into application.js.
//
// Any JavaScript file within this directory can be referenced here
// using a relative path.
//
// You're free to add application-wide JavaScript to this file,
// but it's generally better to create separate JavaScript files as needed.
//
//= require jquery-2.2.0.min.js
//= require jquery-ui.min.js
//= require_tree .
//= require_self

if ( typeof jQuery !== 'undefined' ) {
    ( function ( $ ) {
        $ ( '#spinner' ) . ajaxStart ( function ( ) {
            $ ( this ) . fadeIn ( ) ;
        } ) . ajaxStop ( function ( ) {
            $ ( this ) . fadeOut ( ) ;
        } ) ;
    } ) ( jQuery ) ;
}

上面提供JQuery和JQuery-UI的两行以// =开头需要jquery。

还有其他选项,包括链接到内容交付网络(CDN)或实际上直接在标头中包含库。 同样,可以将各种CSS文件拉入application.css

是Application.groovy还是Application.yml?

步骤4匆匆提到了application.groovyapplication.yml的选择。 最终,在经过反复试验之后,我决定调整一个全新的application.yml,而不是尝试使application.groovy作为Grails 2 Config.groovyDataSource.groovy的混合物。 就我而言,我唯一需要更改的是在datasource:environment:下定义数据库连接的行。 特别是这些线



   
   
    driverClassName: org.h2.Driver
    username: sa
    password: ''



   
   
    development:
        dataSource:
            dbCreate: create-drop
            url: jdbc:h2:mem:devDb;MVCC=TRUE;LOCK_TIMEOUT=10000;DB_CLOSE_ON_EXIT=FALSE
    test:
        dataSource:
            dbCreate: update
            url: jdbc:h2:mem:testDb;MVCC=TRUE;LOCK_TIMEOUT=10000;DB_CLOSE_ON_EXIT=FALSE
    production:
        dataSource:
            dbCreate: none
            url: jdbc:h2:./prodDb;MVCC=TRUE;LOCK_TIMEOUT=10000;DB_CLOSE_ON_EXIT=FALSE

需要进行调整以与我的PostgreSQL实例一起使用(驱动程序,用户名,密码,jdbc…)。

我在application.yml文件中想知道的另一件事是文件顶部的两行:



   
   
    codegen:
        defaultPackage: com.ancientware

这本Grails 3教程讨论了此问题,但是在阅读后以某种方式我感到不满意。 在我看来,默认程序包应为“ com.ancientware.crm”,但到目前为止,我没有由此产生的明显问题。

处理软件包名称更改(如果完成)

如果像我一样,您决定更改软件包名称,则基本上有两个问题需要解决。 第一个是目录结构:按照我们的示例,如果域类最初位于


grails-app/domain/com/ancientware/cms 

那么该路径需要重命名为


grails-app/domain/com/ancientware/crm 

控制器,服务,标签库,测试相同...

除此之外,所有“包含”都需要更改–任何.groovy文件,任何


<%@ page import="com.ancientware.cms.Client" %> 

线在任何视图中,依此类推。

此时,最好查看升级指南的步骤6、7和8。 但是事情并没有就此结束……

GSP的变化

我第一个迁移的应用程序是客户的报告站点,因此从客户的角度来看主要是只读的。 所有数据维护都是由几个值得信赖的文员完成的。 在这种情况下,Grails 2生成的CRUD作为数据维护框架的起点非常有效。

create.gsp文件通常需要特定类型的更改才能起作用。 在Grails 2文件中,该行


<g:form url="[resource:client, action:'save']"  > 

必须替换为以下内容:


<g:form resource="${this.client}" method="POST"> 

行似乎并没有真正导致保存发生,也没有重定向到show.gsp页面。 我推测这是由于缺少“方法”参数。

我也类似地更改了edit.gsp文件。 Grails 2行像


<g:form url="[resource:client, action:'update']" method="PUT" > 

被替换为这样的东西:


<g:form resource="${this.client}" method="PUT"> 

前几行似乎导致405错误。

奇怪的是,即使在相关的Grails 3.3 GSP文档中也没有记录“ resource”参数。 那么我如何得知的呢? 简单—我从头开始构建了一个示例应用程序,创建了一个域类,并为该域类生成了控制器和视图,并且这些视图使用了“ resource”参数。

edit.gsp还需要进行其他更改才能正常工作(否则将其更改为405ed)。 像


<g:actionSubmit class="save" action="update" value="${message(code: 'default.button.update.label', default: 'Update')}" /> 

必须替换为


<input class="save" type="submit" value="${message(code: 'default.button.update.label', default: 'Update')}" /> 

同样,灵感来源是示例应用程序。

show.gsp再次需要类似的处理。 像


<g:form url="[resource:client, action:'delete']" method="DELETE"> 

被替换为


<g:form resource="${this.client}" method="DELETE"> 

和像


<g:actionSubmit class="delete" action="delete" value="${message(code: 'default.button.delete.label', default: 'Delete')}" onclick="return confirm('${message(code: 'default.button.delete.confirm.message', default: 'Are you sure?')}');" /> 

被替换为


<input class="delete" type="submit" value="${message(code: 'default.button.delete.label', default: 'Delete')}" onclick="return confirm('${message(code: 'default.button.delete.confirm.message', default: 'Are you sure?')}');" /> 

除此之外,无论出于何种原因,我与JQuery-UI相关的样式也发生了变化,并且我不得不使用该库在页面的开头插入一个小的<style>块。

ew! 就是这样, index.gsp_form.gsp文件仍然可以正常使用。 为了完整起见,我应该提到Grails 3 CRUD使用新的标记库而不是GSP表单来实现实例的呈现,但是旧的表单技术似乎可以正常工作。

控制器,域,服务和标签库的更改

幸运的是,这些控制器不需要像GSP那样进行太多更改。 对我来说,最大的惊喜是@Transactional指令的含义发生了明显变化。

在Grails 2中,我放置了


@Transactional(readOnly = true) 

在每个CRUD控制器的开头,然后在允许数据更新的位置(例如,save()方法),我将


@Transactional 

这在Grails 3中根本不起作用。在那里,我发现必须放置


@Transactional(readOnly = true) 

仅在只读方法(例如show()方法)之前。

至于域,服务和标记库,则无需进行任何更改。

Spring安全

此时,Spring Security Core和UI都无法正常工作,因此我最终都重新初始化了两者。 对于Core,此命令:


grails s2-quickstart com.ancientware.crm User Role 

做好了 在运行它之前,我已保存了旧的User.groovy域类,因为已向其中添加了一些字段。 不久前,我决定对包含用户,角色和用户角色数据的PostgreSQL表使用不同的名称,因此我不得不将表名称映射插入新的域类定义中。

对于UI,我使用了:



   
   
grails s2ui-override auth
grails s2ui-override layout
grails s2ui-override register com.ancientware.crm.RegisterController
grails s2ui-override register com.ancientware.crm
grails s2ui-override registrationcode com.ancientware.crm
grails s2ui-override securityinfo com.ancientware.crm

我没有启用ACL,因此我跳过了这一部分。

我对静态规则是否正确并不完全满意,但是我在grails-app / conf / application.groovy中添加了以下内容(是的,Spring Security不使用application.yml ),并且我正在测试中:



   
   
    [pattern: '/error/**',       access: ['permitAll']],
    [pattern: '/login',          access: ['permitAll']],
    [pattern: '/login/**',       access: ['permitAll']],
    [pattern: '/logout',         access: ['permitAll']],
    [pattern: '/logout/**',      access: ['permitAll']]

我还将邮件插件的配置内容放入application.groovy中 。 我还没有测试。

最后一件事-Tomcat兼容性

在启动应用程序并运行之后,我们发现了与Tomcat7(旧服务器上可用的最新版本)的有趣不兼容。 我有一些代码使用以下Groovy语法以.CSV格式提供结果:



   
   
response. setHeader "Content-disposition" , "attachment; filename=rcCandidate.csv"
response. contentType = 'text/csv'
response. outputStream << converted
response. outputStream . flush ( )

事实证明,将转换后的内容附加到输出流的第三行为Tomcat7带来了一个巨大的问题。 由StackExchange上非常友善的人提供的解决方案是将最后两行包装在单独的静态方法中,并使用@CompileStatic对其进行注释。 有关更多详细信息,请参见StackExchange上的相关讨论

而已!

结论

首先,尽管文档中的内容很薄,但是我仍然可以通过反复试验来获得适用于我的Grails 3版本的应用程序,特别是通过创建一个新的示例应用程序并研究它与旧代码之间的差异。 。

第二,尽管后期Grails 2 vintage应用程序和Grails 3.3.3(撰写本文时为最新版本)之间确实有很大的差异,但我对缺少重大更改感到非常满意。

第三,我现在需要进行大量测试并总体上使用该系统,并尝试确定过程中最后的一些不确定因素。

第四,也是最重要的是,我仍然非常喜欢Grails。 开发人员讨论了某些编程语言和框架的“含电池”实现; 对我来说,Grails包括“电池,电池工厂,锂矿山和完整的法规批准”。 站在像Spring这样的充满活力的技术之上,所有这些均采用“约定之上的配置”设计,使Grails强大而完全地易于使用。

总之,如果您要维护Grails 2应用程序,建议您尝试将其移至Grails 3,以延长其使用寿命。

翻译自: https://opensource.com/article/18/5/upgrading-grails-applications

grails创建程序

 类似资料: