ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

quartz定时器的处理

2021-07-25 21:32:57  阅读:188  来源: 互联网

标签:触发器 定时器 sched String 处理 param quartz static public


一、quartz的简单配置

1、引入定时器的maven包

      <dependency>
            <groupId>org.quartz-scheduler</groupId>
            <artifactId>quartz</artifactId>
            <version>2.2.1</version>
        </dependency>

        <dependency>
            <groupId>org.quartz-scheduler</groupId>
            <artifactId>quartz-jobs</artifactId>
            <version>2.2.1</version>
        </dependency>
        <!--        >>>>SpringBoot替换为:>>>>-->
        <!--quartz依赖-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-quartz</artifactId>
        </dependency>

2、加注解简单实用

@Component
@Configurable
@EnableScheduling   //启动定时任务
public class SendMailQuartz {

    //日志对象
    private static final Logger logger = LogManager.getLogger(SendMailQuartz.class);



    //每5秒执行一次
    @Scheduled(cron = "*/5 * *  * * * ")
    public void reportCurrentByCron(){

        logger.info("定时器运行五秒一次!!!");
    }
    @Scheduled(fixedDelay = 100*30)
    public void test() {
        System.out.println("定时器第一个执行");
    }

    //每5秒执行一次
    @Scheduled(cron = "*/5 * *  * * * ")
    public void test2() {
        System.out.println("定时器第二个执行");
    }
    //每1分针执行一次
    @Scheduled(cron = "0 */1  *  * * * ")
    public void test3() {
        System.out.println("定时器第三个执行");
    }

}

二、实用xml方式引入定时器Quartz

1、上面引入了Quartz的依赖,下面的方法都实用上面的依赖,开始引入spring-mvc.xml,里面引入spring-quartz.xml

<import resource="spring-quartz.xml"/>

 完整的spring-mvc.xml如下所示

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:task="http://www.springframework.org/schema/task"
       xsi:schemaLocation="
       http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/context
       http://www.springframework.org/schema/context/spring-context-4.2.xsd
       http://www.springframework.org/schema/mvc
       http://www.springframework.org/schema/mvc/spring-mvc.xsd
       http://www.springframework.org/schema/aop
       http://www.springframework.org/schema/aop/spring-aop.xsd
       http://www.springframework.org/schema/task
       http://www.springframework.org/schema/task/spring-task.xsd">

    <context:annotation-config/>
    <!-- 利用import引入定时器的文件 -->
    <import resource="spring-quartz.xml"/>



</beans>
2、引入spring-quartz.xml文件

(1)、这个引入所执行的类,并注入到Spring容器中, 中间的这个,如果要做动态调度执行时间,则不能缺少,<property name="scheduler" ref="scheduler"></property>

<bean id="taskJob" class="com.nswi.quartz.TestTask">
        <property name="scheduler" ref="scheduler"></property>
    </bean>

(2)、通过Id引入上面的类,并 导入需要执行的类中的方法

 <bean id="jobDetail"
          class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">

        <property name="targetObject">
            <ref bean="taskJob"/>
        </property>
<!--        执行的方法-->
        <property name="targetMethod">
            <value>run</value>
        </property>
        <!-- 上一次未执行完成的,要等待有再执行。 -->
        <property name="concurrent" value="false"></property>
    </bean>

 (3)、执行调度方法的执行时间,和执行次数都可以在这个里面配置,配置的value是毫秒,一秒等于1000毫秒,以及执行重复次数repeatCount,调用间隔时间repeatInterval

    <bean id="testTrigger" class="org.springframework.scheduling.quartz.SimpleTriggerFactoryBean">
        <property name="jobDetail" ref="jobDetail"></property>
        <!--       启动开始时间延迟一秒-->
        <property name="startDelay" value="1000"></property>
        <!--     每次时间间隔2秒  2000 -->
     <!--        时间间隔俩分钟-->
        <property name="repeatInterval" value="20000"></property>
<!--     执行重复次数-->
<!--        <property name="repeatCount" value="0" />-->
    </bean>

(4)、调度工厂执行调度任务 

 <bean id="scheduler"
          class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
        <property name="triggers">
            <list>
                <ref bean="testTrigger"/>
            </list>
        </property>
    </bean>

 完整的spring-quartz.xml如下所示

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">

<!--    <bean id="taskJob" class="com.nswi.quartz.TestTask"/>-->

    <bean id="taskJob" class="com.nswi.quartz.TestTask">
        <property name="scheduler" ref="scheduler"></property>
    </bean>

    <bean id="jobDetail"
          class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">

        <property name="targetObject">
            <ref bean="taskJob"/>
        </property>
