萬法歸宗之Hadoop編程無界限

記錄下,散仙今天的工做以及遇到的問題和解決方案,俗話說,好記性不如爛筆頭,寫出來文章,供你們參考,學習和點評,進步,纔是王道 ,廢話很少說,下面切入主題: 

先介紹下需求: 

散仙要處理多個相似表的txt數據,固然只有值,列名什麼的所有在xml裏配置了,而後加工這些每一個表的每一行數據,生成特定的格式基於ASCII碼1和ASCII碼2做爲分隔符的一行數據,ASCII2做爲字段名和字段值的分隔符,ASCII1做爲字段和字段之間的分隔符,每解析一個txt文件時,都要獲取文件名,而後與xml中的schema信息映射並找到對應位置的值,它的列名,前提是,這些的txt的內容位置,是固定的,而後咱們知道它每一行屬於哪一個表結構的映射,由於這些映射信息是提早配置在xml中的,以下圖: 



固然相似這樣的結構有20個左右的表文件,到時候,咱們的數據方,會給咱們提供這些txt文件,而後散仙須要加工成特定的格式,而後寫入HDFS,由咱們的索引系統使用MapReduce批量建索引使用。 

原本想直接用java寫個單機程序,串行處理,而後寫入HDFS,後來一想假如數據量比較大,串行程序還得改爲多線程並行執行,這樣改來改去,倒不如直接使用MapReduce來的方便 


ok,說幹就幹,測試環境已經有一套CDH5.3的hadoop2.5集羣,直接就在eclipse進行開發和MapReduce程序的調試,反正也很久也沒手寫MapReduce了,前段時間,一直在用Apache Pig分析數據,此次處理的邏輯也不復雜,就再寫下練練手 , CDH的集羣在遠程的服務器上,散仙本機的hadoop是Apache Hadoop2.2的版本,在使用eclipse進行開發時,也沒來得及換版本,理論上最好各個版本,不一樣發行版,之間對應起來開發比較好,這樣通常不會存在兼容性問題,但散仙此次就懶的換了,由於CDH5.x以後的版本,是基於社區版的Apache Hadoop2.2之上改造的,接口應該大部分都一致,固然這只是散仙猜測的。 



(1)首先,散仙要搞定的事,就是解析xml了,在程序啓動以前須要把xml解析,加載到一個Map中,這樣在處理每種txt時,會根據文件名來去Map中找到對應的schma信息,解析xml,散仙直接使用的jsoup,具體爲啥,請點擊散仙這篇 
http://qindongliang.iteye.com/blog/2162519文章,在這期間遇到了一個比較蛋疼的問題,簡直是一個bug,最先散仙定義的xml是每一個表,一個table標籤,而後它下面有各個property的映射定義,可是在用jsoup的cssQuery語法解析時,發現老是解析不出來東西,按照之前的作法,是沒任何問題的,此次簡直是開玩笑了,後來就是各類搜索,測試,最後才發現,將table標籤,換成其餘的任何標籤都無任何問題,具體緣由,散仙還沒來得及細看jsoup的源碼,猜想table標籤應該是一個關鍵詞什麼的標籤,在解析時會和html的table衝突,因此在xml解析中失效了,花了接近2個小時,求證,檢驗,終於搞定了這個小bug。 


(2)搞定了這個問題,散仙就開始開發調試MapReduce版的處理程序,這下面臨的又一個問題,就是如何使用Jsoup解析存放在HDFS上的xml文件,有過Hadoop編程經驗的人,應該都知道,HDFS是一套分佈式的文件系統,與咱們本地的磁盤的存儲方式是不同的,好比你在正常的JAVA程序上解析在C:\file\t.tx或者在linux上/home/user/t.txt,所編寫的程序在Hadoop上是沒法使用的,你得使用Hadoop提供的編程接口獲取它的文件信息,而後轉成字符串以後,再給jsoup解析。 


(3)ok,第二個問題搞定以後,你得編寫你的MR程序,處理對應的txt文本,並且保證不一樣的txt裏面的數據格式,所獲取的scheaml是正確的,因此在map方法裏,你要獲取固然處理文件的路徑,而後作相應判斷,在作對應處理。 


(4)很好,第三個問題搞定以後,你的MR的程序,基本編寫的差很少了,下一步就改考慮如何提交到Hadoop的集羣上,來調試程序了,因爲散仙是在Win上的eclipse開發的,因此這一步可能遇到的問題會不少,並且加上,hadoop的版本不一致與發行商也不一致,出問題也純屬正常。 


