第一种:为普通java类中的某个方法配置跑批任务

  1. MethodInvokingJobDetailFactoryBean
  2. CronTriggerBean
  3. SchedulerFactoryBean

1.定义要跑批的类和方法:

  1. package com.xy.utils.quartz;
  2. import org.joda.time.DateTime;
  3. import org.slf4j.Logger;
  4. import org.slf4j.LoggerFactory;
  5. /**
  6. * 测试定时器类
  7. * @author javaw
  8. *
  9. */
  10. public class TestQuartz {
  11. public static Logger logger = LoggerFactory.getLogger(TestQuartz.class);
  12. public void TestMethod(){
  13. logger.info("Auto Execute TestMethod start! Date={}" ,new DateTime().toString("YYYY-MM-DD HH:mm:ss" ));
  14. logger.info("**********测试跑批类************");
  15. logger.info("Auto Execute TestMethod end! Date={}" ,new DateTime().toString("YYYY-MM-DD HH:mm:ss" ));
  16. }
  17. }

2.配置Spring定时器让quartz自动执行testMethod方法:

  1. <!-- 实例化bean -->
  2. <bean id= "testMethodQuartz" class ="com.xy.utils.quartz.TestQuartz"/>
  3. <!-- 配置MethodInvokingJobDetailFactoryBean -->
  4. <bean id= "testTaskMethod"
  5. class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
  6. <property name="targetObject" ref="testMethodQuartz"/>
  7. <property name="targetMethod" value="TestMethod"/>
  8. <property name="concurrent" value="false"/>
  9. </bean>
  10. <!-- 配置定时表达式 -->
  11. <bean id= "testTaskTrigger" class="org.springframework.scheduling.quartz.CronTriggerBean" >
  12. <property name="jobDetail" ref="testTaskMethod" />
  13. <!-- 每一分钟执行一次 -->
  14. <property name="cronExpression" value="0 0/1 * * * ?" />
  15. </bean>
  16. <!-- 配置调度工厂 -->
  17. <bean id= "testSchedulerFactoryBean"
  18. class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
  19. <property name="triggers" >
  20. <list>
  21. <ref bean="testTaskTrigger" />
  22. </list>
  23. </property>
  24. </bean>

3.写测试方法进行调用(不用启动tomcat):

  1. public static void main(String[] args) {
  2. SchedulerFactoryBean schedulerFactoryBean = (SchedulerFactoryBean) SpringUtilsFromClassPathXml.getBean( "testSchedulerFactoryBean");
  3. //启动调度器
  4. schedulerFactoryBean.start();
  5. }

第二种:为继承QuartzJobBean的java类配置跑批任务

1.写java类继承QuartzJobBean,重写executeInternal 方法:

  1. package com.xy.utils.quartz;
  2. import org.joda.time.DateTime;
  3. import org.quartz.JobExecutionContext;
  4. import org.quartz.JobExecutionException;
  5. import org.slf4j.Logger;
  6. import org.slf4j.LoggerFactory;
  7. import org.springframework.scheduling.quartz.QuartzJobBean;
  8. import org.springframework.scheduling.quartz.SchedulerFactoryBean;
  9. /**
  10. * 测试继承QuartzJobBean的java类配置定时器
  11. * @author javaw
  12. *
  13. */
  14. public class TestQuartzExtendsJobBean extends QuartzJobBean{
  15. private static Logger logger = LoggerFactory.getLogger(TestQuartzExtendsJobBean. class);
  16. @Override
  17. protected void executeInternal(JobExecutionContext context)
  18. throws JobExecutionException {
  19. logger.info("Auto Execute TestQuartzExtendsJobBean start! Date={}",new DateTime().toString( "YYYY-MM-DD HH:mm:ss"));
  20. logger.info("**********"+content.getMergedJobDataMap().get("descString")+"************");
  21. logger.info("Auto Execute TestQuartzExtendsJobBean end! Date={}",new DateTime().toString( "YYYY-MM-DD HH:mm:ss"));
  22. }
  23. }

