Grails 插件
? 插件Grails提供了许多扩展点来满足你的扩展,包括从命令行接口到运行时配置引擎。以下章节详细说明了该如何着手来做这些扩展。 12.1 创建和安装插件创建插件创建一个Grails插件,只需要运行如下命令即可: ? grails create-plugin [PLUGIN NAME] 根据你输入的名字将产生一插件工程。比如你输入 除了插件的根目录有一个所谓的“插件描述”的Groovy文件外,其他的跟一般的Grails工程结构完全一样. 将插件作为一个常规的Grails工程是有好处的,比如你可以马上用以下命令来测试你的插件: ? grails run-app ? 由于你创建插件默认是没有 URL 映射的,因此控制器并不会马上有效.如果你的插件需要控制器,那要创建 插件描述文件本身需要符合以 ? class ExampleGrailsPlugin { def version = 0.1 所有插件的根目录下边都必须有此类并且还要有效,此类中定义了插件的版本和其他各式各样的可选的插件扩展点的钩子(hooks)--即插件预留的可以扩展的接口. 通过以下特殊的属性,你还可以提供插件的一些额外的信息:
以 Quartz Grails plugin为例: ? class QuartzGrailsPlugin { def version = "0.1" def author = "Sergey Nebolsin" def authorEmail = "nebolsin@gmail.com" def title = "This plugin adds Quartz job scheduling features to Grails application." def description = ''' Quartz plugin allows your Grails application to schedule jobs to be executed using a specified interval or cron expression. The underlying system uses the Quartz Enterprise Job Scheduler configured via Spring,but is made simpler by the coding by convention paradigm. ''' def documentation = "http://grails.org/Quartz+plugin" ? 插件的安装和发布要发布插件,你需要一个命令行窗口,并且进入到插件的根目录,输入: ? grails package-plugin
这将创建一个 产生了可以发布的插件文件以后(zip文件),进入到你自己的Grails工程的根目录,输入: ? grails install-plugin /path/to/plugin/grails-example-0.1.zip 如果你的插件放在远程的Http服务器上,你也可以这样: ? grails install-plugin http://myserver.com/plugins/grails-example-0.1.zip ? 注意被排除的组件尽管 create-plugin 命令为您创建某些文件,以便插件能做为Grails应用运行,但是当打包插件的时候不是所有的文件都会在含在里面. 以下是通过package-plugin创建时,不包含的文件和目录:
如果你希望创建包含 ? ? 12.2 插件仓库在Grails插件的存储仓库(Repository)发布插件更好的发布插件的方式是将其发布到Grails插件的存储仓库. 这样通过 list-plugins 命令就可以看到你的插件了: ? grails list-plugins 此命令将列出Grails插件存储库的所有插件,当然了也可以用 plugin-info 来查看指定插件的信息: ? grails plugin-info [plugin-name] 这将输出更多的详细信息,这些信息都是维护在插件描述文件中的。 ? 如果你创建了一个Grails插件,你可以访问 创建插件,这里详细说明了如何在容器中发布你的插件。 当你有访问Grails插件仓库的权限时,要发行你的插件,只需要简单执行 release-plugin 即可: ? grails release-plugin 这将自动地将改动提交到SVN和创建标签(svn的tagging),并且通过 list-plugins 命令你可以看到这些改动. ? 配置附加库默认情况下,您使用的 list-plugins,install-plugin and release-plugin 命令都指向 http://plugins.grails.org。 然而,要配置多个插件仓库,您可以使用 ? grails.plugin.repos.discovery.myRepository="http://svn.codehaus.org/grails/trunk/grails-test-plugin-repo" grails.plugin.repos.distribution.myRepository="https://svn.codehaus.org/grails/trunk/grails-test-plugin-repo" Repositories are split into those used for discovery over HTTP and those used for distribution,typically over HTTPS. 如果你想在多个项目中使用相同的设置,你可以把这些配置到 一旦使用了 list-plugins,install-plugin and plugin-info 命令将会自动处理最新配置的插件库。如果你只想把插件库中的插件列表列出来,你可以使用别名: ? grails list-plugins -repository=myRepository 此外,如果你想和配置好的插件包一起发布插件,你可以用 release-plugin 命令: ? grails release-plugin -repository=myRepository ? 12.3 理解插件的结构如前所提到的,一个插件除了包含一个插件描述文件外,几乎就是一个常规的Grails应用。尽管如此,当安装以后,插件的结构还是有些许的差别。比如一个插件目录的结构如下: ? + grails-app + controllers + domain + taglib etc. + lib + src + java + groovy + web-app + js + css 从本质上讲,当一个插件被安装到Grails工程以后, 然而,那些在特定插件目录中 因此,要从正确的地方引用这些静态资源也就成为插件的责任。比如,你要在GSP中引用一个JavaScript文件,你可以这样: ? <g:createLinkTo dir="/plugins/example/js" file="mycode.js" />
这样做当然可以,但是当你开发插件并且单独运行插件的时候,将产生相对链接(link)的问题. 为了应对这种变化即不管插件是单独运行还是在Grails应用中运行,特地新增一个特别的 ? <g:createLinkTo dir="${pluginContextPath}/js" file="mycode.js" />
这样在运行期间 在lib和 12.4 提供基础的工件增加新的脚本在插件的scripts目录下可以增加新的Gant相关的脚本: ? + MyPlugin.groovy + scripts <-- additional scripts here + grails-app + controllers + services + etc. + lib ? 增加新的控制器,标签库或者服务在 ? + ExamplePlugin.groovy + scripts + grails-app + controllers <-- additional controllers here + services <-- additional services here + etc. <-- additional XXX here + lib ? Providing Views,Templates and View resolution提供控制器的插件也会提供默认的视图。通过插件模块化您的应用是个很好的途径。Grails视图处理机制的工作原理是首先查看应用中被安装的视图,如果失败将视图查找插件中的视图。 比如有一个 但是,如果视图使用了模板,同时插件也提供了这个视图,那么必须使用以下的语法: ? <g:render template="fooTemplate" contextPath="${pluginContextPath}"/> 注意 ? Excluded Artefacts默认的,when packaging a plug-in,当打包一个插件时,Grails 的插件包中将不包含以下文件:
如果你的插件需要 此外, 12.5 评估规约 在得以继续查看基于规约所能提供的运行时配置以前,有必要了解一下怎样来评估插件的这些基本规约。本质上,每一个插件都有一个隐含的 GrailsApplication接口的实例变量:
一个 ? application.allClasses.each { println it.name } 在 ? application.controllerClasses.each { println it.name } 这些动态方法的规约如下:
完整的索引请参考 javadoc API. 12.6 参与构建事件安装后进行配置和参与升级操作Grails插件可以在安装完后进行配置并且可以参与应用的升级过程(通过 upgrade命令),这是由scripts目录下两个特定名称的脚本来完成的: -
这些是一个普通的 Gant 脚本,因此你完全可以使用Gant的强大特性。另外 以下的 ? Ant.mkdir(dir:"${basedir}/grails-app/jobs") Ant.copy(file:"${pluginBasedir}/src/samples/SamplePluginConfiguration.groovy",todir:"${basedir}/grails-app/conf") ? 脚本事件将插件和命令行的脚本事件关联起来还是有可能的,这些事件在执行Grails的任务和插件事件的时候被触发。 比如你希望在更新的时候,显示更新状态(如"Tests passed","Server running"),并且创建文件或者人工制品。 一个插件只能通过 12.7 运行时配置中的钩子Hooking into Runtime ConfigurationGrails提供了很多的钩子函数来处理系统的不同部分,并且通过惯例的形式来执行运行时配置。 ? 跟Grails的Spring配置进行交互首先你可以使用 ? import org.springframework.web.servlet.i18n.CookieLocaleResolver; import org.springframework.web.servlet.i18n.LocaleChangeInterceptor; import org.springframework.context.support.ReloadableResourceBundleMessageSource; 这个插件建立起了Grails ? 参与web.xml的生成Grails是在加载的时候生成 考虑如下来自 ? def doWithWebDescriptor = { webXml -> def mappingElement = webXml.'servlet-mapping' mappingElement + { 'servlet-mapping' { 'servlet-name'("grails") 'url-pattern'("*.dispatch") } } } 此处插件得到最后一个 ? 在初始化完毕后进行配置有时候在Spring的 ApplicationContext 被创建以后做一些运行时配置是有意义的,这种情况下,你可以定义 ? class SimplePlugin { def name="simple" def version = 1.1 ? 12.8 运行时添加动态方法基础知识Grails插件允许你在运行时注册Grails管辖类或者其他类的动态方法,但新的方法只能通过 对Grails管辖类来说,比如controllers、tag libraries等等,你可以增加方法,构造函数等,这是通过 ExpandoMetaClass 机制做到的,比如访问每个控制器的 MetaClass的代码如下所示: ? class ExamplePlugin {
def doWithDynamicMethods = { applicationContext ->
application.controllerClasses.each { controllerClass ->
controllerClass.metaClass.myNewMethod = {-> println "hello world" }
}
}
}
此处我们通过隐含的application对象来获取所有控制器类的MetaClass实例,并且为每一个控制器增加一个 ? class ExamplePlugin { 此例中,我们直接在 ? 跟ApplicationContext交互
? import org.springframework.orm.hibernate3.HibernateTemplate 另外因为Spring容器具有自动装配和依赖注入的能力,你可以在运行时实现更强大的动态构造器,此构造器使用applicationContext来装配你的对象及其依赖: ? class MyConstructorPlugin { 这里我们实际做的是通过查找Spring的原型beans(prototyped beans)来替代缺省的构造器。 ? 12.9 参与自动重载监控资源的改变通常来讲,当资源发生改变的时候,监控并且重新加载这些变化是非常有意义的。这也是Grails为什么要在运行时实现复杂的应用程序重新加载。查看如下Grails的 ? class ServicesGrailsPlugin { … def watchedResources = "file:./grails-app/services/*Service.groovy" 首先定义了
通过这些对象,你可以评估这些惯例,而且基于这些惯例你可以将这些变化适当的应用到 ? 影响其他插件当一个插件变化时,插件不但要有相应地反应,而且有时还会“影响”另外的插件。 以Services 和 Controllers插件为例. 当一个service被重新加载的时候,除非你也重新加载controllers,否则你将加载过的service自动装配到旧的controller类的时候,将会发生问题。. 为了避免这种情况发生,你可以指定将要受到“影响”的另外一个插件,这意味着当一个插件监测到改变的时候,它将先重新加载自身,然后重新加载它所影响到的所有插件。看 ? def influences = ['controllers'] ? 观察其他插件如果你想观察一个特殊的插件的变化但又不需要监视插件的资源,那你可以使用"observe"属性: ? def observe = ["hibernate"]
在此示例中,当一个Hibernate的领域类变化的时候,你将收到从hibernate插件传递过来的事件。你也可以使用一个通配符查看所有加载的插件: ? def observe = ["*"]
Logging plugin不仅如此,当应用运行时它都能添加 12.10 理解插件加载的顺序Controlling Plug-in Dependencies插件经常依赖于其他已经存在的插件,并且也能调整这种依赖. 为了做到这点,一个插件可以定义两个属性,首先是 ? class HibernateGrailsPlugin { def version = 1.0 def dependsOn = [dataSource:1.0,domainClass:1.0,i18n:1.0,core: 1.0] 如上述示例所演示的,Hibernate插件依赖于4个插件: 根本上讲,这些被依赖的插件将先被加载,接着才是Hibernate插件,如果这些被依赖的插件没有加载,那么Hibernate也不会加载。
? def dependsOn = [foo:"* > 1.0"] def dependsOn = [foo:"1.0 > 1.1"] def dependsOn = [foo:"1.0 > *"] 当使用*通配符的时候,它表示"任何"版本。 The expression syntax also excludes any suffixes such as -BETA,-ALPHA etc. so for example the expression "1.0 > 1.1" would match any of the following versions:
? Controlling Load Order如果所依赖的插件不能被解析的话,则依赖于此的插件将被放弃并且不会被加载,这就是所谓的“强”依赖。然而我们可以通过使用 loadAfter来定义一个“弱”依赖,示例如下: ? def loadAfter = ['controllers'] 此处如果 ? if(manager?.hasGrailsPlugin("controllers")) { openSessionInViewInterceptor(OpenSessionInViewInterceptor) { flushMode = HibernateAccessor.FLUSH_MANUAL sessionFactory = sessionFactory } grailsUrlHandlerMapping.interceptors << openSessionInViewInterceptor } 这里, (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |