简体   繁体   English

使用Gradle打包WAR中的依赖关系,同时将临时依赖关系保留在EAR中

[英]Using Gradle to package dependencies in a WAR, while leaving transient dependencies in the EAR

I am very new Gradle. 我是新来的Gradle。 I just started looking at it a couple of days ago, and I really like it, so I am trying to convert my project to Gradle. 我只是几天前才开始查看它,我真的很喜欢它,所以我试图将我的项目转换为Gradle。

I just ran into my first difficult problem. 我刚遇到第一个难题。 I can't figure out how to prevent the 'war' plugin from duplicating a lot of the transient dependencies already found in my EAR. 我无法弄清楚如何防止'war'插件复制EAR中已经发现的许多瞬时依赖项。 For example, let's say that I want to use org.springframework:spring-web in my WAR. 例如,假设我要在WAR中使用org.springframework:spring-web This jar has a lot of transient dependencies, which all get packaged in WEB-INF/lib . 这个jar有很多瞬态依赖项,它们都打包在WEB-INF/lib This is a problem, b/c all of these dependencies are already in APP-INF/lib of my EAR, b/c there are other modules that use them. 这是一个问题,b / c所有这些依赖项已经在我的EAR的APP-INF/lib中,b / c还有其他使用它们的模块。

What I'd like to do is to tell Gradle that I wish to compile the WAR code with all the dependencies as per usual, but when it comes to packaging the WAR, I'd like to have some control over what goes into WEB-INF/lib . 我想告诉Gradle我希望像往常一样使用所有依赖项来编译WAR代码,但是在打包WAR时,我希望对进入WEB-INF/lib As far as I can tell, this functionality is not there. 据我所知,此功能尚不存在。 Or am I missing something? 还是我错过了什么?

I have solved the problem with a hack for now, but I feel that there must be an easier way to do this. 我现在已经通过黑客解决了这个问题,但是我认为必须有一种更简单的方法来做到这一点。 I am hoping that someone with more experience can point out where I went wrong here. 我希望有更多经验的人可以指出我在这里出错的地方。

This is what I have so far: 这是我到目前为止的内容:

apply plugin: 'war'


configurations {
  // Use this config to indicate that a module should be packaged inside the WAR w/o its transitive dependencies
  //
  packageWithoutDependencies 

  // Use this one when you want to package this module and all of its dependencies in the WAR
  //
  packageWithDependencies 

  compile.extendsFrom packageWithoutDependencies
  compile.extendsFrom packageWithDependencies
}

dependencies {
  packageWithDependencies "org.richfaces:richfaces-bom:$richFacesVersion"
  packageWithDependencies "org.richfaces.ui:richfaces-components-ui:$richFacesVersion"
  packageWithDependencies "org.richfaces.core:richfaces-core-impl:$richFacesVersion"

  packageWithoutDependencies "org.springframework:spring-web:$springVersion"
  packageWithoutDependencies "org.springframework.security:spring-security-config:$springSecurityVersion"
  packageWithoutDependencies "org.springframework.security:spring-security-taglibs:$springSecurityVersion"
  packageWithoutDependencies "org.springframework.security:spring-security-web:$springSecurityVersion"
}


// The approach here is to directly modify the classpath used by the 'war' task. This is necessary
// b/c we want to compile with all the dependencies resolved as per usual, yet when we deploy,
// we only want the jars that belong in the WAR, with most transitive dependencies for those already
// deployed as 3rd party jars in the EAR. 
//
task modifyWarClasspath << {
  // Get the names of all non-transitive modules we are packaging
  //
  println " ========= WAR Modules w/o dependencies ========= "
  def firstLevelDeps = configurations.packageWithoutDependencies.resolvedConfiguration.firstLevelModuleDependencies
  def nonTransientDepNames = firstLevelDeps.collect { it.moduleName }
  println nonTransientDepNames

  // Get the names of all direct file includes we are packaging
  //
  println "\n ========= WAR Files w/o dependencies ========= "
  def directFileIncludes = configurations.packageWithoutDependencies
    .getDependencies().findAll{it.hasProperty('source')}
    .source.files*.name.flatten()
  println directFileIncludes

  // Get the names of all transitive modules we a re packaging
  //
  println "\n ========= WAR Modules with dependencies ========= "
  def recursiveDeps = configurations.packageWithDependencies.resolvedConfiguration
    .firstLevelModuleDependencies*.allModuleArtifacts.flatten()

  def transientDepNames = recursiveDeps.collect { it.name }
  println transientDepNames

  // Look through the WAR classpath (runtime - providedCompile), and keep only those
  // files that match a module name on either of the 3 lists we made above.
  //
  println "\n ========= Packaging jars in the WAR ========= "
  war.classpath = war.classpath.findAll {file -> 
    ((nonTransientDepNames + transientDepNames + directFileIncludes + 'main').find {directDepName -> 
      file.name.startsWith(directDepName) 
    } != null)
  }
  war.classpath*.name.sort().each { println it }
  println "\n\n"
}

// Enable 'packageWithDependencies' and 'packageWithoutDependencies' configs
war {
  dependsOn modifyWarClasspath
}

I have a nice simple solution to this now. 我现在有一个很好的简单解决方案。 The key was to make use of a 'provided' scope, and then use it in my WAR dependencies to reference my EAR dependencies. 关键是利用“提供的”范围,然后在我的WAR依赖项中使用它来引用我的EAR依赖项。 That way the entire WAR classpath has the classpath reachable from the EAR dependencies subtracted from it, so only the web dependencies get packaged in the WAR. 这样,整个WAR类路径中的类路径可以从EAR依赖项中减去,因此只有Web依赖项被打包在WAR中。 Nice and simple. 漂亮又简单。

Here's how: 这是如何做:

configurations {
    provided {
        dependencies.all { dep ->
            configurations.default.exclude(group: dep.group, module: dep.name)
        }
    }
    compile.extendsFrom provided
}

And then in your WAR project, you can do: 然后在您的WAR项目中,您可以执行以下操作:

dependencies {
  provided project(':DFIPConfig')
  provided project(':DFIPSAPBatch')
  provided project(':DFIPDomain')
  // etc...

  compile project(':DryDockProjects:DryDockWebProjects:CommonWebWCAGJar')
  compile project(':DryDockProjects:DryDockWebProjects:CommonParticipantWeb')
  // etc...

  // Other WAR dependencies as per usual

}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM