1007
阿裏雲
技術社區[雲棲]
《Groovy官方教程》Grape依賴管理器
1 快速入門
1.1添加一個依賴
Grape是一個內嵌在Groovy裏的Jar包依賴管理器。Grape讓你可以快速添加maven倉庫依賴到你的classpath裏,使腳本運行更加簡單。最簡單的一種用法是隻需要在你的腳本裏添加一個注解:
1 |
@Grab(group='org.springframework', module='spring-orm', version='3.2.5.RELEASE')
|
2 |
import org.springframework.jdbc.core.JdbcTemplate
|
@Grab也支持簡潔版:
1 |
@Grab('org.springframework:spring-orm:3.2.5.RELEASE')
|
2 |
import org.springframework.jdbc.core.JdbcTemplate
|
注意,這裏我們用到了import,這是推薦的做法。當然你也可以在mvnrepository.com搜索到依賴包然後使用@Grab注解形式加到pom.xml實體裏。
1.2特定的倉庫
不是所有的依賴都在maven中心倉庫裏,你可以像下麵這樣添加新的倉庫:
2 |
@Grab(group='org.restlet', module='org.restlet', version='1.1.6')
|
1.3Maven分類器
有些maven依賴需要分類器才能解析,你可以這樣處理:
1 |
@Grab(group='net.sf.json-lib', module='json-lib', version='2.2.3', classifier='jdk15')
|
1.4去除過渡依賴
有時你用到了一些過渡版本的依賴,它們可能和正式穩點版本有一點點差別,這時你想要將過渡依賴排除掉,你可以這樣寫:
1 |
@Grab('net.sourceforge.htmlunit:htmlunit:2.8')
|
2 |
@GrabExclude('xml-apis:xml-apis')
|
(譯者注:原文標題是Excluding Transitive Dependencies,譯者翻譯為過渡依賴。譯者理解為那些非穩定版本的依賴,如果讀者有更好的理解或翻譯請留言,謝謝)
1.5JDBC驅動
你可能需要加載JDBC驅動,因此你需要將JDBC驅動依賴添加到係統類加載器中,示例如下:
1 |
@GrabConfig(systemClassLoader=true) |
2 |
@Grab(group='mysql', module='mysql-connector-java', version='5.1.6')
|
1.6從Groovy Shell中使用Grape
通過groovysh使用grape需要調用一個變量:
1 |
groovy.grape.Grape.grab(group:'org.springframework', module:'spring', version:'2.5.6')
|
1.7代理設置
如果因為防火牆,你可能需要一個代理服務器才能使用Groovy/Grape,你可以將代理服務器設置通過http.proxyHost和http.proxyPort係統屬性在命令行來設置:
1 |
groovy -Dhttp.proxyHost=yourproxy -Dhttp.proxyPort=8080 yourscript.groovy
|
或者你也可以將其添加到JAVA_OPTS環境變量裏:
1 |
JAVA_OPTS = -Dhttp.proxyHost=yourproxy -Dhttp.proxyPort=8080
|
1.8日誌
如果你想查看Grape的運行時狀態,可以通過設置係統屬性groovy.grape.report.downloads為true(比如說將-Dgroovy.grape.report.downloads=true添加JAVA_OPTS或調用它),Grape將會打印下麵的一些係統信息:
- 開始解析依賴
- 開始下載工件(原文為artifact,工件的意思)
- 重新下載工件
- 現在工件的時間和大小
如果要更加詳細的日誌,可以通過提高日誌級別(默認為-1),示例如下:
1 |
-Divy.message.logger.level=4
|
2 詳細
Grape(The Groovy Adaptable Packaging Engine or Groovy Advanced Packaging Engine))是Groovy裏內嵌的一個基礎組件,通過grab()方法調用,一些類可以使用Ivy來打包成倉庫給Groovy用。這就支持開發者通過寫一段腳本來實現一些核心庫的需求。裝載這段腳本,Grape將會在運行時下載並鏈接所有依賴的庫。即便這些庫存在於Jcenter,Ibiblio和java.net
Grape遵從Ivy對模塊版本標識和命名轉換。
- group – 模塊屬於一個模塊組。對應Maven的groupId或者一個Ivy組織。任何匹配/groovy[x][\..*]^/的組都是被保留的,對於Groovy是有特定意義的。
- module – 加載的模塊名字,對應Mavne的artifactId或Ivy的artifact
- version – 模塊使用的版本號,要麼是字符串 ‘1.1-RC3’,要麼是Ivy的[2.2.1,)代表2.2.1或更高版本
- classifier – 可選的分類器,比如jdk15
3 用法
3.1 注解
可以在任何可以放注解的地方放一個或多個groovy.lang.Grab注解來告訴編譯器這段代碼依賴於特定的類庫。這個和添加類庫到Groovy編譯器的效果是一樣的。這個注解將會在任何其他類腳本的運行前被執行,也就是說類的導入可以通過添加@Grab注解來實現:
1 |
import com.jidesoft.swing.JideSplitButton
|
2 |
@Grab(group='com.jidesoft', module='jide-oss', version='[2.2.1,2.3.0)')
|
3 |
public class TestClassAnnotation {
|
4 |
public static String testMethod () {
|
5 |
return JideSplitButton.class.name
|
一個合適的grab(…)調用將會加在包含這個注解類的靜態初始化函數上(或者腳本元素)
3.2 多個Grape注解
如果需要在同一個節點使用一個注解多次可以使用@Grapes注解,比如說:
2 |
@Grab(group='commons-primitives', module='commons-primitives', version='1.0'),
|
3 |
@Grab(group='org.ccil.cowan.tagsoup', module='tagsoup', version='0.9.7')])
|
如果不這樣用的話,將會報這樣的錯:
1 |
Cannot specify duplicate annotation on the same member |
3.3 方法調用
一般地grab調用會在一個類或腳本初始化的時候進行。這可以確保groovy代碼依賴的庫在運行時都被類加載器加載進去。一種典型的調用如下:
1 |
import groovy.grape.Grape
|
2 |
// random maven library |
3 |
Grape.grab(group:'com.jidesoft', module:'jide-oss', version:'[2.2.0,)')
|
4 |
Grape.grab([group:'org.apache.ivy', module:'ivy', version:'2.0.0-beta1', conf:['default', 'optional']],
|
5 |
[group:'org.apache.ant', module:'ant', version:'1.7.0'])
|
- 在同一個地方使用相同的參數多次調用grab是等價的,但是如果使用不同的類加載器可能需要重新運行
- 如果參數列表傳到grab調用有一個noExceptions參數,那麼將不會拋出參數
- grab需要一個rootLoader或GroovyClassLoader,也可以是調用類的類加載器鏈。默認情況下列的情形將會失敗並且拋出異常
- 通過classLoader傳遞的類加載器:參數和它的父類加載器
- 對象的加載器作為引用對象傳入,參數和它的父類加載器
- 類的類加載器調用grab
3.3.1 grab(HashMap)參數
- group: – – 模塊所屬的模塊組,對應Maven的groupId,任何匹配/groovy(|\..|x|x\..)/的組都是保留的,在Groovy模塊中有特殊用途
- module:– 要加載的模塊名,對應Maven的artifactId
- version:-也有可能是-使用的模塊版本號,要麼是字符串1.1-RC3要麼是Ivy Range [2.2.1,)表示2.2.1版本或更高版本
- classifier:–Maven解析的分類器
- conf:-,默認default’ – The configuration or scope of the module to download. The default conf is `default:映射到maven的runtime和master範圍
- force-默認是true,用於衝突時的修複,依賴於衝突管理器
- changing:-,默認是false,是否工件可以修改而不管版本的改變
- transitive:-,默認是true,是否解析其他依賴
grab有兩個基本變量,一個單個的map一個是帶一個map和多個依賴的map。調用單個map的grab和將一個相同的map傳入兩次調用是一樣的,因此grab參數和依賴可以混合在一個map裏,grab可以當成一個具有命名好參數的方法調用。
下麵的參數每組都是相同的意思,如果傳入多餘一個將是一個運行時錯誤
- group:, groupId:, organisation:, organization:, org:
- module:, artifactId:, artifact:
- version:, revision:, rev:
- conf:, scope:, configuration:
3.3.2 參數列表
- classLoader: – 或-解析jar包的類加載器
- refObject:–最近的父類加載器,可以作為加載器參數被傳遞
- validate:-,默認是false,是否驗證poms或ivy文件,或者是否直接信任緩存信息(默認false)
- noExceptions:-,默認是false,如果類加載器或參考查詢失敗,是否應該拋出異常或吞並異常(默認情況)
3.4 命令行工具
Grape增加了一個命令行來執行grape,可以用來檢視和管理本地grape緩存。
1 |
grape install <groupId> <artifactId> [<version>] |
這條命令會安裝特定的groovy模塊或maven工件,如果指定了版本,那麼將安裝特定的的版本,否則安裝最新的版本(類似我們傳遞 * 參數)
列出本地安裝的模塊(如果是groovy模塊,會顯示完整的maven名字)和版本
1 |
grape resolve (<groupId> <artifactId> <version>)+ |
返回安裝的模塊或工件的文件位置,並且會返回傳遞依賴模塊的位置。你可以傳入可選參數-ant,-dos,-shell中來得到ant腳本,windows批處理或unix shell腳本格式文件,-ivy將會得到類ivy格式的依賴
3.5 高級配置
3.5.1 倉庫目錄
如果你需要改變下載庫的grape目錄,可以使用grape.root係統屬性來改變默認值(默認值是~/.groovy/grape)
1 |
groovy -Dgrape.root=/repo/grape yourscript.groovy |
3.5.2 自定義Ivy設置
你可以自定義ivy的是指,通過創建一個~/.groovy/grapeConfig.xml文件,如果沒有這個文件,Grape會使用默認配置,詳細參考這裏。需要查找更多關於自定義設置的文檔,可以參考Ivy文檔。
3.6 更多示例
使用Apache Commons集合工具類
01 |
// create and use a primitive array list |
02 |
import org.apache.commons.collections.primitives.ArrayIntList
|
04 |
@Grab(group='commons-primitives', module='commons-primitives', version='1.0')
|
05 |
def createEmptyInts() { new ArrayIntList() }
|
07 |
def ints = createEmptyInts()
|
09 |
assert ints.size() == 1
|
10 |
assert ints.get(0) == 42
|
使用TagSoup
1 |
// find the PDF links of the Java specifications |
2 |
@Grab(group='org.ccil.cowan.tagsoup', module='tagsoup', version='1.2.1')
|
4 |
def parser = new XmlParser(new org.ccil.cowan.tagsoup.Parser())
|
7 |
html.body.'**'.a.@href.grep(~/.*\.pdf/).each{ println it }
|
使用Google集合工具類
1 |
import com.google.common.collect.HashBiMap
|
2 |
@Grab(group='com.google.code.google-collections', module='google-collect', version='snapshot-20080530')
|
3 |
def getFruit() { [grape:'purple', lemon:'yellow', orange:'orange'] as HashBiMap }
|
4 |
assert fruit.lemon == 'yellow'
|
5 |
assert fruit.inverse().yellow == 'lemon'
|
啟動Jetty服務器來運行Groovy模塊
02 |
@Grab(group='org.eclipse.jetty.aggregate', module='jetty-server', version='8.1.7.v20120910'),
|
03 |
@Grab(group='org.eclipse.jetty.aggregate', module='jetty-servlet', version='8.1.7.v20120910'),
|
04 |
@Grab(group='javax.servlet', module='javax.servlet-api', version='3.0.1')])
|
06 |
import org.eclipse.jetty.server.Server
|
07 |
import org.eclipse.jetty.servlet.*
|
08 |
import groovy.servlet.*
|
10 |
def runServer(duration) {
|
11 |
def server = new Server(8080)
|
12 |
def context = new ServletContextHandler(server, "/", ServletContextHandler.SESSIONS);
|
13 |
context.resourceBase = "."
|
14 |
context.addServlet(TemplateServlet, "*.gsp")
|
第一次啟動這個腳本的時候Grape會下載Jetty和它的依賴,並且會緩存它們。我們在8080端口創建了一個Jetty服務,並且將Groovy的TemplateServlet最為根服務。Groovy有自己強大的模板引擎機製。我們啟動這個服務並且運行一段時間。每次有人訪問https://localhost:8080/somepage.gsp的時候,它會顯示somepage.gsp給用戶,這些模板頁是放在一個相同的目錄下座位服務器腳本。
最後更新:2017-05-22 10:03:42