這裏多寫一點,通常建議你們不要在win上調試hadoop程序,這裏的坑很是多,若是能夠,仍是建議你們在linux上直接玩,下面說下,散仙今天又踩的坑,關於在windows上調試eclipse開發, 運行Yarn的MR程序,散仙之前也記錄了文章,感興趣者,能夠點擊這個連接 
http://qindongliang.iteye.com/blog/2078452地址。 


(5)提交前,是須要使用ant或maven或者java自帶的導出工具,將項目打成一個jar包提交的,這一點你們須要注意下,最後測試得出,Apache的hadoop2.2編寫的MR程序,是能夠直接向CDH Hadoop2.5提交做業的,可是因爲hadoop2.5中,使用google的guice做爲了一個內嵌的MVC輕量級的框架,因此在windows上打包提交時,須要引入額外的guice的幾個包,截圖以下: 



 

上面幾步搞定後,打包整個項目,而後運行成功,過程以下:  
Java代碼   收藏代碼
  1. 輸出路徑存在,已刪除!  
  2. 2015-04-08 19:35:18,001 INFO  [main] client.RMProxy (RMProxy.java:createRMProxy(56)) - Connecting to ResourceManager at /172.26.150.18:8032  
  3. 2015-04-08 19:35:18,170 WARN  [main] mapreduce.JobSubmitter (JobSubmitter.java:copyAndConfigureFiles(149)) - Hadoop command-line option parsing not performed. Implement the Tool interface and execute your application with ToolRunner to remedy this.  
  4. 2015-04-08 19:35:21,156 INFO  [main] input.FileInputFormat (FileInputFormat.java:listStatus(287)) - Total input paths to process : 2  
  5. 2015-04-08 19:35:21,219 INFO  [main] mapreduce.JobSubmitter (JobSubmitter.java:submitJobInternal(394)) - number of splits:2  
  6. 2015-04-08 19:35:21,228 INFO  [main] Configuration.deprecation (Configuration.java:warnOnceIfDeprecated(840)) - user.name is deprecated. Instead, use mapreduce.job.user.name  
  7. 2015-04-08 19:35:21,228 INFO  [main] Configuration.deprecation (Configuration.java:warnOnceIfDeprecated(840)) - mapred.jar is deprecated. Instead, use mapreduce.job.jar  
  8. 2015-04-08 19:35:21,228 INFO  [main] Configuration.deprecation (Configuration.java:warnOnceIfDeprecated(840)) - fs.default.name is deprecated. Instead, use fs.defaultFS  
  9. 2015-04-08 19:35:21,229 INFO  [main] Configuration.deprecation (Configuration.java:warnOnceIfDeprecated(840)) - mapred.reduce.tasks is deprecated. Instead, use mapreduce.job.reduces  
  10. 2015-04-08 19:35:21,229 INFO  [main] Configuration.deprecation (Configuration.java:warnOnceIfDeprecated(840)) - mapred.mapoutput.value.class is deprecated. Instead, use mapreduce.map.output.value.class  
  11. 2015-04-08 19:35:21,230 INFO  [main] Configuration.deprecation (Configuration.java:warnOnceIfDeprecated(840)) - mapreduce.map.class is deprecated. Instead, use mapreduce.job.map.class  
  12. 2015-04-08 19:35:21,230 INFO  [main] Configuration.deprecation (Configuration.java:warnOnceIfDeprecated(840)) - mapred.job.name is deprecated. Instead, use mapreduce.job.name  
  13. 2015-04-08 19:35:21,230 INFO  [main] Configuration.deprecation (Configuration.java:warnOnceIfDeprecated(840)) - mapreduce.inputformat.class is deprecated. Instead, use mapreduce.job.inputformat.class  
  14. 2015-04-08 19:35:21,230 INFO  [main] Configuration.deprecation (Configuration.java:warnOnceIfDeprecated(840)) - mapred.input.dir is deprecated. Instead, use mapreduce.input.fileinputformat.inputdir  
  15. 2015-04-08 19:35:21,230 INFO  [main] Configuration.deprecation (Configuration.java:warnOnceIfDeprecated(840)) - mapred.output.dir is deprecated. Instead, use mapreduce.output.fileoutputformat.outputdir  
  16. 2015-04-08 19:35:21,230 INFO  [main] Configuration.deprecation (Configuration.java:warnOnceIfDeprecated(840)) - mapreduce.outputformat.class is deprecated. Instead, use mapreduce.job.outputformat.class  
  17. 2015-04-08 19:35:21,231 INFO  [main] Configuration.deprecation (Configuration.java:warnOnceIfDeprecated(840)) - mapred.map.tasks is deprecated. Instead, use mapreduce.job.maps  
  18. 2015-04-08 19:35:21,233 INFO  [main] Configuration.deprecation (Configuration.java:warnOnceIfDeprecated(840)) - mapred.mapoutput.key.class is deprecated. Instead, use mapreduce.map.output.key.class  
  19. 2015-04-08 19:35:21,233 INFO  [main] Configuration.deprecation (Configuration.java:warnOnceIfDeprecated(840)) - mapred.working.dir is deprecated. Instead, use mapreduce.job.working.dir  
  20. 2015-04-08 19:35:21,331 INFO  [main] mapreduce.JobSubmitter (JobSubmitter.java:printTokens(477)) - Submitting tokens for job: job_1419419533357_5012  
  21. 2015-04-08 19:35:21,481 INFO  [main] impl.YarnClientImpl (YarnClientImpl.java:submitApplication(174)) - Submitted application application_1419419533357_5012 to ResourceManager at /172.21.50.108:8032  
  22. 2015-04-08 19:35:21,506 INFO  [main] mapreduce.Job (Job.java:submit(1272)) - The url to track the job: http://http://dnode1:8088/proxy/application_1419419533357_5012/  
  23. 2015-04-08 19:35:21,506 INFO  [main] mapreduce.Job (Job.java:monitorAndPrintJob(1317)) - Running job: job_1419419533357_5012  
  24. 2015-04-08 19:35:33,777 INFO  [main] mapreduce.Job (Job.java:monitorAndPrintJob(1338)) - Job job_1419419533357_5012 running in uber mode : false  
  25. 2015-04-08 19:35:33,779 INFO  [main] mapreduce.Job (Job.java:monitorAndPrintJob(1345)) -  map 0% reduce 0%  
  26. 2015-04-08 19:35:43,885 INFO  [main] mapreduce.Job (Job.java:monitorAndPrintJob(1345)) -  map 100% reduce 0%  
  27. 2015-04-08 19:35:43,902 INFO  [main] mapreduce.Job (Job.java:monitorAndPrintJob(1356)) - Job job_1419419533357_5012 completed successfully  
  28. 2015-04-08 19:35:44,011 INFO  [main] mapreduce.Job (Job.java:monitorAndPrintJob(1363)) - Counters: 27  
  29.     File System Counters  
  30.         FILE: Number of bytes read=0  
  31.         FILE: Number of bytes written=166572  
  32.         FILE: Number of read operations=0  
  33.         FILE: Number of large read operations=0  
  34.         FILE: Number of write operations=0  
  35.         HDFS: Number of bytes read=47795  
  36.         HDFS: Number of bytes written=594  
  37.         HDFS: Number of read operations=12  
  38.         HDFS: Number of large read operations=0  
  39.         HDFS: Number of write operations=4  
  40.     Job Counters   
  41.         Launched map tasks=2  
  42.         Data-local map tasks=2  
  43.         Total time spent by all maps in occupied slots (ms)=9617  
  44.         Total time spent by all reduces in occupied slots (ms)=0  
  45.     Map-Reduce Framework  
  46.         Map input records=11  
  47.         Map output records=5  
  48.         Input split bytes=252  
  49.         Spilled Records=0  
  50.         Failed Shuffles=0  
  51.         Merged Map outputs=0  
  52.         GC time elapsed (ms)=53  
  53.         CPU time spent (ms)=2910  
  54.         Physical memory (bytes) snapshot=327467008  
  55.         Virtual memory (bytes) snapshot=1905754112  
  56.         Total committed heap usage (bytes)=402653184  
  57.     File Input Format Counters   
  58.         Bytes Read=541  
  59.     File Output Format Counters   
  60.         Bytes Written=594  
  61. true  

最後附上核心代碼,以做備忘: 
(1)Map Only做業的代碼: 

Java代碼   收藏代碼
  1. package com.dhgate.search.rate.convert;  
  2.   
  3. import java.io.File;  
  4. import java.io.FileInputStream;  
  5. import java.io.FileNotFoundException;  
  6. import java.io.FilenameFilter;  
  7. import java.io.IOException;  
  8. import java.util.Map;  
  9.   
  10. import org.apache.hadoop.conf.Configuration;  
  11. import org.apache.hadoop.fs.FileSystem;  
  12. import org.apache.hadoop.fs.Path;  
  13. import org.apache.hadoop.io.LongWritable;  
  14. import org.apache.hadoop.io.NullWritable;  
  15. import org.apache.hadoop.io.Text;  
  16. import org.apache.hadoop.mapreduce.Job;  
  17. import org.apache.hadoop.mapreduce.Mapper;  
  18. import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;  
  19. import org.apache.hadoop.mapreduce.lib.input.FileSplit;  
  20. import org.apache.hadoop.mapreduce.lib.input.TextInputFormat;  
  21. import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;  
  22. import org.apache.hadoop.mapreduce.lib.output.TextOutputFormat;  
  23. import org.slf4j.Logger;  
  24. import org.slf4j.LoggerFactory;  
  25.   
  26. import com.dhgate.parse.xml.tools.HDFSParseXmlTools;  
  27. import com.sun.xml.bind.v2.schemagen.xmlschema.Import;  
  28.   
  29. /** 
  30.  * 加工處理數據格式 
  31.  *  
  32.  * @author qindongliang 2015年04月07日 
  33.  *  
  34.  * **/  
  35. public class StoreConvert {  
  36.       
  37.     //log4j記錄  
  38.     static Logger log=LoggerFactory.getLogger(StoreConvert.class);  
  39.       
  40.     /** 
  41.      * 轉換支持的格式 
  42.      *  
  43.      * **/  
  44.     private static class FormatMapper extends Mapper<LongWritable, Text, NullWritable, Text>{  
  45.           
  46.         @Override  
  47.         protected void map(LongWritable key, Text value,Context context)throws IOException, InterruptedException {  
  48.               String filename = ((FileSplit) context.getInputSplit()).getPath().getName().split("\\.")[0];  
  49.                 
  50.               //System.out.println("文件名是: "+filename);  
  51.               //log.info("讀取的文件名是: "+filename);  
  52.               String vs[]=value.toString().split(",");  
  53.                 
  54.               if(HDFSParseXmlTools.map.get(filename)!=null){  
  55.                   Map<String, String> m=HDFSParseXmlTools.map.get(filename);  
  56.                   StringBuffer sb=new StringBuffer();  
  57.                   for(int i=0;i<vs.length;i++){  
  58.                       //字段\2值  
  59.                       if(i==vs.length-1){  
  60.                       sb.append(m.get(i+"")).append("\2").append(vs[i]);  
  61.                       }else{  
  62.                       sb.append(m.get(i+"")).append("\2").append(vs[i]).append("\1");  
  63.                         
  64.                       }  
  65.                   }  
  66.                   context.write(NullWritable.get(), new Text(filename+" ==  "+sb.toString()));  
  67.               }  
  68.                 
  69.               
  70.         }  
  71.           
  72.           
  73.           
  74.           
  75.           
  76.     }  
  77.       
  78.        
  79.       
  80.     public static void main(String[] args) throws Exception {  
  81.           
  82.           
  83. //      System.setProperty("HADOOP_USER_NAME", "root");    
  84.             Configuration conf=new Configuration();    
  85.            // getConf(conf);  
  86.             conf.set("mapreduce.job.jar""searchrate.jar");    
  87.             conf.set("fs.defaultFS","hdfs://172.21.50.108:8020");    
  88.             conf.set("mapreduce.framework.name""yarn");      
  89.             conf.set("mapred.remote.os""Linux");  
  90.             conf.set("yarn.resourcemanager.scheduler.address""172.21.50.108:8030");    
  91.             conf.set("yarn.resourcemanager.address""172.21.50.108:8032");  
  92.            // System.exit(0);  
  93.             Job job=Job.getInstance(conf, "formatdata");    
  94.             job.setJarByClass(StoreConvert.class);    
  95.               
  96. //          System.out.println("模式:  "+conf.get("mapreduce.jobtracker.address"));;    
  97.               
  98.               
  99.               
  100.             job.setMapperClass(FormatMapper.class);  
  101.               
  102.             job.setMapOutputKeyClass(Text.class);  
  103.             job.setMapOutputValueClass(Text.class);  
  104.               
  105.             job.setInputFormatClass(TextInputFormat.class);  
  106.             job.setOutputFormatClass(TextOutputFormat.class);  
  107.             job.setNumReduceTasks(0);//Map Only做業  
  108.   
  109.       
  110.            
  111.   
  112.             String path = "/tmp/qin/out";  
  113.             FileSystem fs = FileSystem.get(conf);  
  114.             Path p = new Path(path);  
  115.             if (fs.exists(p)) {  
  116.                 fs.delete(p, true);  
  117.                 System.out.println("輸出路徑存在,已刪除!");  
  118.             }  
  119.             FileInputFormat.setInputPaths(job, "/tmp/qin/testfile/");  
  120.             FileOutputFormat.setOutputPath(job, p);  
  121.               
  122.               
  123.               
  124.               
  125.               
  126.             System.out.println(job.waitForCompletion(true));  
  127.               
  128.               
  129.               
  130.               
  131.               
  132.               
  133.               
  134.               
  135.           
  136.     }  
  137.       
  138.       
  139.   
  140. }  

