背景:在JAVA中执行groovy有多种方式,个人觉得最舒服的莫过于使用IDE插件创建groovy工程,这样可以直接在java代码中引用groovy的类。因groovy的IDE插件会自动对groovy脚本编译,并生成相应的class放于工程的output目录下,这样在编译时就不会报错,直接使用groovy类了。这种方式在协作开发时就有了不便,这要求团队中其它人也要使用groovy插件,否则别人的环境中就会编译报错,且个人觉得目前eclipse对groovy的支持不是很好,如果没有创建groovy工程,那么脚本默认不会自动编译(可能是我个人没有找到好的方式),所以如果要在老的项目中使用一些groovy实现,那么可能还是需要使用脚本引擎或者groovy的GroovyShell或GroovyClassLoader。


       本文是JAVA与groovy交互的例子,通过简单的解析xml配置的例子,涉及了JAVA与groovy中互相调用、使用groovy解析xml的方法。

1、环境

       需下载groovy的发布包,解压后将其lib下如下jar加入工程的classpath,本文使用的是groovy1.8.6版本。

2、代码

   代码结构:

 

    先给出解析的xml配置文件,一个简单的用户管理配置users.xml,主要包含两个elements,分别是users、roles,即用户和角色:

 
  
  1. <?xml version="1.0" encoding="UTF-8"?> 
  2. <userMgr> 
  3.     <users role="administrator"> 
  4.         <user name="root"> 
  5.             <authType>local</authType> 
  6.             <type>admin</type> 
  7.         </user> 
  8.         <user name="domain"> 
  9.             <authType>LDAP</authType> 
  10.             <type>admin</type> 
  11.         </user> 
  12.     </users> 
  13.  
  14.     <roles> 
  15.         <role name="administrator"> 
  16.             <auth>user</auth> 
  17.             <auth>res</auth> 
  18.         </role> 
  19.     </roles> 
  20. </userMgr> 

    再给出解析该xml的groovy脚本parseUserXml.groovy,该脚本通过JAVA client传递的输入流解析xml并打印输出各节点,并且将xml转为java模型存储到JAVA的缓存中,代码有些冗长但多数代码是在做打印输出和模型转换,而具体的xml的解析实际是很简单的:    

 
  
  1. import groovy.CacheXml; 
  2. import model.*; 
  3.  
  4. def doParse(InputStream ins){ 
  5.  
  6.     // 使用输入流构造XmlParser 
  7.     def userMgr = new XmlParser().parse(ins) 
  8.  
  9.     println "---------- users ----------" 
  10.     println "role:" + userMgr.users[0].attribute("role"
  11.  
  12.     // 对于非遍历的情况类似数据的操作,可直接用下标引用 
  13.     userMgr.users[0].user.each { 
  14.         println "\nuser name: " + it.attribute("name"
  15.         println "user authType: " + it.authType.text() 
  16.         println "user type: " + it.type.text() 
  17.  
  18.         // 转换为java模型并加入缓存 
  19.         User user = new User(); 
  20.         user.setAuthType(it.authType.text()) 
  21.         user.setName(it.attribute("name")) 
  22.         user.setType(it.type.text()) 
  23.         CacheXml.getInstance().put(user.getName(), user); 
  24.     } 
  25.  
  26.     println "\n---------- roles ----------" 
  27.  
  28.     // 闭包嵌套 
  29.     userMgr.roles[0].role.each {role -> 
  30.         println "role type" + role.attribute("name"
  31.          
  32.         // 转换为java模型并加入缓存 
  33.         Role rol = new Role() 
  34.         rol.setName(role.attribute("name")) 
  35.         Set authSet = new HashSet(); 
  36.          
  37.         role.each { 
  38.             println "auth: " + it.text() 
  39.             authSet.add(it.text()); 
  40.         } 
  41.          
  42.         rol.setAuths(authSet); 
  43.         CacheXml.getInstance().put(rol.getName(), rol) 
  44.     } 

User.java和Role.java只是两个JavaBean,其属性对应着xml中相关配置,实现时只是重写了toString方法(使用eclipse的缺省实现),这里省略其代码。CacheXml是一个map缓存用来缓存配置转换后的模型对象:

 
  
  1. import java.util.HashMap; 
  2. import java.util.Map; 
  3. import java.util.Map.Entry; 
  4. import java.util.Set; 
  5.  
  6. public class CacheXml 
  7.     private static CacheXml cx = null
  8.  
  9.     private static Map<String, Object> map1 = new HashMap<String, Object>(); 
  10.  
  11.     public static synchronized CacheXml getInstance() 
  12.     { 
  13.         if (cx == null
  14.         { 
  15.             return new CacheXml(); 
  16.         } 
  17.         return cx; 
  18.     } 
  19.  
  20.     public static void put(String key, Object value) 
  21.     { 
  22.         map1.put(key, value); 
  23.     } 
  24.  
  25.     public String toString() 
  26.     { 
  27.         StringBuilder sb = new StringBuilder(); 
  28.  
  29.         Set<Entry<String, Object>> set = map1.entrySet(); 
  30.  
  31.         for (Entry<String, Object> entry : set) 
  32.         { 
  33.             sb.append("key:" + entry.getKey() + ",value:" + entry.getValue() 
  34.                     + "\n"); 
  35.         } 
  36.  
  37.         return sb.toString(); 
  38.     } 

        最后给出调用groovy的JAVA client

 
  
  1. package groovy; 
  2.  
  3. import java.io.IOException; 
  4. import java.io.InputStream; 
  5. import java.io.InputStreamReader; 
  6.  
  7. import javax.script.Invocable; 
  8. import javax.script.ScriptEngine; 
  9. import javax.script.ScriptEngineManager; 
  10. import javax.script.SimpleBindings; 
  11.  
  12. public class XmlParserWithEngineManager 
  13.  
  14.     public static void main(String[] args) 
  15.     { 
  16.         // 使用java script API获取脚本引擎 
  17.         ScriptEngineManager sem = new ScriptEngineManager(); 
  18.         ScriptEngine engine = sem.getEngineByName("groovy"); 
  19.  
  20.         // 绑定入参 
  21.         SimpleBindings bindings = new SimpleBindings(); 
  22.         InputStream inXml = XmlParserWithEngineManager.class 
  23.                 .getResourceAsStream("/users.xml"); 
  24.         bindings.put("ins", inXml); 
  25.  
  26.         InputStream in = null
  27.         try 
  28.         { 
  29.             in = XmlParserWithEngineManager.class 
  30.                     .getResourceAsStream("/groovy/parseUserXml.groovy"); 
  31.              
  32.             Invocable inv = (Invocable) engine; 
  33.              
  34.             engine.eval(new InputStreamReader(in), bindings); 
  35.             inv.invokeFunction("doParse"new Object[] { inXml }); 
  36.              
  37.             System.out.println("---------- IN JAVA ----------\n" 
  38. + CacheXml.getInstance().toString()); 
  39.              
  40.         } 
  41.         catch (Exception ex) 
  42.         { 
  43. // TODO
  44.             ex.printStackTrace(); 
  45.         } 
  46.         finally 
  47.         { 
  48.             if (in != null
  49.             { 
  50.                 try 
  51.                 { 
  52.                     in.close(); 
  53.                 } 
  54.                 catch (IOException e) 
  55.                 { 
  56.                     // TODO 
  57.                     e.printStackTrace(); 
  58.                 } 
  59.             } 
  60.             if (inXml != null
  61.             { 
  62.                 try 
  63.                 { 
  64.                     inXml.close(); 
  65.                 } 
  66.                 catch (IOException e) 
  67.                 { 
  68.                     // TODO 
  69.                     e.printStackTrace(); 
  70.                 } 
  71.             } 
  72.         } 
  73.     } 

3、运行

        运行XmlParserWithEngineManager类,有如下控制台输出:

 
  
  1. ---------- users ---------- 
  2. role:administrator 
  3.  
  4. user name: root 
  5. user authType: local 
  6. user type: admin 
  7.  
  8. user name: domain 
  9. user authType: LDAP 
  10. user type: admin 
  11.  
  12. ---------- roles ---------- 
  13. role typeadministrator 
  14. auth: user 
  15. auth: res 
  16. ---------- IN JAVA ---------- 
  17. key:root,value:User [name=root, authType=local, type=admin] 
  18. key:administrator,value:Role [name=administrator, auths=[res, user]] 
  19. key:domain,value:User [name=domain, authType=LDAP, type=admin]