zoukankan      html  css  js  c++  java
  • Eclipse调用hadoop2运行MR程序(转)

    hadoop:hadoop2.2 ,windows myeclipse环境;

    Eclipse调用hadoop运行MR程序其实就是普通的java程序可以提交MR任务到集群执行而已。在Hadoop1中,只需指定jt(jobtracker)和fs(namenode)即可,一般如下:

    [java] view plaincopy在CODE上查看代码片派生到我的代码片
     
    1. Configuration conf = new Configuration();  
    2. conf.set("mapred.job.tracker", "192.168.128.138:9001");  
    3. conf.set("fs.default.name","192.168.128.138:9000");  

    上面的代码在hadoop1中运行是ok的,完全可以使用java提交任务到集群运行。但是,hadoop2却是没有了jt,新增了yarn。这个要如何使用呢?最简单的想法,同样指定其配置,试试。

    [java] view plaincopy在CODE上查看代码片派生到我的代码片
     
    1. Configuration conf = new YarnConfiguration();  
    2.               conf.set("fs.defaultFS", "hdfs://node31:9000");  
    3.               conf.set("mapreduce.framework.name", "yarn");  
    4.               conf.set("yarn.resourcemanager.address", "node31:8032");  

    恩,这样配置后,可以运行,首先是下面的错误:

    [html] view plaincopy在CODE上查看代码片派生到我的代码片
     
    1. 2014-04-03 21:20:21,568 ERROR [main] util.Shell (Shell.java:getWinUtilsPath(303)) - Failed to locate the winutils binary in the hadoop binary path  
    2. java.io.IOException: Could not locate executable nullinwinutils.exe in the Hadoop binaries.  
    3.     at org.apache.hadoop.util.Shell.getQualifiedBinPath(Shell.java:278)  
    4.     at org.apache.hadoop.util.Shell.getWinUtilsPath(Shell.java:300)  
    5.     at org.apache.hadoop.util.Shell.<clinit>(Shell.java:293)  
    6.     at org.apache.hadoop.util.StringUtils.<clinit>(StringUtils.java:76)  
    7.     at org.apache.hadoop.yarn.conf.YarnConfiguration.<clinit>(YarnConfiguration.java:345)  
    8.     at org.fansy.hadoop.mr.WordCount.getConf(WordCount.java:104)  
    9.     at org.fansy.hadoop.mr.WordCount.runJob(WordCount.java:84)  
    10.     at org.fansy.hadoop.mr.WordCount.main(WordCount.java:47)  


    这个错误不用管,这个好像是windows调用的时候就会出的错误。

    然后是什么权限问题之类的,这个时候就需要去调整下权限,至少我目前是这样做的。调整的权限主要有/tmp 以及运行wordcount的输入、输出目录。命令如下: $HADOOP_HOME/bin/hadoop fs -chmod -R 777 /tmp 。

    然后直到你出现了下面的错误,那么,好了,可以说你已经成功了一半了。

    [java] view plaincopy在CODE上查看代码片派生到我的代码片
     
    1. 2014-04-03 20:32:36,596 ERROR [main] security.UserGroupInformation (UserGroupInformation.java:doAs(1494)) - PriviledgedActionException as:Administrator (auth:SIMPLE) cause:java.io.IOException: Failed to run job : Application application_1396459813671_0001 failed 2 times due to AM Container for appattempt_1396459813671_0001_000002 exited with  exitCode: 1 due to: Exception from container-launch:   
    2. org.apache.hadoop.util.Shell$ExitCodeException: /bin/bash: line 0: fg: no job control  
    3.   
    4.     at org.apache.hadoop.util.Shell.runCommand(Shell.java:464)  
    5.     at org.apache.hadoop.util.Shell.run(Shell.java:379)  
    6.     at org.apache.hadoop.util.Shell$ShellCommandExecutor.execute(Shell.java:589)  
    7.     at org.apache.hadoop.yarn.server.nodemanager.DefaultContainerExecutor.launchContainer(DefaultContainerExecutor.java:195)  
    8.     at org.apache.hadoop.yarn.server.nodemanager.containermanager.launcher.ContainerLaunch.call(ContainerLaunch.java:283)  
    9.     at org.apache.hadoop.yarn.server.nodemanager.containermanager.launcher.ContainerLaunch.call(ContainerLaunch.java:79)  
    10.     at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:334)  
    11.     at java.util.concurrent.FutureTask.run(FutureTask.java:166)  
    12.     at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)  
    13.     at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)  
    14.     at java.lang.Thread.run(Thread.java:724)  
    15.   
    16.   
    17. .Failing this attempt.. Failing the application.  

    用上面出现的错误去google,可以得到这个网页:https://issues.apache.org/jira/browse/MAPREDUCE-5655 。 恩,对的。这个网页就是我们的solution。

    我们分为1、2、3步骤吧。

    1. 修改MRapps.java 、YARNRunner.java的源码,然后打包替换原来的jar包中的相应class文件,这两个jar我已经打包,可以在这里下载http://download.csdn.net/detail/fansy1990/7143547 。然后替换集群中相应的jar吧,同时需要注意替换Myeclipse中导入的包。额,说起Myeclipse中的jar包,这里还是先上幅jar包的图吧:



    2. 修改mapred-default.xml ,添加:(这个只需在eclipse中导入的jar包修改即可,修改后的jar包不用上传到集群)

    [html] view plaincopy在CODE上查看代码片派生到我的代码片
     
    1. <property>  
    2.     <name>mapred.remote.os</name>  
    3.     <value>Linux</value>  
    4.     <description>  
    5.         Remote MapReduce framework's OS, can be either Linux or Windows  
    6.     </description>  
    7. </property>  

    (题外话,添加了这个属性后,按说我new一个Configuration后,我使用conf.get("mapred.remote.os")的时候应该是可以得到Linux的,但是我得到的却是null,这个就不清楚是怎么了。)

    其文件在:


    这时,你再运行程序,额好吧程序基本可以提交了,但是还是报错,查看log,可以看到下面的错误:

    [html] view plaincopy在CODE上查看代码片派生到我的代码片
     
    1. Error: Could not find or load main class org.apache.hadoop.mapreduce.v2.app.MRAppMaster  

    额,说了这么久,还是把我的wordcount程序贴出来吧:

    [java] view plaincopy在CODE上查看代码片派生到我的代码片
     
    1. package org.fansy.hadoop.mr;  
    2.   
    3. import java.io.IOException;  
    4.   
    5. import org.apache.hadoop.conf.Configuration;  
    6. import org.apache.hadoop.fs.FileSystem;  
    7. import org.apache.hadoop.fs.LocatedFileStatus;  
    8. import org.apache.hadoop.fs.Path;  
    9. import org.apache.hadoop.fs.RemoteIterator;  
    10. import org.apache.hadoop.io.LongWritable;  
    11. import org.apache.hadoop.io.Text;  
    12. import org.apache.hadoop.mapred.ClusterStatus;  
    13. import org.apache.hadoop.mapred.JobClient;  
    14. import org.apache.hadoop.mapreduce.Job;  
    15. import org.apache.hadoop.mapreduce.Mapper;  
    16. import org.apache.hadoop.mapreduce.Reducer;  
    17. import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;  
    18. import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;  
    19. import org.apache.hadoop.yarn.conf.YarnConfiguration;  
    20. import org.slf4j.Logger;  
    21. import org.slf4j.LoggerFactory;  
    22.   
    23. public class WordCount {  
    24.         private static Logger log = LoggerFactory.getLogger(WordCount.class);  
    25.        public static class WCMapper extends  Mapper<LongWritable, Text, LongWritable, Text> {  
    26.             
    27.           public void map(LongWritable key, Text value, Context cxt) throws IOException,InterruptedException {  
    28.           // String[] values= value.toString().split("[,| ]");  
    29.            cxt.write(key, value);  
    30.           }  
    31.        }  
    32.           
    33.         public static class WCReducer extends  Reducer<LongWritable, Text, LongWritable,Text> {  
    34.             public void reduce(LongWritable key, Iterable<Text> values, Context cxt) throws IOException,InterruptedException {  
    35.                 StringBuffer buff = new StringBuffer();  
    36.                 for (Text v:values) {  
    37.                     buff.append(v.toString()+" ");  
    38.                }  
    39.                 cxt.write(key, new Text(buff.toString()));  
    40.             }  
    41.         }  
    42.   
    43.         public static void main(String[] args) throws Exception {  
    44.     //    checkFS();  
    45.           String input ="hdfs://node31:9000/input/test.dat";  
    46.           String output="hdfs://node31:9000/output/wc003";  
    47.             runJob(input,output);  
    48.         //  runJob(args[0],args[1]);  
    49.         //  upload();  
    50.         }  
    51.           
    52.         /** 
    53.          * test operate the hdfs 
    54.          * @throws IOException  
    55.          */  
    56.         public static void checkFS() throws IOException{  
    57.             Configuration conf=getConf();   
    58.             Path f= new Path("/user");  
    59.             FileSystem fs = FileSystem.get(f.toUri(),conf);  
    60.               
    61.             RemoteIterator<LocatedFileStatus> paths=fs.listFiles(f, true);  
    62.             while(paths.hasNext()){  
    63.                 System.out.println(paths.next());  
    64.             }  
    65.               
    66.         }  
    67.           
    68.         public static void upload() throws IOException{  
    69.             Configuration conf = getConf();  
    70.             Path f= new Path("d:\wordcount.jar");  
    71.             FileSystem fs = FileSystem.get(f.toUri(),conf);  
    72.             fs.copyFromLocalFile(true, f, new Path("/input/wordcount.jar"));  
    73.             System.out.println("done ...");  
    74.         }  
    75.           
    76.         /** 
    77.          *  test the job submit 
    78.          * @throws IOException 
    79.          * @throws InterruptedException  
    80.          * @throws ClassNotFoundException  
    81.          */  
    82.         public static void runJob(String input,String output) throws IOException, ClassNotFoundException, InterruptedException{  
    83.               
    84.               Configuration conf=getConf();   
    85.               Job job = new Job(conf,"word count");  
    86.         //    job.setJar("hdfs://node31:9000/input/wordcount.jar");  
    87.               job.setJobName("wordcount");  
    88.               job.setJarByClass(WordCount.class);  
    89.             //  job.setOutputFormatClass(SequenceFileOutputFormat.class);  
    90.               job.setOutputKeyClass(LongWritable.class);  
    91.               job.setOutputValueClass(Text.class);  
    92.       
    93.               job.setMapperClass(WCMapper.class);  
    94.               job.setCombinerClass(WCReducer.class);  
    95.               job.setReducerClass(WCReducer.class);  
    96.       
    97.               FileInputFormat.addInputPath(job, new Path(input));  
    98.             //  SequenceFileOutputFormat.setOutputPath(job, new Path(args[1]));  
    99.               FileOutputFormat.setOutputPath(job, new Path(output));  
    100.               System.exit(job.waitForCompletion(true)?0:1);  
    101.         }  
    102.           
    103.         private static Configuration getConf() throws IOException{  
    104.             Configuration conf = new YarnConfiguration();  
    105.               conf.set("fs.defaultFS", "hdfs://node31:9000");  
    106.               conf.set("mapreduce.framework.name", "yarn");  
    107.               conf.set("yarn.resourcemanager.address", "node31:8032");  
    108.         //    conf.set("mapred.remote.os", "Linux");  
    109.               System.out.println(conf.get("mapred.remote.os"));  
    110.         //    JobClient client = new JobClient(conf);  
    111.         //    ClusterStatus cluster = client.getClusterStatus();  
    112.               return conf;  
    113.         }  
    114. }  


    3. 如何修复上面的报错?按照那个链接的solution,需要修改mapred-default.xml 和yarn-default.xml ,其中mapred-default.xml刚才已经修改过了,这次再次修改,添加:

    [java] view plaincopy在CODE上查看代码片派生到我的代码片
     
    1. <property>  
    2.     <name>mapreduce.application.classpath</name>  
    3.     <value>  
    4.         $HADOOP_CONF_DIR,  
    5.         $HADOOP_COMMON_HOME/share/hadoop/common/*,  
    6.         $HADOOP_COMMON_HOME/share/hadoop/common/lib/*,  
    7.         $HADOOP_HDFS_HOME/share/hadoop/hdfs/*,  
    8.         $HADOOP_HDFS_HOME/share/hadoop/hdfs/lib/*,  
    9.         $HADOOP_MAPRED_HOME/share/hadoop/mapreduce/*,  
    10.         $HADOOP_MAPRED_HOME/share/hadoop/mapreduce/lib/*,  
    11.         $HADOOP_YARN_HOME/share/hadoop/yarn/*,  
    12.         $HADOOP_YARN_HOME/share/hadoop/yarn/lib/*  
    13.     </value>  
    14. </property>  

    对于yarn-default.xml也是同样的修改,其在hadoop-yarn-common-2.2.0.jar包中,修改内容如下:

    [java] view plaincopy在CODE上查看代码片派生到我的代码片
     
    1. <property>  
    2.     <name>mapreduce.application.classpath</name>  
    3.     <value>  
    4.         $HADOOP_CONF_DIR,  
    5.         $HADOOP_COMMON_HOME/share/hadoop/common/*,  
    6.         $HADOOP_COMMON_HOME/share/hadoop/common/lib/*,  
    7.         $HADOOP_HDFS_HOME/share/hadoop/hdfs/*,  
    8.         $HADOOP_HDFS_HOME/share/hadoop/hdfs/lib/*,  
    9.         $HADOOP_MAPRED_HOME/share/hadoop/mapreduce/*,  
    10.         $HADOOP_MAPRED_HOME/share/hadoop/mapreduce/lib/*,  
    11.         $HADOOP_YARN_HOME/share/hadoop/yarn/*,  
    12.         $HADOOP_YARN_HOME/share/hadoop/yarn/lib/*  
    13.     </value>  
    14.   </property>  


    同样的,上面两个jar包只用替换myeclipse中的jar包即可,不需要替换集群中的。

    4. 经过上面的替换,然后再次运行,出现下面的错误:

    [html] view plaincopy在CODE上查看代码片派生到我的代码片
     
    1. Caused by: java.lang.ClassNotFoundException: Class org.fansy.hadoop.mr.WordCount$WCMapper not found  
    2.     at org.apache.hadoop.conf.Configuration.getClassByName(Configuration.java:1626)  
    3.     at org.apache.hadoop.conf.Configuration.getClass(Configuration.java:1718)  
    4.     ... 8 more  

    额,好吧,我应该不用多少了,这样的错误,应该已经说明我们的myeclipse可以提交任务到hadoop2了,并且可以运行了。好吧最后一步,上传我们打包的wordcount程序的jar文件到$HADOOP_HOME/share/hadoop/mapreduce/lib下面,然后再次运行。(这里上传后不用重启集群)呵呵,最后得到下面的结果:

    [html] view plaincopy在CODE上查看代码片派生到我的代码片
     
    1. 2014-04-03 21:17:34,289 ERROR [main] util.Shell (Shell.java:getWinUtilsPath(303)) - Failed to locate the winutils binary in the hadoop binary path  
    2. java.io.IOException: Could not locate executable nullinwinutils.exe in the Hadoop binaries.  
    3.     at org.apache.hadoop.util.Shell.getQualifiedBinPath(Shell.java:278)  
    4.     at org.apache.hadoop.util.Shell.getWinUtilsPath(Shell.java:300)  
    5.     at org.apache.hadoop.util.Shell.<clinit>(Shell.java:293)  
    6.     at org.apache.hadoop.util.StringUtils.<clinit>(StringUtils.java:76)  
    7.     at org.apache.hadoop.yarn.conf.YarnConfiguration.<clinit>(YarnConfiguration.java:345)  
    8.     at org.fansy.hadoop.mr.WordCount.getConf(WordCount.java:104)  
    9.     at org.fansy.hadoop.mr.WordCount.runJob(WordCount.java:84)  
    10.     at org.fansy.hadoop.mr.WordCount.main(WordCount.java:47)  
    11. Linux  
    12. 2014-04-03 21:18:19,853 WARN  [main] util.NativeCodeLoader (NativeCodeLoader.java:<clinit>(62)) - Unable to load native-hadoop library for your platform... using builtin-java classes where applicable  
    13. 2014-04-03 21:18:20,499 INFO  [main] client.RMProxy (RMProxy.java:createRMProxy(56)) - Connecting to ResourceManager at node31/192.168.0.31:8032  
    14. 2014-04-03 21:18:20,973 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.  
    15. 2014-04-03 21:18:21,020 INFO  [main] input.FileInputFormat (FileInputFormat.java:listStatus(287)) - Total input paths to process : 1  
    16. 2014-04-03 21:18:21,313 INFO  [main] mapreduce.JobSubmitter (JobSubmitter.java:submitJobInternal(394)) - number of splits:1  
    17. 2014-04-03 21:18:21,336 INFO  [main] Configuration.deprecation (Configuration.java:warnOnceIfDeprecated(840)) - user.name is deprecated. Instead, use mapreduce.job.user.name  
    18. 2014-04-03 21:18:21,337 INFO  [main] Configuration.deprecation (Configuration.java:warnOnceIfDeprecated(840)) - mapred.jar is deprecated. Instead, use mapreduce.job.jar  
    19. 2014-04-03 21:18:21,337 INFO  [main] Configuration.deprecation (Configuration.java:warnOnceIfDeprecated(840)) - fs.default.name is deprecated. Instead, use fs.defaultFS  
    20. 2014-04-03 21:18:21,338 INFO  [main] Configuration.deprecation (Configuration.java:warnOnceIfDeprecated(840)) - mapred.output.value.class is deprecated. Instead, use mapreduce.job.output.value.class  
    21. 2014-04-03 21:18:21,338 INFO  [main] Configuration.deprecation (Configuration.java:warnOnceIfDeprecated(840)) - mapreduce.combine.class is deprecated. Instead, use mapreduce.job.combine.class  
    22. 2014-04-03 21:18:21,339 INFO  [main] Configuration.deprecation (Configuration.java:warnOnceIfDeprecated(840)) - mapreduce.map.class is deprecated. Instead, use mapreduce.job.map.class  
    23. 2014-04-03 21:18:21,339 INFO  [main] Configuration.deprecation (Configuration.java:warnOnceIfDeprecated(840)) - mapred.job.name is deprecated. Instead, use mapreduce.job.name  
    24. 2014-04-03 21:18:21,339 INFO  [main] Configuration.deprecation (Configuration.java:warnOnceIfDeprecated(840)) - mapreduce.reduce.class is deprecated. Instead, use mapreduce.job.reduce.class  
    25. 2014-04-03 21:18:21,340 INFO  [main] Configuration.deprecation (Configuration.java:warnOnceIfDeprecated(840)) - mapred.input.dir is deprecated. Instead, use mapreduce.input.fileinputformat.inputdir  
    26. 2014-04-03 21:18:21,340 INFO  [main] Configuration.deprecation (Configuration.java:warnOnceIfDeprecated(840)) - mapred.output.dir is deprecated. Instead, use mapreduce.output.fileoutputformat.outputdir  
    27. 2014-04-03 21:18:21,342 INFO  [main] Configuration.deprecation (Configuration.java:warnOnceIfDeprecated(840)) - mapred.map.tasks is deprecated. Instead, use mapreduce.job.maps  
    28. 2014-04-03 21:18:21,343 INFO  [main] Configuration.deprecation (Configuration.java:warnOnceIfDeprecated(840)) - mapred.output.key.class is deprecated. Instead, use mapreduce.job.output.key.class  
    29. 2014-04-03 21:18:21,343 INFO  [main] Configuration.deprecation (Configuration.java:warnOnceIfDeprecated(840)) - mapred.working.dir is deprecated. Instead, use mapreduce.job.working.dir  
    30. 2014-04-03 21:18:21,513 INFO  [main] mapreduce.JobSubmitter (JobSubmitter.java:printTokens(477)) - Submitting tokens for job: job_1396463733942_0003  
    31. 2014-04-03 21:18:21,817 INFO  [main] impl.YarnClientImpl (YarnClientImpl.java:submitApplication(174)) - Submitted application application_1396463733942_0003 to ResourceManager at node31/192.168.0.31:8032  
    32. 2014-04-03 21:18:21,859 INFO  [main] mapreduce.Job (Job.java:submit(1272)) - The url to track the job: http://node31:8088/proxy/application_1396463733942_0003/  
    33. 2014-04-03 21:18:21,860 INFO  [main] mapreduce.Job (Job.java:monitorAndPrintJob(1317)) - Running job: job_1396463733942_0003  
    34. 2014-04-03 21:18:31,307 INFO  [main] mapreduce.Job (Job.java:monitorAndPrintJob(1338)) - Job job_1396463733942_0003 running in uber mode : false  
    35. 2014-04-03 21:18:31,311 INFO  [main] mapreduce.Job (Job.java:monitorAndPrintJob(1345)) -  map 0% reduce 0%  
    36. 2014-04-03 21:19:02,346 INFO  [main] mapreduce.Job (Job.java:monitorAndPrintJob(1345)) -  map 100% reduce 0%  
    37. 2014-04-03 21:19:11,416 INFO  [main] mapreduce.Job (Job.java:monitorAndPrintJob(1345)) -  map 100% reduce 100%  
    38. 2014-04-03 21:19:11,425 INFO  [main] mapreduce.Job (Job.java:monitorAndPrintJob(1356)) - Job job_1396463733942_0003 completed successfully  
    39. 2014-04-03 21:19:11,552 INFO  [main] mapreduce.Job (Job.java:monitorAndPrintJob(1363)) - Counters: 43  
    40.     File System Counters  
    41.         FILE: Number of bytes read=11139  
    42.         FILE: Number of bytes written=182249  
    43.         FILE: Number of read operations=0  
    44.         FILE: Number of large read operations=0  
    45.         FILE: Number of write operations=0  
    46.         HDFS: Number of bytes read=8646  
    47.         HDFS: Number of bytes written=10161  
    48.         HDFS: Number of read operations=6  
    49.         HDFS: Number of large read operations=0  
    50.         HDFS: Number of write operations=2  
    51.     Job Counters   
    52.         Launched map tasks=1  
    53.         Launched reduce tasks=1  
    54.         Data-local map tasks=1  
    55.         Total time spent by all maps in occupied slots (ms)=29330  
    56.         Total time spent by all reduces in occupied slots (ms)=5825  
    57.     Map-Reduce Framework  
    58.         Map input records=235  
    59.         Map output records=235  
    60.         Map output bytes=10428  
    61.         Map output materialized bytes=11139  
    62.         Input split bytes=98  
    63.         Combine input records=235  
    64.         Combine output records=235  
    65.         Reduce input groups=235  
    66.         Reduce shuffle bytes=11139  
    67.         Reduce input records=235  
    68.         Reduce output records=235  
    69.         Spilled Records=470  
    70.         Shuffled Maps =1  
    71.         Failed Shuffles=0  
    72.         Merged Map outputs=1  
    73.         GC time elapsed (ms)=124  
    74.         CPU time spent (ms)=21920  
    75.         Physical memory (bytes) snapshot=299376640  
    76.         Virtual memory (bytes) snapshot=1671372800  
    77.         Total committed heap usage (bytes)=152834048  
    78.     Shuffle Errors  
    79.         BAD_ID=0  
    80.         CONNECTION=0  
    81.         IO_ERROR=0  
    82.         WRONG_LENGTH=0  
    83.         WRONG_MAP=0  
    84.         WRONG_REDUCE=0  
    85.     File Input Format Counters   
    86.         Bytes Read=8548  
    87.     File Output Format Counters   
    88.         Bytes Written=10161  

    上面你看到Linux,是因为我使用了conf.set("mapred.remote.os", "Linux"); 不过在实际运行的时候却不需要设置。

    另外,如果是linux系统部署的tomcat调用hadoop2集群运行MR程序的话,应该不需要替换其jar吧的,这个还有待验证。

    哈,总算搞定了。这个问题也算是困扰了我好久了,期间几次想要冲破,结果都是无果而归,甚是郁闷。额,其实这个也不算是原创了,哎,国外在02/Dec/13 18:35这个时间点就搞定了。不过,我搜了好久,都没有中文的相关介绍。(如果有的话,那就是我搜索能力的问题了,居然没有搜到,哎)。

    分享,成长,快乐

    转载请注明blog地址:http://blog.csdn.net/fansy1990

  • 相关阅读:
    UVa 10474
    UVa 1339
    UVa 1368
    UVa 1585
    UVa 1586
    ACM中Java高效输入输出封装
    Ajax中Get请求与Post请求的区别
    AJAX——核心XMLHttpRequest对象
    PHP面向对象编程之深入理解方法重载与方法覆盖(多态)
    PHP类方法重写原则
  • 原文地址:https://www.cnblogs.com/sha0830/p/5061898.html
Copyright © 2011-2022 走看看