如何检查Gradle CopySpec以将其导出为文本表示?

时间:2017-02-01 14:33:45

标签: java gradle groovy

我使用应用程序服务器的功能,允许我直接从Gradle的输出文件夹和源文件夹中的静态文件部署资源和类。我不想浪费时间打包到 EAR WAR JAR ,我想在不重新部署的情况下使用类似HotSwap的功能。< / p>

让我用一个简单的gradle项目和Tomcat 7来演示这个想法。

假设我们有一个具有以下结构的文件夹:

.
|-- build.gradle
`-- src
    |-- css
    |   `-- main.css
    |-- html
    |   `-- index.html
    `-- images
        `-- logo.png

4 directories, 4 files

我创建了一个简单的gradle项目:

的build.gradle

apply plugin: 'war'

war {
  destinationDir temporaryDir
  into 'META-INF/resources', {
    from 'src/html/index.html'
  }
  into 'META-INF/resources/static', {
    from 'src/css'
  }
  into 'META-INF/resources/static', {
    from 'src/images'
  }
}

然后,能够自动创建以下配置是完美的:

$ CATALINA_HOME /卡塔利娜/本地主机/ myapp.xml

<?xml version="1.0" encoding="UTF-8"?>
<Context docBase="">
  <Resources className="org.apache.naming.resources.VirtualDirContext" extraResourcePaths="
    /META-INF/resources/index.html=C:/myapp/src/html/index.html,
    /META-INF/resources/static=C:/myapp/src/css,
    /META-INF/resources/static=C:/myapp/src/images
  "/>
</Context>

请注意仅仅创建一个文件列表(没有文件夹映射)是不够的,例如:

/META-INF/resources/index.html=C:/myapp/src/html/index.html
/META-INF/resources/static/main.css=C:/myapp/src/css/main.css,
/META-INF/resources/static/logo.png=C:/myapp/src/images/logo.png

因为最初的问题陈述意味着有必要在没有重新部署应用程序的情况下创建和删除传入文件夹中的文件。

更新1

在Gradle的github上创建issue

更新2

请注意,这个例子只是一个虚构的案例来向您展示这个想法。我知道java源路径约定。

我的目标是找到一种自动生成现有大型项目的CopySpec地图的方法。我想为任何开发人员提供添加和删除CopySpec(或基于CopySpec的任务)的能力,而不了解它如何转换为应用服务器的映射配置的详细信息。

3 个答案:

答案 0 :(得分:1)

我能想到的三种方法

  1. 将groovy代码解析为AST并从AST生成xml。这对我来说真的很难

  2. 首先在您自己的自定义模型中定义目录等。然后根据相同的模型生成CopySpecXML。这听起来更容易

  3. 通过内部Gradle API(例如WarAbstractCopyTaskCopySpecInternal)来确定您是否可以执行任何操作。也许您可以使用CopySpecVisitorCopySpecListener解决此问题。注意:如果您使用内部API,Gradle不保证在将来的版本中不会被破坏。

答案 1 :(得分:0)

您可以使用eachFile来记录参与战争的所有文件的父目录,并使用doLast来处理您的记录并生成所需的XML。

为方便起见,我使用了Guava的Multimap,因为相同的虚拟目录(在您的应用容器中)可以映射到多个物理目录。

以下脚本打印到stdout,但您可以轻松更改它以写入文件:

buildscript {
    repositories { jcenter() }
    dependencies { classpath 'com.google.guava:guava:18.0' }
}

import com.google.common.collect.ArrayListMultimap
import groovy.xml.MarkupBuilder

apply plugin: 'war'

war {
    destinationDir temporaryDir
    into 'META-INF/resources', {
        from 'src/html/index.html'
    }
    into 'META-INF/resources/static', {
        from 'src/css'
    }
    into 'META-INF/resources/static', {
        from 'src/images'
    }

    def parentDirs = ArrayListMultimap.create()
    eachFile { file ->
        parentDirs.put(file.relativePath.parent, file.file.parent)
    }

    doLast {
        def lines = []
        for (e in parentDirs.entries()) {
           lines.add("$e.key=$e.value")
        }

        def writer = new StringWriter()
        def xml = new MarkupBuilder(writer)
        xml.Context(docBase:"") {
            Resources(className:"org.apache.naming.resources.VirtualDirContext",
                extraResourcePaths:lines.join(","))
        }
        println writer
    }
}

答案 2 :(得分:0)

为什么要将东西存放在这些非标准位置?为什么不使用Gradle(和Maven)约定?你可以:

  1. src/html/index.html移至src/main/webapp/META-INF/resources
  2. src/css/*.*移至src/main/webapp/META-INF/resources/static/*.*
  3. src/images/*.*移至src/main/webapp/META-INF/resources/static/*.*
  4. into ... from ...配置中删除war(因为使用标准惯例)
  5. /
  6. 中添加从C:/myapp/src/main/webapp$CATALINA_HOME/Catalina/localhost/myapp.xml的单一映射

    请参阅here

      

    War任务的默认行为是将src / main / webapp的内容复制到存档的根目录