<!--        执行的方法-->
        <property name="targetMethod">
            <value>run</value>
        </property>
        <!-- 上一次未执行完成的,要等待有再执行。 -->
        <property name="concurrent" value="false"></property>
    </bean>

    <!--  调度触发器 -->
<!--    <bean id="myTrigger"-->
<!--          class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">-->
<!--        <property name="jobDetail">-->
<!--            <ref bean="jobDetail" />-->
<!--        </property>-->
<!--        <property name="cronExpression">-->
<!--            <value>0/5 * * * * ?</value>-->
<!--        </property>-->
<!--    </bean>-->
    <bean id="testTrigger" class="org.springframework.scheduling.quartz.SimpleTriggerFactoryBean">
        <property name="jobDetail" ref="jobDetail"></property>
        <!--       启动开始时间延迟一秒-->
        <property name="startDelay" value="1000"></property>
        <!--     每次时间间隔2秒  2000 -->
     <!--        时间间隔俩分钟-->
        <property name="repeatInterval" value="20000"></property>
<!--     执行重复次数-->
<!--        <property name="repeatCount" value="0" />-->
    </bean>

    <!-- 调度工厂 -->
    <bean id="scheduler"
          class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
        <property name="triggers">
            <list>
                <ref bean="testTrigger"/>
            </list>
        </property>
    </bean>
</beans>

3、在启动器上面引入spring-mvc.xml,间接引入spring-quartz.xml

@SpringBootApplication
@ImportResource(locations={"classpath:spring-mvc.xml"})
public class QuartzCgqApplication {
    public static void main(String[] args) {
        SpringApplication.run(QuartzCgqApplication.class, args);
    }
}

4、配置执行类,和执行方法,这样,启动后会自动执行,这个类下面标记的方法,这里设置的是run方法,

package com.nswi.quartz;

import com.nswi.entity.CgqCall;
import com.nswi.entity.CgqType;
import com.nswi.entity.CgqTypeDetails;
import com.nswi.mapper.CgqTypeMapper;
import com.nswi.mod.ModbusRtuMaster;
import com.nswi.service.ICgqCallService;
import com.nswi.service.ICgqTypeDetailsService;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.TriggerKey;
import org.quartz.impl.triggers.SimpleTriggerImpl;
import org.springframework.beans.factory.annotation.Autowired;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;

/**
 * 描述:定时器类
 */
public class TestTask {


    

    public void run()  {

      System.out.println("执行了这个方法");


    }

    private Scheduler scheduler;

    public Scheduler getScheduler() {
        return scheduler;
    }

    public void setScheduler(Scheduler scheduler) {
        this.scheduler = scheduler;
    }

    public void restJob(long time) {

        TriggerKey triggerKey = new TriggerKey("testTrigger", Scheduler.DEFAULT_GROUP);
        SimpleTriggerImpl simpleTrigger = null;
        try {
            simpleTrigger = (SimpleTriggerImpl) scheduler.getTrigger(triggerKey);
        } catch (SchedulerException e) {
            e.printStackTrace();
        }

        simpleTrigger.setRepeatInterval(time);

        try {
            scheduler.rescheduleJob(triggerKey, simpleTrigger);
        } catch (SchedulerException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }


}

下面的配置,是为了动态调用方法,用来改变quartz执行的间隔时间 

   private Scheduler scheduler;

    public Scheduler getScheduler() {
        return scheduler;
    }

    public void setScheduler(Scheduler scheduler) {
        this.scheduler = scheduler;
    }