2.配置文件:

  1. <!--
  2. 第二种:为继承Quartz的java类实现跑批
  3. **********1.JobDetailBean
  4. **********2.CronTriggerBean
  5. **********3.SchedulerFactoryBean
  6. -->
  7. <bean id= "testJobDetailBean"
  8. class="org.springframework.scheduling.quartz.JobDetailBean">
  9. <property name="name" value="exampleJob" />
  10. <property name="jobClass"
  11. value="com.xy.utils.quartz.TestQuartzExtendsJobBean"/>
  12. <!-- 可以封装各种数据到JobExecutionContext里 -->
  13. <property name="jobDataAsMap">
  14. <map>
  15. <entry key="descString" value="测试跑批"/>
  16. </map>
  17. </property>
  18. </bean >
  19. <bean id= "testTaskTrigger"
  20. class="org.springframework.scheduling.quartz.CronTriggerBean">
  21. <property name="jobDetail" ref="testJobDetailBean" />
  22. <property name="cronExpression" value="0 0/1 * * * ?" />
  23. </bean>
  24. <bean id= "testSchedulerFactoryBean"
  25. class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
  26. <property name="triggers" >
  27. <list>
  28. <ref bean="testTaskTrigger" />
  29. </list>
  30. </property>
  31. </bean>

第三种:定时任务持久化(JobDetailTx)

优势:

集群部署定时器通过故障切换和负载均衡的功能,提高调度器的可用性和扩展性。

本质:

集群上的所有节点通过共享一个数据库来来工作的。所有节点quartz通过启动两个维护线程来维护数据库状态实现集群管理,一个是检测节点状态线程,一个是恢复任务线程。一个 Quartz 集群中的每个节点是一个独立的 Quartz 应用,它又管理着其他的节点。

模式:

1.获取任务

负载均衡是自动完成的,集群的每个节点会尽快触发任务。当第一个节点获取到任务,会通过锁定,阻止其他线程获取到该任务。

2.故障切换

当一个节点执行任务失败(服务down掉或其他原因),其他节点会检测到并标识在失败节点上正在执行的数据库中的任务。任何标记为可恢复(任务详细里的requests recovery属性)的任务都会被其他节点继续执行。没有标记可恢复的任务会被释放掉。

  1. CREATE TABLE qrtz_job_details
  2. (
  3. ....
  4. JOB_NAME VARCHAR2(80) NOT NULL,
  5. JOB_GROUP VARCHAR2(80) NOT NULL,
  6. REQUESTS_RECOVERY VARCHAR2(1) NOT NULL, --可恢复标记
  7. );
  1. SchedulerFactoryBean
  2. JobDetail
  3. Trigger
  4. Job

将定时任务持久化可以解决分布式跑批的问题,避免服务器重启信息丢失。

定时任务定义需要实例化JobDetail和Trigger,然后使用Scheduler进行调度。这个需要使用到Quartz的jar包。

每个jar包创建任务的方式都不相同。具体需要查看官方api。

quartz2.2.1中给出的示例:

  1. JobDetail job = newJob(MyJob.class)
  2. .withIdentity("myJob")
  3. .build();
  4. Trigger trigger = newTrigger()
  5. .withIdentity(triggerKey("myTrigger", "myTriggerGroup"))
  6. .withSchedule(simpleSchedule()
  7. .withIntervalInHours(1)
  8. .repeatForever())
  9. .startAt(futureDate(10, MINUTES))
  10. .build();
  11. scheduler.scheduleJob(job, trigger);

导入jar包后,写如下测试类:

  1. package com.xy.utils.scheduler;
  2. import org.quartz.JobBuilder;
  3. import org.quartz.JobDetail;
  4. import org.quartz.Scheduler;
  5. import org.quartz.SchedulerFactory;
  6. import org.quartz.SimpleScheduleBuilder;
  7. import org.quartz.Trigger;
  8. import org.quartz.TriggerBuilder;
  9. import org.quartz.impl.StdSchedulerFactory;
  10. public class quartzTest {
  11. public static void main(String args[]) throws Exception {
  12. JobDetail jobDetail= JobBuilder.newJob(TestJob.class)
  13. .withIdentity("job","group")
  14. .build();
  15. Trigger trigger= TriggerBuilder.newTrigger().withIdentity("job","group").startNow().withSchedule(
  16. SimpleScheduleBuilder.simpleSchedule()
  17. .withIntervalInSeconds(10)   //时间间隔
  18. .withRepeatCount(10)        //重复次数n+1
  19. )
  20. .build();
  21. SchedulerFactory sf = new StdSchedulerFactory();
  22. Scheduler sched = sf.getScheduler();
  23. sched.scheduleJob(jobDetail, trigger);
  24. sched.start();
  25. }
  26. }

定时执行的任务类:

  1. package com.xy.utils.scheduler;
  2. import org.quartz.Job;
  3. import org.quartz.JobExecutionContext;
  4. import org.quartz.JobExecutionException;
  5. public class TestJob implements Job {
  6. public void execute(JobExecutionContext arg0) throws JobExecutionException {
  7. System.out.println("*****执行批处理任务******");
  8. }
  9. }

这种任务并没有持久化到数据库中。

在Spring中配置SchedulerFactoryBean:

  1. <!--
  2. 第三种:从数据库中读取跑批任务(适合集群部署跑批)
  3. **********1.SchedulerFactoryBean
  4. -->
  5. <bean id="schedulerBeanFactory" class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
  6. <!-- 注入数据源,包含任务执行表 -->
  7. <property name="dataSource" ref="dataSource"/>
  8. <!--applicationContextSchedulerContextKey:
  9. 把spring上下文以key/value的方式存放在了quartz的上下文中了,
  10. 可以用applicationContextSchedulerContextKey所定义的key得到对应的spring上下文-->
  11. <property name="applicationContextSchedulerContextKey" value="applicationContext"/>
  12. <!-- 读取配置文件 -->
  13. <property name="configLocation" value="classpath:/properties/quartz.properties"/>
  14. <property name="autoStartup" value="true"/>
  15. </bean>

配置quartz.properties:

下载了quartz.jar后,在\quartz-2.2.1\src\org\quartz\目录下有个quartz.properties的文件,可以根据自己的需要更改其中的配置内容。

  1. #批处理常量表 QUARTZ2.2.1
  2. #============================================================================
  3. # Configure Main Scheduler Properties
  4. #============================================================================
  5. org.quartz.scheduler.instanceName = MyQuartzScheduler
  6. org.quartz.scheduler.instanceId = AUTO
  7. #============================================================================
  8. # Configure ThreadPool
  9. #============================================================================
  10. org.quartz.threadPool.class = org.quartz.simpl.SimpleThreadPool
  11. org.quartz.threadPool.threadCount = 10
  12. org.quartz.threadPool.threadPriority = 5
  13. org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread:true
  14. #============================================================================
  15. # Configure JobStore
  16. #============================================================================
  17. org.quartz.jobStore.misfireThreshold = 10000
  18. org.quartz.jobStore.class = org.springframework.scheduling.quartz.LocalDataSourceJobStore
  19. org.quartz.jobStore.driverDelegateClass = org.quartz.impl.jdbcjobstore.StdJDBCDelegate
  20. org.quartz.jobStore.isClustered = true --是否集群部署
  21. #任务表前缀
  22. org.quartz.jobStore.tablePrefix = test_qrtz_

创建任务表:

jar包文件中,给出了所有数据库的建表语句。可以根据给出的sql语句创建表。

调度类:

  1. package com.xy.utils.scheduler;
  2. import org.quartz.JobBuilder;
  3. import org.quartz.JobDetail;
  4. import org.quartz.Scheduler;
  5. import org.quartz.SimpleScheduleBuilder;
  6. import org.quartz.Trigger;
  7. import org.quartz.TriggerBuilder;
  8. import com.xy.utils.SpringUtils.SpringUtilsFromClassPathXml;
  9. public class quartzTest {
  10. //从Spring中获取调度bean工厂
  11. public static Scheduler scheduler = (Scheduler)SpringUtilsFromClassPathXml.getBean("schedulerBeanFactory");
  12. public static void main(String args[]) throws Exception {
  13. JobDetail jobDetail= JobBuilder.newJob(TestJob.class)
  14. .withIdentity("job","group")
  15. .build();
  16. Trigger trigger= TriggerBuilder.newTrigger().withIdentity("job","group").startNow().withSchedule(
  17. SimpleScheduleBuilder.simpleSchedule()
  18. .withIntervalInSeconds(10) //时间间隔
  19. .repeatForever()
  20. )
  21. .build();
  22. scheduler.scheduleJob(jobDetail, trigger);
  23. scheduler.start();
  24. }
  25. }

任务类(需要实现job接口):

  1. package com.xy.utils.scheduler;
  2. import org.quartz.Job;
  3. import org.quartz.JobExecutionContext;
  4. import org.quartz.JobExecutionException;
  5. public class TestJob implements Job {
  6. public void execute(JobExecutionContext arg0) throws JobExecutionException {
  7. System.out.println("*****执行批处理任务******");
  8. }
  9. }

此时执行该类就会将任务数据写入数据库中。

调度任务工具类:

自定义任务调度工具类:

  1. package com.xy.utils.scheduler;
  2. import java.text.ParseException;
  3. import java.text.SimpleDateFormat;
  4. import java.util.Date;
  5. import org.quartz.CronScheduleBuilder;
  6. import org.quartz.CronTrigger;
  7. import org.quartz.DateBuilder;
  8. import org.quartz.Job;
  9. import org.quartz.JobBuilder;
  10. import org.quartz.JobDetail;
  11. import org.quartz.Scheduler;
  12. import org.quartz.SchedulerException;
  13. import org.quartz.SimpleScheduleBuilder;
  14. import org.quartz.Trigger;
  15. import org.quartz.TriggerBuilder;
  16. import org.quartz.TriggerKey;
  17. import org.quartz.DateBuilder.IntervalUnit;
  18. import org.slf4j.Logger;
  19. import org.slf4j.LoggerFactory;
  20. import com.xy.common.SysContent;
  21. public class SchedulerJobUtils {
  22. private static Logger logger = LoggerFactory.getLogger(SchedulerJobUtils.class);
  23. public static Scheduler scheduler = (Scheduler)SysContent.applicationContext.getBean("schedulerBeanFactory");
  24. //public static Scheduler scheduler = (Scheduler)SpringUtilsFromClassPathXml.getBean("schedulerBeanFactory");
  25. public static String dateFormate = "ss mm HH dd MM ? yyyy";
  26. public static SimpleDateFormat cronSdf = new SimpleDateFormat(dateFormate);
  27. public static SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
  28. /**
  29. * 数据库放入一个指定时间的任务,任务只执行一次
  30. * @see 适合对数据进行定时删除,修改等等
  31. * @param <T>
  32. * @param clazz  要执行任务类class,任务类必须继承Job类
  33. * @param jobName 任务名称
  34. * @param groupName 分组名称
  35. * @param executeTime 执行时间,格式:yyyy-MM-dd HH:mm:ss
  36. * @return
  37. */
  38. public static<T> boolean putSpecifyTimeSchedulerJobToDB(Class<? extends Job> clazz,String jobName,String groupName,String executeTime){
  39. //定义一个job
  40. JobDetail job = JobBuilder.newJob(clazz).withIdentity(jobName, groupName).build();
  41. //定义一个TriggerKey
  42. TriggerKey triggerKey = TriggerKey.triggerKey(jobName, groupName);
  43. SchedulerJob schedulerJob = new SchedulerJob();
  44. schedulerJob.setJobName(jobName);
  45. schedulerJob.setGroupName(groupName);
  46. job.getJobDataMap().put("schedulerJob", schedulerJob);
  47. Date executeDate = null;
  48. try {
  49. executeDate = sdf.parse(executeTime);
  50. } catch (ParseException e) {
  51. logger.info("method putSchedulerJobToDB execute error!exception={}",e);
  52. }
  53. String dbExecuteTime = cronSdf.format(executeDate);
  54. CronTrigger cronTrigger = TriggerBuilder.newTrigger().withIdentity(triggerKey).withSchedule(CronScheduleBuilder.cronSchedule(dbExecuteTime)).build();
  55. try {
  56. scheduler.scheduleJob(job, cronTrigger);
  57. } catch (SchedulerException e) {
  58. logger.info("method putSchedulerJobToDB execute error!exception={}",e);
  59. }
  60. return true;
  61. }
  62. /**
  63. * 数据库放入一条指定开始时间,指定间隔时间,指定次数的任务
  64. * @param <T>
  65. * @param clazz 任务类
  66. * @param jobName  任务名
  67. * @param groupName 分组名
  68. * @param seconds   间隔时间,以秒为单位
  69. * @param count 执行次数,0为一直执行
  70. * @param startSecondsToNow 开始时间(距离现在?秒)
  71. * @return
  72. * @throws SchedulerException
  73. */
  74. @SuppressWarnings("unchecked")
  75. public static<T> boolean putPeriodSchedulerJobToDB(Class<? extends Job> clazz,String jobName,String groupName,
  76. int seconds,int count,int startSecondsToNow){
  77. JobDetail jobDetail= JobBuilder.newJob(clazz).withIdentity(jobName,groupName).build();
  78. TriggerBuilder triggerBuilder = TriggerBuilder.newTrigger().withIdentity(jobName,groupName);
  79. if(startSecondsToNow==0){
  80. triggerBuilder.startNow();
  81. }else{
  82. triggerBuilder.startAt(DateBuilder.futureDate(startSecondsToNow,IntervalUnit.SECOND));
  83. }
  84. SimpleScheduleBuilder scheduleBuilder = SimpleScheduleBuilder.simpleSchedule().withIntervalInSeconds(seconds);
  85. if(count==0){
  86. scheduleBuilder.repeatForever();
  87. }else{
  88. scheduleBuilder.withRepeatCount(count);
  89. }
  90. Trigger trigger = triggerBuilder.withSchedule(scheduleBuilder).build();
  91. try {
  92. scheduler.scheduleJob(jobDetail,trigger);
  93. } catch (SchedulerException e) {
  94. logger.info("put putPeriodSchedulerJobToDB error,error={}",e);
  95. }
  96. return true;
  97. }
  98. }

任务类:

  1. package com.xy.utils.scheduler;
  2. import org.joda.time.DateTime;
  3. import org.quartz.Job;
  4. import org.quartz.JobExecutionContext;
  5. import org.quartz.JobExecutionException;
  6. import org.slf4j.Logger;
  7. import org.slf4j.LoggerFactory;
  8. public class TestSchedulerTask implements Job{
  9. private static Logger logger = LoggerFactory.getLogger(TestSchedulerTask.class);
  10. public void execute(JobExecutionContext context) throws JobExecutionException {
  11. logger.info("**********TestSchedulerTask1 start at={}",new DateTime().toString("yyyy-MM-dd HH:mm:ss"));
  12. logger.info("**********I'm Ok!************");
  13. logger.info("**********TestSchedulerTask1 end at={}",new DateTime().toString("yyyy-MM-dd HH:mm:ss"));
  14. }
  15. /**
  16. * 调度任务工具类测试
  17. * 10秒执行一次,无限次数,30秒后开始
  18. * @param args
  19. */
  20. public static void main(String[] args) {
  21. System.out.println(SchedulerJobUtils.putPeriodSchedulerJobToDB(TestSchedulerTask.class, "myJob", "myGroup", 10, 0, 30));
  22. }
  23. }

数据库里的任务表:

打印出的日志:
2016-01-10 00:37:34,810  INFO TestSchedulerTask1:14 - **********TestSchedulerTask1 start at=2016-01-10 00:37:34
2016-01-10 00:37:34,810  INFO TestSchedulerTask1:15 - **********I'm Ok!************
2016-01-10 00:37:34,811  INFO TestSchedulerTask1:16 - **********TestSchedulerTask1 end at=2016-01-10 00:37:34

2016-01-10 00:37:44,690  INFO TestSchedulerTask1:14 - **********TestSchedulerTask1 start at=2016-01-10 00:37:44
2016-01-10 00:37:44,691  INFO TestSchedulerTask1:15 - **********I'm Ok!************
2016-01-10 00:37:44,691  INFO TestSchedulerTask1:16 - **********TestSchedulerTask1 end at=2016-01-10 00:37:44

2016-01-10 00:37:54,697  INFO TestSchedulerTask1:14 - **********TestSchedulerTask1 start at=2016-01-10 00:37:54
2016-01-10 00:37:54,697  INFO TestSchedulerTask1:15 - **********I'm Ok!************
2016-01-10 00:37:54,697  INFO TestSchedulerTask1:16 - **********TestSchedulerTask1 end at=2016-01-10 00:37:54