使用解析HDFS上xml文件的代碼:  
Java代碼   收藏代碼
  1. package com.dhgate.parse.xml.tools;  
  2.   
  3.   
  4.   
  5. import java.io.BufferedReader;  
  6. import java.io.InputStreamReader;  
  7. import java.util.HashMap;  
  8. import java.util.HashSet;  
  9. import java.util.List;  
  10. import java.util.Map;  
  11. import java.util.Map.Entry;  
  12. import java.util.Set;  
  13. import java.util.TreeMap;  
  14.   
  15. import org.apache.hadoop.conf.Configuration;  
  16. import org.apache.hadoop.fs.FileSystem;  
  17. import org.apache.hadoop.fs.Path;  
  18. import org.jsoup.Jsoup;  
  19. import org.jsoup.nodes.Document;  
  20. import org.jsoup.nodes.Element;  
  21. import org.slf4j.Logger;  
  22. import org.slf4j.LoggerFactory;  
  23.   
  24.   
  25. /** 
  26.  * Created by qindongliang on 15-4-6. 
  27.  * 大數據交流羣:415886155 
  28.  */  
  29. public class HDFSParseXmlTools {  
  30.     private final static Logger log= LoggerFactory.getLogger(HDFSParseXmlTools.class);  
  31.     //存儲元數據信息  
  32.     public static Map<String, Map<String, String>> map=new HashMap<String, Map<String,String>>();  
  33.     static Configuration conf=new  Configuration();    
  34.     static FileSystem fs=null;    
  35.      
  36.       
  37.     static{  
  38.             log.info("初始化加載mapping.xml開始.......");  
  39.  try{  
  40.           
  41.        
  42.            conf.set("fs.defaultFS","hdfs://172.21.50.108:8020/");      
  43.            fs=FileSystem.get(conf);//獲取conf對象    
  44.            Path xml =new Path("/tmp/qin/mapping.xml");//讀取HDFS的xml文件  
  45.            BufferedReader br=new BufferedReader(new InputStreamReader(fs.open(xml)));//獲取輸入流  
  46.            StringBuffer sb=new StringBuffer();//聲明一個buffer對象用來存儲xml文件內容  
  47.            String line;  
  48.            line=br.readLine();//讀取第一行  
  49.            sb.append(line);//追加到StringBuffer中  
  50.            while (line != null){  
  51.                    line=br.readLine();//循環讀取  
  52.                    sb.append(line);//循環追加  
  53.            }  
  54. //           System.out.println(sb.toString());  
  55.             br.close();//釋放資源  
  56.             Document d=Jsoup.parse(sb.toString(),"UTF-8");//解析xml  
  57.             Set<String> set=new HashSet<String>();//排除,不須要解析的文件  
  58.             List<Element> excludes=d.select("exclude");  
  59.              for(Element ee:excludes){  
  60.                  set.add(ee.text().trim());  
  61.              }  
  62.               
  63.             List<Element> tables=d.select("type");  
  64.             for(Element t:tables){  
  65.                 String num=t.attr("num");  
  66.                 String name=t.attr("name");  
  67.                 String indexname=t.attr("indexname");  
  68.                 if(set.contains(name)){  
  69.                     log.info("跳過的表名:"+name);  
  70.                     continue;  
  71.                 }  
  72. //                System.out.println(" 序號: "+num+" 表名:  "+name+"   索引名:  "+indexname);  
  73.                 Map<String, String> data=new TreeMap<String, String>();  
  74.                 for(Element s:t.select("map")){  
  75. //                   System.out.println("----------------------"+s.attr("pos")+"  "+s.attr("field")+"  "+s.attr(""));  
  76.                    String pos=s.attr("pos");//位置信息  
  77.                    String field=s.attr("field");//索引字段名  
  78.                    data.put(pos, field);  
  79.                 }  
  80.                 map.put(name, data);//將此表名對應的映射信息存儲到map裏  
  81.             }  
  82.   
  83.  }catch(Exception e){  
  84.      //e.printStackTrace();  
  85.      log.error("加載映射文件異常!",e);  
  86.  }  
  87.   
  88.     }  
  89.   
  90.   
  91.     public static void parseXml()throws Exception{  
  92.           
  93.           
  94.        
  95.   
  96.   
  97.     }  
  98.   
  99.   
  100.   
  101.   
  102.     public static void main(String[] args) throws  Exception{  
  103.         System.out.println();  
  104.         for(Entry<String, Map<String, String>> m:map.entrySet()){  
  105.             System.out.println("表名:"+m.getKey());  
  106. //          for(Entry<String, String> me:m.getValue().entrySet()){  
  107. //              System.out.println(me.getKey()+"         "+me.getValue());  
  108. //          }  
  109.               
  110. //          System.out.println("==================================================");  
  111.         }  
  112.     }  
  113.   
  114.    
  115. }  