    public void restJob(long time) {

        TriggerKey triggerKey = new TriggerKey("testTrigger", Scheduler.DEFAULT_GROUP);
        SimpleTriggerImpl simpleTrigger = null;
        try {
            simpleTrigger = (SimpleTriggerImpl) scheduler.getTrigger(triggerKey);
        } catch (SchedulerException e) {
            e.printStackTrace();
        }

        simpleTrigger.setRepeatInterval(time);

        try {
            scheduler.rescheduleJob(triggerKey, simpleTrigger);
        } catch (SchedulerException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

5、动态调用接口,来改变quartz的执行间隔

其中value的taskJob来自于xml中的配置


    @Autowired
    @Qualifier(value = "taskJob")
    private TestTask job;
  <bean id="taskJob" class="com.nswi.quartz.TestTask">
        <property name="scheduler" ref="scheduler"></property>
    </bean>

6、 完整的接口配置,如下所示,通过简单调用接口方式,动态调节定时器执行时间


    @Autowired
    @Qualifier(value = "taskJob")
    private TestTask job;

    //两分钟一次
    private static Long Time1 = 120000L;
    //五分钟一次
    private static Long Time2 = 300000L;
    //10分钟一次
    private static Long Time3 = 600000L;

    @GetMapping("/job/{time}/{key}")
    @ResponseBody
    public Result job(@PathVariable("time") Long time,@PathVariable("key") String key) {

        if (key.equals("wwjsj")&& time!=null) {
            if(time==2){
                System.out.println("调整为2分钟");
                job.restJob(Time1);
            }else  if(time==5){
                System.out.println("调整为5分钟");
                job.restJob(Time2);
            }else {
                System.out.println("调整为10分钟");
                job.restJob(Time3);
            }

        }

        System.out.println(time);
        return Result.ok(key);
    }

三、自定义定时器的启动,删除,暂停

工具类如下所示

 1、定时器的增加的方法

 private static SchedulerFactory schedulerFactory = new StdSchedulerFactory();

    /**
     * @param jobName          任务名
     * @param jobGroupName     任务组名
     * @param triggerName      触发器名
     * @param triggerGroupName 触发器组名
     * @param jobClass         任务
     * @param cron             时间设置,参考quartz说明文档
     * @Description: 添加一个定时任务
     */
    //SuppressWarnings  用于抑制编译器产生警告信息
    @SuppressWarnings({"unchecked", "rawtypes"})
    public static void addJob(String jobName, String jobGroupName,
                              String triggerName, String triggerGroupName, Class jobClass, String cron) {
        try {
            Scheduler sched = schedulerFactory.getScheduler();
            // 任务名,任务组,任务执行类
            JobDetail jobDetail = JobBuilder.newJob(jobClass).withIdentity(jobName, jobGroupName).build();
            // 触发器
            TriggerBuilder<Trigger> triggerBuilder = TriggerBuilder.newTrigger();
            // 触发器名,触发器组
            triggerBuilder.withIdentity(triggerName, triggerGroupName);
            triggerBuilder.startNow();
            // 触发器时间设定
            triggerBuilder.withSchedule(CronScheduleBuilder.cronSchedule(cron));
            // 创建Trigger对象
            CronTrigger trigger = (CronTrigger) triggerBuilder.build();

            // 调度容器设置JobDetail和Trigger
            sched.scheduleJob(jobDetail, trigger);

            // 启动
            if (!sched.isShutdown()) {
                sched.start();
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

2、定时器修改触发时间

    /**
     * @param jobName
     * @param jobGroupName
     * @param triggerName      触发器名
     * @param triggerGroupName 触发器组名
     * @param cron             时间设置,参考quartz说明文档
     * @Description: 修改一个任务的触发时间
     */
    public static void modifyJobTime(String jobName,
                                     String jobGroupName, String triggerName, String triggerGroupName, String cron) {
        try {
            Scheduler sched = schedulerFactory.getScheduler();
            TriggerKey triggerKey = TriggerKey.triggerKey(triggerName, triggerGroupName);
            CronTrigger trigger = (CronTrigger) sched.getTrigger(triggerKey);
            if (trigger == null) {
                return;
            }

            String oldTime = trigger.getCronExpression();
            if (!oldTime.equalsIgnoreCase(cron)) {
                /** 方式一 :调用 rescheduleJob 开始 */
                // 触发器
                TriggerBuilder<Trigger> triggerBuilder = TriggerBuilder.newTrigger();
                // 触发器名,触发器组
                triggerBuilder.withIdentity(triggerName, triggerGroupName);
                triggerBuilder.startNow();
                // 触发器时间设定
                triggerBuilder.withSchedule(CronScheduleBuilder.cronSchedule(cron));
                // 创建Trigger对象
                trigger = (CronTrigger) triggerBuilder.build();
                // 方式一 :修改一个任务的触发时间
                sched.rescheduleJob(triggerKey, trigger);
                /** 方式一 :调用 rescheduleJob 结束 */

                /** 方式二:先删除,然后在创建一个新的Job  */
                //JobDetail jobDetail = sched.getJobDetail(JobKey.jobKey(jobName, jobGroupName));
                //Class<? extends Job> jobClass = jobDetail.getJobClass();
                //removeJob(jobName, jobGroupName, triggerName, triggerGroupName);
                //addJob(jobName, jobGroupName, triggerName, triggerGroupName, jobClass, cron);
                /** 方式二 :先删除,然后在创建一个新的Job */
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

3、移除某一任务

  /**
     * @param jobName
     * @param jobGroupName
     * @param triggerName
     * @param triggerGroupName
     * @Description: 移除一个任务
     */
    public static void removeJob(String jobName, String jobGroupName,
                                 String triggerName, String triggerGroupName) {
        try {
            Scheduler sched = schedulerFactory.getScheduler();

            TriggerKey triggerKey = TriggerKey.triggerKey(triggerName, triggerGroupName);

            sched.pauseTrigger(triggerKey);// 停止触发器
            sched.unscheduleJob(triggerKey);// 移除触发器
            sched.deleteJob(JobKey.jobKey(jobName, jobGroupName));// 删除任务
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

4、启动所有定时任务

   /**
     * @Description:启动所有定时任务
     */
    public static void startJobs() {
        try {
            Scheduler sched = schedulerFactory.getScheduler();
            sched.start();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

5、关闭所有定时器

 /**
     * @Description:关闭所有定时任务
     */
    public static void shutdownJobs() {
        try {
            Scheduler sched = schedulerFactory.getScheduler();
            if (!sched.isShutdown()) {
                sched.shutdown();
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

这个工具类完整的如下

package com.nswi.quartz;

import org.quartz.*;
import org.quartz.impl.StdSchedulerFactory;

public class QuartzManager {

    private static SchedulerFactory schedulerFactory = new StdSchedulerFactory();

    /**
     * @param jobName          任务名
     * @param jobGroupName     任务组名
     * @param triggerName      触发器名
     * @param triggerGroupName 触发器组名
     * @param jobClass         任务
     * @param cron             时间设置,参考quartz说明文档
     * @Description: 添加一个定时任务
     */
    //SuppressWarnings  用于抑制编译器产生警告信息
    @SuppressWarnings({"unchecked", "rawtypes"})
    public static void addJob(String jobName, String jobGroupName,
                              String triggerName, String triggerGroupName, Class jobClass, String cron) {
        try {
            Scheduler sched = schedulerFactory.getScheduler();
            // 任务名,任务组,任务执行类
            JobDetail jobDetail = JobBuilder.newJob(jobClass).withIdentity(jobName, jobGroupName).build();
            // 触发器
            TriggerBuilder<Trigger> triggerBuilder = TriggerBuilder.newTrigger();
            // 触发器名,触发器组
            triggerBuilder.withIdentity(triggerName, triggerGroupName);
            triggerBuilder.startNow();
            // 触发器时间设定
            triggerBuilder.withSchedule(CronScheduleBuilder.cronSchedule(cron));
            // 创建Trigger对象
            CronTrigger trigger = (CronTrigger) triggerBuilder.build();

            // 调度容器设置JobDetail和Trigger
            sched.scheduleJob(jobDetail, trigger);

            // 启动
            if (!sched.isShutdown()) {
                sched.start();
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * @param jobName
     * @param jobGroupName
     * @param triggerName      触发器名
     * @param triggerGroupName 触发器组名
     * @param cron             时间设置,参考quartz说明文档
     * @Description: 修改一个任务的触发时间
     */
    public static void modifyJobTime(String jobName,
                                     String jobGroupName, String triggerName, String triggerGroupName, String cron) {
        try {
            Scheduler sched = schedulerFactory.getScheduler();
            TriggerKey triggerKey = TriggerKey.triggerKey(triggerName, triggerGroupName);
            CronTrigger trigger = (CronTrigger) sched.getTrigger(triggerKey);
            if (trigger == null) {
                return;
            }

            String oldTime = trigger.getCronExpression();
            if (!oldTime.equalsIgnoreCase(cron)) {
                /** 方式一 :调用 rescheduleJob 开始 */
                // 触发器
                TriggerBuilder<Trigger> triggerBuilder = TriggerBuilder.newTrigger();
                // 触发器名,触发器组
                triggerBuilder.withIdentity(triggerName, triggerGroupName);
                triggerBuilder.startNow();
                // 触发器时间设定
                triggerBuilder.withSchedule(CronScheduleBuilder.cronSchedule(cron));
                // 创建Trigger对象
                trigger = (CronTrigger) triggerBuilder.build();
                // 方式一 :修改一个任务的触发时间
                sched.rescheduleJob(triggerKey, trigger);
                /** 方式一 :调用 rescheduleJob 结束 */

                /** 方式二:先删除,然后在创建一个新的Job  */
                //JobDetail jobDetail = sched.getJobDetail(JobKey.jobKey(jobName, jobGroupName));
                //Class<? extends Job> jobClass = jobDetail.getJobClass();
                //removeJob(jobName, jobGroupName, triggerName, triggerGroupName);
                //addJob(jobName, jobGroupName, triggerName, triggerGroupName, jobClass, cron);
                /** 方式二 :先删除,然后在创建一个新的Job */
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * @param jobName
     * @param jobGroupName
     * @param triggerName
     * @param triggerGroupName
     * @Description: 移除一个任务
     */
    public static void removeJob(String jobName, String jobGroupName,
                                 String triggerName, String triggerGroupName) {
        try {
            Scheduler sched = schedulerFactory.getScheduler();

            TriggerKey triggerKey = TriggerKey.triggerKey(triggerName, triggerGroupName);

            sched.pauseTrigger(triggerKey);// 停止触发器
            sched.unscheduleJob(triggerKey);// 移除触发器
            sched.deleteJob(JobKey.jobKey(jobName, jobGroupName));// 删除任务
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * @Description:启动所有定时任务
     */
    public static void startJobs() {
        try {
            Scheduler sched = schedulerFactory.getScheduler();
            sched.start();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * @Description:关闭所有定时任务
     */
    public static void shutdownJobs() {
        try {
            Scheduler sched = schedulerFactory.getScheduler();
            if (!sched.isShutdown()) {
                sched.shutdown();
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}

执行的方法如下所示

1、执行的类继承Job类,然后实现它的excute方法

MyJob implements Job
public class MyJob implements Job {



    @Autowired
    CgqTypeMapper cgqTypeMapper;


    int i = 1;

    public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {

        Date date = new Date();
        System.out.println(date);
        i++;
        System.out.println(i);


        cgqTypeMapper = (CgqTypeMapper) SpringContextJobUtil.getBean("cgqTypeMapper");

        List<CgqType> cgqTypes = cgqTypeMapper.selectAll();
        try {

            cgqTypes.forEach(System.out::println);
            System.out.println(cgqTypes.size() + "个");



        } catch (Exception e) {

            e.printStackTrace();
        }


    }
}

2、调用方法如下

public class Test {

    public static String JOB_NAME = "动态任务调度";
    public static String TRIGGER_NAME = "动态任务触发器";
    public static String JOB_GROUP_NAME = "XLXXCC_JOB_GROUP";
    public static String TRIGGER_GROUP_NAME = "XLXXCC_JOB_GROUP";

    public static void main(String[] args) {
        try {
            System.out.println("【系统启动】开始(每5秒输出一次)...");
            QuartzManager.addJob(JOB_NAME, JOB_GROUP_NAME, TRIGGER_NAME, TRIGGER_GROUP_NAME, MyJob.class, "0/5 * * * * ?");

//            Thread.sleep(5000);
//            System.out.println("【修改时间】开始(每5秒输出一次)...");
//            QuartzManager.modifyJobTime(JOB_NAME, JOB_GROUP_NAME, TRIGGER_NAME, TRIGGER_GROUP_NAME, "0/5 * * * * ?");

//            Thread.sleep(6000);
//            System.out.println("【移除定时】开始...");
//            QuartzManager.removeJob(JOB_NAME, JOB_GROUP_NAME, TRIGGER_NAME, TRIGGER_GROUP_NAME);
//            System.out.println("【移除定时】成功");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

四、对比两种动态调用定时器的不同

1、xml 方式比较灵活简单,可以定时执行某个类下面具体的方法

2、采用继承job,只能执行excute的方法,因为输入的是 MyJob.class,这样的class文件,所以如果使用Spring容器中的某个bean,会出现找不到bean的问题。所以我建立了一个方法类如下,上面的excute方法中有使用到这个方法类

@Component
public class SpringContextJobUtil implements ApplicationContextAware {

    private static ApplicationContext context;

    @Override
    @SuppressWarnings("static-access" )
    public void setApplicationContext(ApplicationContext contex)
            throws BeansException {
        // TODO Auto-generated method stub
        this.context = contex;
    }
    public static Object getBean(String beanName){
        return context.getBean(beanName);
    }

    public static String getMessage(String key){
        return context.getMessage(key, null, Locale.getDefault());
    }
}

3、引用方式如下(我这里使用MybatisPlus的Mapper层的SelectAll)

  @Autowired
 CgqTypeMapper cgqTypeMapper;



cgqTypeMapper = (CgqTypeMapper) SpringContextJobUtil.getBean("cgqTypeMapper");

List<CgqType> cgqTypes = cgqTypeMapper.selectAll();

标签:触发器,定时器,sched,String,处理,param,quartz,static,public
来源: https://blog.csdn.net/weixin_43288858/article/details/118892157

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有