【spring配置】——spring整合Quartz定时器的更多相关文章

  1. Spring Boot 整合Quartz定时器

    概述 项目需要定时器的调度管理,原来使用Spring Boot自带的定时器,但是不能后台动态的操作暂停.启动以及新增任务等操作,维护起来相对麻烦:最近研究了Quartz的框架,觉得还算不错,整理了一下 ...

  2. spring通过配置xml文件集成quartz定时器

    概述 Spring为创建Quartzde Scheduler.Trigger和JobDetail提供了方便的FactoryBean类,以便能够在Spring容器中享受注入的好处. 此外,Spring还 ...

  3. Spring整合Quartz定时器

    1.添加jar #此处省略spring核心jar包 <dependency> <groupId>org.quartz-scheduler</groupId> < ...

  4. Spring Boot 应用系列 6 -- Spring Boot 2 整合Quartz

    Quartz是实现定时任务的利器,Quartz主要有四个组成部分,分别是: 1. Job(任务):包含具体的任务逻辑: 2. JobDetail(任务详情):是对Job的一种详情描述: 3. Trig ...

  5. spring data JPA使用quartz定时器的具体实现

    第一步.在pom.xml中的配置 <!--quartz--> <dependency> <groupId>org.quartz-scheduler</grou ...

  6. Spring 配置 Spring JPA 发生错误的解决方法

    今天在项目的applicationContext.xml中配JPA时 <?xml version="1.0" encoding="UTF-8"?> ...

  7. Spring整合Quartz实现动态定时器

    一.版本说明 spring3.1以下的版本必须使用quartz1.x系列,3.1以上的版本才支持quartz 2.x,不然会出错. 原因:spring对于quartz的支持实现,org.springf ...

  8. Spring整合Quartz实现动态定时器,相关api,定时器添加,删除,修改

    一.版本说明 spring3.1以下的版本必须使用quartz1.x系列,3.1以上的版本才支持quartz 2.x,不然会出错. 原因:spring对于quartz的支持实现,org.springf ...

  9. Spring 整合 Quartz框架(定时任务)

    Maven 无法下载 Quartz 依赖,去官网下载 http://www.quartz-scheduler.org/downloads/ Quartz 官方手册:https://www.w3csch ...

随机推荐

  1. Hibernate search与Lucene包异常学习心得

    最近使用了了一下Hibernate  Search这个组件 这个组件是对域模型进行全文检索,在全文检索的底层实现上使用了Lucene技术 在进行小测试的时候费了很大的力气去搞定包的问题 我直接通过实例 ...

  2. BZOJ 3029 守卫者的挑战

    题面 Description 打开了黑魔法师Vani的大门,队员们在迷宫般的路上漫无目的地搜寻着关押applepi的监狱的所在地.突然,眼前一道亮光闪过."我,Nizem,是黑魔法圣殿的守卫 ...

  3. APNS push server端 SSL3.0 转 TLS (iPhone苹果推送服务)

    (转载此文,请说明原文出处) 苹果的官方公布 Update to the Apple Push Notification Service October 22, 2014 The Apple Push ...

  4. k8s学习(二)——etcdctl工具的使用

    k8s的实现核心实际上就是通过读写etcd数据库实现对资源的存储,管理和控制. k8s所有资源的本源都是存储在etcd中的一个个键值对. 理论上可以观察到etcd数据库中的数据变化.具体的使用方式如下 ...

  5. mock平台架构及实现

    转载: http://blog.csdn.net/xkhgnc_6666/article/details/51757209 在测试过程中有些情况通过手工测试是无法测试出来的或是非常难复现,比如网络异常 ...

  6. centos 7 mariadb 安装

    yum install -y mariadb mariadb-server systemctl start mariadb systemctl enable mariadb #初始化 mysql_se ...

  7. Android4.0(Phone)拨号启动过程分析(一)

    因为工作的须要.须要改动原生的Phone程序,如今就好好看下来电与拨号是怎样处理的:无论是拨号还是来电,调用的都是Phone程序,因为非常多类都涉及到framework层,比較复杂:先从简单的拨号分析 ...

  8. &lt;&lt;Python基础教程&gt;&gt;学习笔记 | 第04章 | 字典

    第04章:字典 当索引不好用时 Python唯一的内建的映射类型,无序,但都存储在一个特定的键中.键能够使字符.数字.或者是元祖. ------ 字典使用: 表征游戏棋盘的状态,每一个键都是由坐标值组 ...

  9. WPF 基础到企业应用系列5——WPF千年轮回 续前缘

    一.摘要 首先非常高兴这个系列能得到大家的关注和支持,前端时间身体状况不适,所以暂停了更新,对此表示非常抱歉,以后会逐渐加快进度.只是因为这是一个非常长的系列,我也想把它写好,所以以后也会慢慢来,在这 ...

  10. Theme.AppCompat.Light.DarkActionBar ActionBarActivity

    关于android-support-v7-appcompat.jar的引用.这个不单纯的把jar复制到项目lib目录下的,不然就会报一堆主题找不到的2b问题, 正确方法例如以下: 1.找到androi ...