job源码分析_new jobconf-程序员宅基地

  1. /** 
  2.  * Licensed to the Apache Software Foundation (ASF) under one 
  3.  * or more contributor license agreements.  See the NOTICE file 
  4.  * distributed with this work for additional information 
  5.  * regarding copyright ownership.  The ASF licenses this file 
  6.  * to you under the Apache License, Version 2.0 (the 
  7.  * "License"); you may not use this file except in compliance 
  8.  * with the License.  You may obtain a copy of the License at 
  9.  * 
  10.  *     http://www.apache.org/licenses/LICENSE-2.0 
  11.  * 
  12.  * Unless required by applicable law or agreed to in writing, software 
  13.  * distributed under the License is distributed on an "AS IS" BASIS, 
  14.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
  15.  * See the License for the specific language governing permissions and 
  16.  * limitations under the License. 
  17.  */  
  18.   
  19. package org.apache.hadoop.mapreduce;  
  20.   
  21. import java.io.IOException;  
  22. import java.security.PrivilegedExceptionAction;  
  23.   
  24. import org.apache.hadoop.conf.Configuration;  
  25. import org.apache.hadoop.fs.Path;  
  26. import org.apache.hadoop.io.RawComparator;  
  27. import org.apache.hadoop.mapreduce.TaskAttemptID;  
  28. import org.apache.hadoop.mapred.JobClient;  
  29. import org.apache.hadoop.mapred.JobConf;  
  30. import org.apache.hadoop.mapred.RunningJob;  
  31. import org.apache.hadoop.mapred.TaskCompletionEvent;  
  32.   
  33. /** 
  34.  * The job submitter's view of the Job. It allows the user to configure the 
  35.  * job, submit it, control its execution, and query the state. The set methods 
  36.  * only work until the job is submitted, afterwards they will throw an  
  37.  * IllegalStateException. 
  38.  * job 提交者看到的job的视图。它允许用户配置job,提交job,控制job的执行,并且查询他的状态 
  39.  * set方法只有在job提交的时候才会工作 
  40.  */  
  41. public class Job extends JobContext {    
  42.   public static enum JobState {DEFINE, RUNNING};//job的状态,有定义好的和正在运行  
  43.   private JobState state = JobState.DEFINE;  
  44.   private JobClient jobClient;  
  45.   private RunningJob info;  
  46.   
  47.   /** 
  48.    * Creates a new {@link Job} 
  49.    * A Job will be created with a generic {@link Configuration}. 
  50.    *创建一个新的job,用通用的configuration 
  51.    * @return the {@link Job} 
  52.    * @throws IOException 
  53.    */  
  54.   public static Job getInstance() throws IOException {  
  55.     // create with a null Cluster  
  56.     return getInstance(new Configuration());  
  57.   }  
  58.   
  59.   /** 
  60.    * Creates a new {@link Job} with a given {@link Configuration}. 
  61.    * The <code>Job</code> makes a copy of the <code>Configuration</code> so 
  62.    * that any necessary internal modifications do not reflect on the incoming 
  63.    * parameter. 
  64.    *使用给定的configuration创建job 
  65.    *这里对configuration进行了备份,如此,任何必要的对configuration内部修改,都不会影响传进来的conf参数 
  66.    * @param conf the {@link Configuration} 
  67.    * @return the {@link Job} 
  68.    * @throws IOException 
  69.    */  
  70.   public static Job getInstance(Configuration conf) throws IOException {  
  71.     // create with a null Cluster 没有任何集群的创建  
  72.     JobConf jobConf = new JobConf(conf);  
  73.     return new Job(jobConf);  
  74.   }  
  75.   
  76.   /** 
  77.    * Creates a new {@link Job} with a given {@link Configuration} 
  78.    * and a given jobName. 
  79.    *用给定的conf和jobname 
  80.    * The <code>Job</code> makes a copy of the <code>Configuration</code> so 
  81.    * that any necessary internal modifications do not reflect on the incoming 
  82.    * parameter. 
  83.    * 
  84.    * @param conf the {@link Configuration} 
  85.    * @param jobName the job instance's name 
  86.    * @return the {@link Job} 
  87.    * @throws IOException 
  88.    */  
  89.   public static Job getInstance(Configuration conf, String jobName)  
  90.            throws IOException {  
  91.     // create with a null Cluster  
  92.     Job result = getInstance(conf);  
  93.     result.setJobName(jobName);  
  94.     return result;  
  95.   }  
  96.   
  97.   public Job() throws IOException {  
  98.     this(new Configuration());  
  99.   }  
  100.   
  101.   public Job(Configuration conf) throws IOException {  
  102.     super(conf, null);  
  103.   }  
  104.   
  105.   public Job(Configuration conf, String jobName) throws IOException {  
  106.     this(conf);  
  107.     setJobName(jobName);  
  108.   }  
  109.   
  110.   JobClient getJobClient() {  
  111.     return jobClient;  
  112.   }  
  113.     
  114.   //确保job的状态  
  115.   private void ensureState(JobState state) throws IllegalStateException {  
  116.     if (state != this.state) {  
  117.       throw new IllegalStateException("Job in state "+ this.state +   
  118.                                       " instead of " + state);  
  119.     }  
  120.   
  121.     if (state == JobState.RUNNING && jobClient == null) {  
  122.       throw new IllegalStateException("Job in state " + JobState.RUNNING +   
  123.                                       " however jobClient is not initialized!");  
  124.     }  
  125.   }  
  126.   
  127.   /** 
  128.    * Set the number of reduce tasks for the job. 
  129.    * 设置reducer的个数 常用 
  130.    * @param tasks the number of reduce tasks 
  131.    * @throws IllegalStateException if the job is submitted 
  132.    */  
  133.   public void setNumReduceTasks(int tasks) throws IllegalStateException {  
  134.     ensureState(JobState.DEFINE);  
  135.     conf.setNumReduceTasks(tasks);  
  136.   }  
  137.   
  138.   /** 
  139.    * Set the current working directory for the default file system. 
  140.    * 为默认文件系统 设置当前工作目录 
  141.    * @param dir the new current working directory. 
  142.    * @throws IllegalStateException if the job is submitted 
  143.    */  
  144.   public void setWorkingDirectory(Path dir) throws IOException {  
  145.     ensureState(JobState.DEFINE);  
  146.     conf.setWorkingDirectory(dir);  
  147.   }  
  148.   
  149.   /** 
  150.    * Set the {@link InputFormat} for the job. 
  151.    * @param cls the <code>InputFormat</code> to use 
  152.    * @throws IllegalStateException if the job is submitted 
  153.    */  
  154.   public void setInputFormatClass(Class<? extends InputFormat> cls  
  155.                                   ) throws IllegalStateException {  
  156.     ensureState(JobState.DEFINE);  
  157.     conf.setClass(INPUT_FORMAT_CLASS_ATTR, cls, InputFormat.class);  
  158.   }  
  159.   
  160.   /** 
  161.    * Set the {@link OutputFormat} for the job. 
  162.    * @param cls the <code>OutputFormat</code> to use 
  163.    * @throws IllegalStateException if the job is submitted 
  164.    */  
  165.   public void setOutputFormatClass(Class<? extends OutputFormat> cls  
  166.                                    ) throws IllegalStateException {  
  167.     ensureState(JobState.DEFINE);  
  168.     conf.setClass(OUTPUT_FORMAT_CLASS_ATTR, cls, OutputFormat.class);  
  169.   }  
  170.   
  171.   /** 
  172.    * Set the {@link Mapper} for the job. 
  173.    * @param cls the <code>Mapper</code> to use 
  174.    * @throws IllegalStateException if the job is submitted 
  175.    */  
  176.   public void setMapperClass(Class<? extends Mapper> cls  
  177.                              ) throws IllegalStateException {  
  178.     ensureState(JobState.DEFINE);  
  179.     conf.setClass(MAP_CLASS_ATTR, cls, Mapper.class);  
  180.   }  
  181.   
  182.   /** 
  183.    * Set the Jar by finding where a given class came from. 
  184.    * 设置jar包,hadoop根据给定的class来寻找他的jar包 
  185.    * @param cls the example class 
  186.    */  
  187.   public void setJarByClass(Class<?> cls) {  
  188.     conf.setJarByClass(cls);  
  189.   }  
  190.     
  191.   /** 
  192.    * Get the pathname of the job's jar. 
  193.    * @return the pathname 
  194.    */  
  195.   public String getJar() {  
  196.     return conf.getJar();  
  197.   }  
  198.   
  199.   /** 
  200.    * Set the combiner class for the job. 
  201.    * @param cls the combiner to use 
  202.    * @throws IllegalStateException if the job is submitted 
  203.    */  
  204.   public void setCombinerClass(Class<? extends Reducer> cls  
  205.                                ) throws IllegalStateException {  
  206.     ensureState(JobState.DEFINE);  
  207.     conf.setClass(COMBINE_CLASS_ATTR, cls, Reducer.class);  
  208.   }  
  209.   
  210.   /** 
  211.    * Set the {@link Reducer} for the job. 
  212.    * @param cls the <code>Reducer</code> to use 
  213.    * @throws IllegalStateException if the job is submitted 
  214.    */  
  215.   public void setReducerClass(Class<? extends Reducer> cls  
  216.                               ) throws IllegalStateException {  
  217.     ensureState(JobState.DEFINE);  
  218.     conf.setClass(REDUCE_CLASS_ATTR, cls, Reducer.class);  
  219.   }  
  220.   
  221.   /** 
  222.    * Set the {@link Partitioner} for the job. 
  223.    * @param cls the <code>Partitioner</code> to use 
  224.    * @throws IllegalStateException if the job is submitted 
  225.    */  
  226.   public void setPartitionerClass(Class<? extends Partitioner> cls  
  227.                                   ) throws IllegalStateException {  
  228.     ensureState(JobState.DEFINE);  
  229.     conf.setClass(PARTITIONER_CLASS_ATTR, cls, Partitioner.class);  
  230.   }  
  231.   
  232.   /** 
  233.    * Set the key class for the map output data. This allows the user to 
  234.    * specify the map output key class to be different than the final output 
  235.    * value class. 
  236.    *  
  237.    * @param theClass the map output key class. 
  238.    * @throws IllegalStateException if the job is submitted 
  239.    */  
  240.   public void setMapOutputKeyClass(Class<?> theClass  
  241.                                    ) throws IllegalStateException {  
  242.     ensureState(JobState.DEFINE);  
  243.     conf.setMapOutputKeyClass(theClass);  
  244.   }  
  245.   
  246.   /** 
  247.    * Set the value class for the map output data. This allows the user to 
  248.    * specify the map output value class to be different than the final output 
  249.    * value class. 
  250.    *  
  251.    * @param theClass the map output value class. 
  252.    * @throws IllegalStateException if the job is submitted 
  253.    */  
  254.   public void setMapOutputValueClass(Class<?> theClass  
  255.                                      ) throws IllegalStateException {  
  256.     ensureState(JobState.DEFINE);  
  257.     conf.setMapOutputValueClass(theClass);  
  258.   }  
  259.   
  260.   /** 
  261.    * Set the key class for the job output data. 
  262.    *  
  263.    * @param theClass the key class for the job output data. 
  264.    * @throws IllegalStateException if the job is submitted 
  265.    */  
  266.   public void setOutputKeyClass(Class<?> theClass  
  267.                                 ) throws IllegalStateException {  
  268.     ensureState(JobState.DEFINE);  
  269.     conf.setOutputKeyClass(theClass);  
  270.   }  
  271.   
  272.   /** 
  273.    * Set the value class for job outputs. 
  274.    *  
  275.    * @param theClass the value class for job outputs. 
  276.    * @throws IllegalStateException if the job is submitted 
  277.    */  
  278.   public void setOutputValueClass(Class<?> theClass  
  279.                                   ) throws IllegalStateException {  
  280.     ensureState(JobState.DEFINE);  
  281.     conf.setOutputValueClass(theClass);  
  282.   }  
  283.   
  284.   /** 
  285.    * Define the comparator that controls how the keys are sorted before they 
  286.    * are passed to the {@link Reducer}. 
  287.    * @param cls the raw comparator 
  288.    * @throws IllegalStateException if the job is submitted 
  289.    */  
  290.   public void setSortComparatorClass(Class<? extends RawComparator> cls  
  291.                                      ) throws IllegalStateException {  
  292.     ensureState(JobState.DEFINE);  
  293.     conf.setOutputKeyComparatorClass(cls);  
  294.   }  
  295.   
  296.   /** 
  297.    * Define the comparator that controls which keys are grouped together 
  298.    * for a single call to  
  299.    * {@link Reducer#reduce(Object, Iterable,  
  300.    *                       org.apache.hadoop.mapreduce.Reducer.Context)} 
  301.    * @param cls the raw comparator to use 
  302.    * @throws IllegalStateException if the job is submitted 
  303.    */  
  304.   public void setGroupingComparatorClass(Class<? extends RawComparator> cls  
  305.                                          ) throws IllegalStateException {  
  306.     ensureState(JobState.DEFINE);  
  307.     conf.setOutputValueGroupingComparator(cls);  
  308.   }  
  309.   
  310.   /** 
  311.    * Set the user-specified job name. 
  312.    *  
  313.    * @param name the job's new name. 
  314.    * @throws IllegalStateException if the job is submitted 
  315.    */  
  316.   public void setJobName(String name) throws IllegalStateException {  
  317.     ensureState(JobState.DEFINE);  
  318.     conf.setJobName(name);  
  319.   }  
  320.     
  321.   /** 
  322.    * Turn speculative execution on or off for this job.  
  323.    * 设置推测执行的开关 
  324.    * @param speculativeExecution <code>true</code> if speculative execution  
  325.    *                             should be turned on, else <code>false</code>. 
  326.    */  
  327.   public void setSpeculativeExecution(boolean speculativeExecution) {  
  328.     ensureState(JobState.DEFINE);  
  329.     conf.setSpeculativeExecution(speculativeExecution);  
  330.   }  
  331.   
  332.   /** 
  333.    * Turn speculative execution on or off for this job for map tasks.  
  334.    *  
  335.    * @param speculativeExecution <code>true</code> if speculative execution  
  336.    *                             should be turned on for map tasks, 
  337.    *                             else <code>false</code>. 
  338.    */  
  339.   public void setMapSpeculativeExecution(boolean speculativeExecution) {  
  340.     ensureState(JobState.DEFINE);  
  341.     conf.setMapSpeculativeExecution(speculativeExecution);  
  342.   }  
  343.   
  344.   /** 
  345.    * Turn speculative execution on or off for this job for reduce tasks.  
  346.    *  
  347.    * @param speculativeExecution <code>true</code> if speculative execution  
  348.    *                             should be turned on for reduce tasks, 
  349.    *                             else <code>false</code>. 
  350.    */  
  351.   public void setReduceSpeculativeExecution(boolean speculativeExecution) {  
  352.     ensureState(JobState.DEFINE);  
  353.     conf.setReduceSpeculativeExecution(speculativeExecution);  
  354.   }  
  355.   
  356.   /** 
  357.    * Get the URL where some job progress information will be displayed. 
  358.    * 得到 一些job 进度信息会展示的url地址 
  359.    * @return the URL where some job progress information will be displayed. 
  360.    */  
  361.   public String getTrackingURL() {  
  362.     ensureState(JobState.RUNNING);  
  363.     return info.getTrackingURL();  
  364.   }  
  365.   
  366.   /** 
  367.    * Get the <i>progress</i> of the job's setup, as a float between 0.0  
  368.    * and 1.0.  When the job setup is completed, the function returns 1.0. 
  369.    *  
  370.    * @return the progress of the job's setup. 
  371.    * @throws IOException 
  372.    */  
  373.   public float setupProgress() throws IOException {  
  374.     ensureState(JobState.RUNNING);  
  375.     return info.setupProgress();  
  376.   }  
  377.   
  378.   /** 
  379.    * Get the <i>progress</i> of the job's map-tasks, as a float between 0.0  
  380.    * and 1.0.  When all map tasks have completed, the function returns 1.0. 
  381.    *  
  382.    * @return the progress of the job's map-tasks. 
  383.    * @throws IOException 
  384.    */  
  385.   public float mapProgress() throws IOException {  
  386.     ensureState(JobState.RUNNING);  
  387.     return info.mapProgress();  
  388.   }  
  389.   
  390.   /** 
  391.    * Get the <i>progress</i> of the job's reduce-tasks, as a float between 0.0  
  392.    * and 1.0.  When all reduce tasks have completed, the function returns 1.0. 
  393.    *  
  394.    * @return the progress of the job's reduce-tasks. 
  395.    * @throws IOException 
  396.    */  
  397.   public float reduceProgress() throws IOException {  
  398.     ensureState(JobState.RUNNING);  
  399.     return info.reduceProgress();  
  400.   }  
  401.   
  402.   /** 
  403.    * Check if the job is finished or not.  
  404.    * This is a non-blocking call. 
  405.    *  
  406.    * @return <code>true</code> if the job is complete, else <code>false</code>. 
  407.    * @throws IOException 
  408.    */  
  409.   public boolean isComplete() throws IOException {  
  410.     ensureState(JobState.RUNNING);  
  411.     return info.isComplete();  
  412.   }  
  413.   
  414.   /** 
  415.    * Check if the job completed successfully.  
  416.    *  
  417.    * @return <code>true</code> if the job succeeded, else <code>false</code>. 
  418.    * @throws IOException 
  419.    */  
  420.   public boolean isSuccessful() throws IOException {  
  421.     ensureState(JobState.RUNNING);  
  422.     return info.isSuccessful();  
  423.   }  
  424.   
  425.   /** 
  426.    * Kill the running job.  Blocks until all job tasks have been 
  427.    * killed as well.  If the job is no longer running, it simply returns. 
  428.    * 杀掉正在运行的job 直到所有的job tasks都被杀掉之后 才会停止。 
  429.    * 如果job不再运行来 他就会返回 
  430.    * @throws IOException 
  431.    */  
  432.   public void killJob() throws IOException {  
  433.     ensureState(JobState.RUNNING);  
  434.     info.killJob();  
  435.   }  
  436.       
  437.   /** 
  438.    * Get events indicating completion (success/failure) of component tasks. 
  439.    *   
  440.    * @param startFrom index to start fetching events from 
  441.    * @return an array of {@link TaskCompletionEvent}s 
  442.    * @throws IOException 
  443.    */  
  444.   public TaskCompletionEvent[] getTaskCompletionEvents(int startFrom  
  445.                                                        ) throws IOException {  
  446.     ensureState(JobState.RUNNING);  
  447.     return info.getTaskCompletionEvents(startFrom);  
  448.   }  
  449.     
  450.   /** 
  451.    * Kill indicated task attempt. 
  452.    *  
  453.    * @param taskId the id of the task to be terminated. 
  454.    * @throws IOException 
  455.    */  
  456.   public void killTask(TaskAttemptID taskId) throws IOException {  
  457.     ensureState(JobState.RUNNING);  
  458.     info.killTask(org.apache.hadoop.mapred.TaskAttemptID.downgrade(taskId),   
  459.                   false);  
  460.   }  
  461.   
  462.   /** 
  463.    * Fail indicated task attempt. 
  464.    *  
  465.    * @param taskId the id of the task to be terminated. 
  466.    * @throws IOException 
  467.    */  
  468.   public void failTask(TaskAttemptID taskId) throws IOException {  
  469.     ensureState(JobState.RUNNING);  
  470.     info.killTask(org.apache.hadoop.mapred.TaskAttemptID.downgrade(taskId),   
  471.                   true);  
  472.   }  
  473.   
  474.   /** 
  475.    * Gets the counters for this job. 
  476.    *  
  477.    * @return the counters for this job. 
  478.    * @throws IOException 
  479.    */  
  480.   public Counters getCounters() throws IOException {  
  481.     ensureState(JobState.RUNNING);  
  482.     return new Counters(info.getCounters());  
  483.   }  
  484.   
  485.   private void ensureNotSet(String attr, String msg) throws IOException {  
  486.     if (conf.get(attr) != null) {  
  487.       throw new IOException(attr + " is incompatible with " + msg + " mode.");  
  488.     }      
  489.   }  
  490.     
  491.   /** 
  492.    * Sets the flag that will allow the JobTracker to cancel the HDFS delegation 
  493.    * tokens upon job completion. Defaults to true. 
  494.    */  
  495.   public void setCancelDelegationTokenUponJobCompletion(boolean value) {  
  496.     ensureState(JobState.DEFINE);  
  497.     conf.setBoolean(JOB_CANCEL_DELEGATION_TOKEN, value);  
  498.   }  
  499.   
  500.   /** 
  501.    * Default to the new APIs unless they are explicitly set or the old mapper or 
  502.    * reduce attributes are used. 
  503.    * @throws IOException if the configuration is inconsistant 
  504.    */  
  505.   private void setUseNewAPI() throws IOException {  
  506.     int numReduces = conf.getNumReduceTasks();  
  507.     String oldMapperClass = "mapred.mapper.class";  
  508.     String oldReduceClass = "mapred.reducer.class";  
  509.     conf.setBooleanIfUnset("mapred.mapper.new-api",  
  510.                            conf.get(oldMapperClass) == null);  
  511.     if (conf.getUseNewMapper()) {  
  512.       String mode = "new map API";  
  513.       ensureNotSet("mapred.input.format.class", mode);  
  514.       ensureNotSet(oldMapperClass, mode);  
  515.       if (numReduces != 0) {  
  516.         ensureNotSet("mapred.partitioner.class", mode);  
  517.        } else {  
  518.         ensureNotSet("mapred.output.format.class", mode);  
  519.       }        
  520.     } else {  
  521.       String mode = "map compatability";  
  522.       ensureNotSet(JobContext.INPUT_FORMAT_CLASS_ATTR, mode);  
  523.       ensureNotSet(JobContext.MAP_CLASS_ATTR, mode);  
  524.       if (numReduces != 0) {  
  525.         ensureNotSet(JobContext.PARTITIONER_CLASS_ATTR, mode);  
  526.        } else {  
  527.         ensureNotSet(JobContext.OUTPUT_FORMAT_CLASS_ATTR, mode);  
  528.       }  
  529.     }  
  530.     if (numReduces != 0) {  
  531.       conf.setBooleanIfUnset("mapred.reducer.new-api",  
  532.                              conf.get(oldReduceClass) == null);  
  533.       if (conf.getUseNewReducer()) {  
  534.         String mode = "new reduce API";  
  535.         ensureNotSet("mapred.output.format.class", mode);  
  536.         ensureNotSet(oldReduceClass, mode);     
  537.       } else {  
  538.         String mode = "reduce compatability";  
  539.         ensureNotSet(JobContext.OUTPUT_FORMAT_CLASS_ATTR, mode);  
  540.         ensureNotSet(JobContext.REDUCE_CLASS_ATTR, mode);     
  541.       }  
  542.     }     
  543.   }  
  544.   
  545.   /** 
  546.    * Submit the job to the cluster and return immediately. 
  547.    * 提交job到集群上面 并且立刻返回 
  548.    * @throws IOException 
  549.    */  
  550.   public void submit() throws IOException, InterruptedException,   
  551.                               ClassNotFoundException {  
  552.     ensureState(JobState.DEFINE);  
  553.     setUseNewAPI();  
  554.       
  555.     // Connect to the JobTracker and submit the job  
  556.     //连接到jobtracker 并且提交作业  
  557.     connect();  
  558.     info = jobClient.submitJobInternal(conf);//这里才真正的提交作业  
  559.     super.setJobID(info.getID());  
  560.     state = JobState.RUNNING;  
  561.    }  
  562.     
  563.   /** 
  564.    * Open a connection to the JobTracker 
  565.    * 打开到jobtracker的连接 
  566.    * @throws IOException 
  567.    * @throws InterruptedException  
  568.    */  
  569.   private void connect() throws IOException, InterruptedException {  
  570.     ugi.doAs(new PrivilegedExceptionAction<Object>() {  
  571.       public Object run() throws IOException {  
  572.         jobClient = new JobClient((JobConf) getConfiguration());      
  573.         return null;  
  574.       }  
  575.     });  
  576.   }  
  577.     
  578.   /** 
  579.    * Submit the job to the cluster and wait for it to finish. 
  580.    * @param verbose print the progress to the user 
  581.    * @return true if the job succeeded 
  582.    * @throws IOException thrown if the communication with the  
  583.    *         <code>JobTracker</code> is lost 
  584.    */  
  585.   public boolean waitForCompletion(boolean verbose  
  586.                                    ) throws IOException, InterruptedException,  
  587.                                             ClassNotFoundException {  
  588.     if (state == JobState.DEFINE) {  
  589.       submit();  
  590.     }  
  591.     if (verbose) {  
  592.       jobClient.monitorAndPrintJob(conf, info);  
  593.     } else {  
  594.       info.waitForCompletion();  
  595.     }  
  596.     return isSuccessful();  
  597.   }  
  598.     
  599. }  
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/jiaxinhong/article/details/82826232