項目結構以下圖:  


 

Ant的打包腳本以下:  
Java代碼   收藏代碼
  1. <project name="${component.name}" basedir="." default="jar">  
  2.     <property environment="env"/>  
  3.        
  4.     <!-- <property name="hadoop.home" value="${env.HADOOP_HOME}"/>  -->  
  5.        
  6.     <property name="hadoop.home" value="E:/hadooplib"/>    
  7.     <!-- 指定jar包的名字 -->  
  8.     <property name="jar.name" value="searchrate.jar"/>  
  9.     <path id="project.classpath">  
  10.         <fileset dir="lib">  
  11.             <include name="*.jar" />  
  12.         </fileset>  
  13.         <fileset dir="${hadoop.home}">  
  14.             <include name="**/*.jar" />  
  15.         </fileset>  
  16.     </path>  
  17.     <target name="clean" >  
  18.         <delete dir="bin" failonerror="false" />  
  19.         <mkdir dir="bin"/>  
  20.     </target>   
  21.     <target name="build" depends="clean">  
  22.         <echo message="${ant.project.name}: ${ant.file}"/>  
  23.         <javac destdir="bin" encoding="utf-8" debug="true" includeantruntime="false" debuglevel="lines,vars,source">  
  24.             <src path="src"/>  
  25.             <exclude name="**/.svn" />  
  26.             <classpath refid="project.classpath"/>  
  27.         </javac>  
  28.         <copy todir="bin">  
  29.             <fileset dir="src">  
  30.                 <include name="*config*"/>  
  31.             </fileset>  
  32.         </copy>  
  33.     </target>  
  34.       
  35.     <target name="jar" depends="build">  
  36.         <copy todir="bin/lib">  
  37.             <fileset dir="lib">  
  38.                 <include name="**/*.*"/>  
  39.             </fileset>  
  40.         </copy>  
  41.         <copy todir="bin/lib">  
  42.                     <fileset dir="${hadoop.home}">  
  43.                         <include name="**/*.*"/>  
  44.                     </fileset>  
  45.          </copy>  
  46.           
  47.         <path id="lib-classpath">  
  48.             <fileset dir="lib" includes="**/*.jar" />  
  49.         </path>  
  50.           
  51.         <pathconvert property="my.classpath" pathsep=" " >  
  52.             <mapper>  
  53.                 <chainedmapper>  
  54.                     <!-- 移除絕對路徑 -->  
  55.                     <flattenmapper />  
  56.                     <!-- 加上lib前綴 -->  
  57.                     <globmapper from="*" to="lib/*" />  
  58.                </chainedmapper>  
  59.              </mapper>  
  60.              <path refid="lib-classpath" />  
  61.         </pathconvert>  
  62.           
  63.         <jar basedir="bin" destfile="${jar.name}" >  
  64.             <include name="**/*"/>  
  65.             <!-- define MANIFEST.MF -->  
  66.             <manifest>  
  67.                 <attribute name="Class-Path" value="${my.classpath}" />  
  68.             </manifest>  
  69.         </jar>  
  70.     </target>  
  71. </project>  

至此,咱們以及完成了,這個小項目的開發,最終迴歸當生產環境上,咱們是須要打成jar包,在linux上定時執行的,直接使用linux環境來開發調試hadoop,遇到的問題會更少,雖然不推薦使用win直接開發hadoop程序,可是瞭解一些基本的方法和技巧,對咱們來講也是一件不錯的事情。
相關文章
相關標籤/搜索