智能推荐

使用nginx解决浏览器跨域问题_nginx不停的xhr-程序员宅基地

文章浏览阅读1k次。通过使用ajax方法跨域请求是浏览器所不允许的,浏览器出于安全考虑是禁止的。警告信息如下:不过jQuery对跨域问题也有解决方案,使用jsonp的方式解决,方法如下:$.ajax({ async:false, url: 'http://www.mysite.com/demo.do', // 跨域URL ty..._nginx不停的xhr

在 Oracle 中配置 extproc 以访问 ST_Geometry-程序员宅基地

文章浏览阅读2k次。关于在 Oracle 中配置 extproc 以访问 ST_Geometry,也就是我们所说的 使用空间SQL 的方法,官方文档链接如下。http://desktop.arcgis.com/zh-cn/arcmap/latest/manage-data/gdbs-in-oracle/configure-oracle-extproc.htm其实简单总结一下,主要就分为以下几个步骤。..._extproc

Linux C++ gbk转为utf-8_linux c++ gbk->utf8-程序员宅基地

文章浏览阅读1.5w次。linux下没有上面的两个函数,需要使用函数 mbstowcs和wcstombsmbstowcs将多字节编码转换为宽字节编码wcstombs将宽字节编码转换为多字节编码这两个函数,转换过程中受到系统编码类型的影响,需要通过设置来设定转换前和转换后的编码类型。通过函数setlocale进行系统编码的设置。linux下输入命名locale -a查看系统支持的编码_linux c++ gbk->utf8

IMP-00009: 导出文件异常结束-程序员宅基地

文章浏览阅读750次。今天准备从生产库向测试库进行数据导入,结果在imp导入的时候遇到“ IMP-00009:导出文件异常结束” 错误,google一下,发现可能有如下原因导致imp的数据太大,没有写buffer和commit两个数据库字符集不同从低版本exp的dmp文件,向高版本imp导出的dmp文件出错传输dmp文件时,文件损坏解决办法:imp时指定..._imp-00009导出文件异常结束

python程序员需要深入掌握的技能_Python用数据说明程序员需要掌握的技能-程序员宅基地

文章浏览阅读143次。当下是一个大数据的时代,各个行业都离不开数据的支持。因此,网络爬虫就应运而生。网络爬虫当下最为火热的是Python,Python开发爬虫相对简单,而且功能库相当完善,力压众多开发语言。本次教程我们爬取前程无忧的招聘信息来分析Python程序员需要掌握那些编程技术。首先在谷歌浏览器打开前程无忧的首页,按F12打开浏览器的开发者工具。浏览器开发者工具是用于捕捉网站的请求信息,通过分析请求信息可以了解请..._初级python程序员能力要求

Spring @Service生成bean名称的规则(当类的名字是以两个或以上的大写字母开头的话,bean的名字会与类名保持一致)_@service beanname-程序员宅基地

文章浏览阅读7.6k次,点赞2次,收藏6次。@Service标注的bean,类名:ABDemoService查看源码后发现,原来是经过一个特殊处理:当类的名字是以两个或以上的大写字母开头的话,bean的名字会与类名保持一致public class AnnotationBeanNameGenerator implements BeanNameGenerator { private static final String C..._@service beanname

随便推点

二叉树的各种创建方法_二叉树的建立-程序员宅基地

文章浏览阅读6.9w次,点赞73次,收藏463次。1.前序创建#include&lt;stdio.h&gt;#include&lt;string.h&gt;#include&lt;stdlib.h&gt;#include&lt;malloc.h&gt;#include&lt;iostream&gt;#include&lt;stack&gt;#include&lt;queue&gt;using namespace std;typed_二叉树的建立

解决asp.net导出excel时中文文件名乱码_asp.net utf8 导出中文字符乱码-程序员宅基地

文章浏览阅读7.1k次。在Asp.net上使用Excel导出功能,如果文件名出现中文,便会以乱码视之。 解决方法: fileName = HttpUtility.UrlEncode(fileName, System.Text.Encoding.UTF8);_asp.net utf8 导出中文字符乱码

笔记-编译原理-实验一-词法分析器设计_对pl/0作以下修改扩充。增加单词-程序员宅基地

文章浏览阅读2.1k次,点赞4次,收藏23次。第一次实验 词法分析实验报告设计思想词法分析的主要任务是根据文法的词汇表以及对应约定的编码进行一定的识别,找出文件中所有的合法的单词,并给出一定的信息作为最后的结果,用于后续语法分析程序的使用;本实验针对 PL/0 语言 的文法、词汇表编写一个词法分析程序,对于每个单词根据词汇表输出: (单词种类, 单词的值) 二元对。词汇表:种别编码单词符号助记符0beginb..._对pl/0作以下修改扩充。增加单词

android adb shell 权限,android adb shell权限被拒绝-程序员宅基地

文章浏览阅读773次。我在使用adb.exe时遇到了麻烦.我想使用与bash相同的adb.exe shell提示符,所以我决定更改默认的bash二进制文件(当然二进制文件是交叉编译的,一切都很完美)更改bash二进制文件遵循以下顺序> adb remount> adb push bash / system / bin /> adb shell> cd / system / bin> chm..._adb shell mv 权限

投影仪-相机标定_相机-投影仪标定-程序员宅基地

文章浏览阅读6.8k次,点赞12次,收藏125次。1. 单目相机标定引言相机标定已经研究多年,标定的算法可以分为基于摄影测量的标定和自标定。其中,应用最为广泛的还是张正友标定法。这是一种简单灵活、高鲁棒性、低成本的相机标定算法。仅需要一台相机和一块平面标定板构建相机标定系统,在标定过程中,相机拍摄多个角度下(至少两个角度,推荐10~20个角度)的标定板图像(相机和标定板都可以移动),即可对相机的内外参数进行标定。下面介绍张氏标定法(以下也这么称呼)的原理。原理相机模型和单应矩阵相机标定,就是对相机的内外参数进行计算的过程,从而得到物体到图像的投影_相机-投影仪标定

Wayland架构、渲染、硬件支持-程序员宅基地

文章浏览阅读2.2k次。文章目录Wayland 架构Wayland 渲染Wayland的 硬件支持简 述: 翻译一篇关于和 wayland 有关的技术文章, 其英文标题为Wayland Architecture .Wayland 架构若是想要更好的理解 Wayland 架构及其与 X (X11 or X Window System) 结构;一种很好的方法是将事件从输入设备就开始跟踪, 查看期间所有的屏幕上出现的变化。这就是我们现在对 X 的理解。 内核是从一个输入设备中获取一个事件,并通过 evdev 输入_wayland

推荐文章

热门文章

相关标签