java自带定时任务可以解决部分问题但是当我们要动态执行定时任务时,quartz可以帮助我们有效解决这类型问题

代码亲测可用

springmvc中配置注入调度器scheduler,调用定时任务

<!-- quart -->
<!-- 调度类,如果lazy-init="false"容器启动时候回执行调度程序  -->
<bean id="scheduler" lazy-init="false" autowire="no"  class="org.springframework.scheduling.quartz.SchedulerFactoryBean"></bean><!-- 用来设置触发时间的,startJobs方法启动调度容器,然后按照上面的触发器,每个1s执行一次myjob2.dosomething()方法 -->
<bean id="quartzManager" class="cn.com.sinosoft.controller.QuartzManager"  lazy-init="true" init-method="startJobs"><!-- 注入对象,管理定时任务,还有在类型要用set get方法,否则会报异常   --><property name="scheduler" ref="scheduler" ></property></bean>

代码逻辑

quartzManager的调用方式,

QuartzManager qm = new QuartzManager();//newquartzManager对象
qm.addJob(votes.getName(), "group"+votes.getName(), "trigger"+votes.getName(), "triggerGroup"+votes.getName(), VoteJob.class,CronDateUtils.getCron(sdf.parse(votes.getEnd_time())),sdf.parse(votes.getOpen_time()), sdf.parse(votes.getEnd_time()),sdf.parse(votes.getOpen_time_join()),sdf.parse(votes.getEnd_time_join()),votes.getId());//直接调用给指定方法就ok

QuartzManager 直接copy即可,根据业务需要修改每个方法的传递参数(笔者该方法使用的是cronSchedule调度器,按照日历的格式,定期执行定时任务)

import java.text.SimpleDateFormat;
import java.util.Date;import org.quartz.CronScheduleBuilder;
import org.quartz.CronTrigger;
import org.quartz.JobBuilder;
import org.quartz.JobDetail;
import org.quartz.JobKey;
import org.quartz.Scheduler;
import org.quartz.Trigger;
import org.quartz.TriggerBuilder;
import org.quartz.TriggerKey;
import org.quartz.impl.StdSchedulerFactory;
import org.quartz.impl.matchers.EverythingMatcher;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;import cn.com.sinosoft.lisener.MyJobListener;
import cn.com.sinosoft.service.FxActivityService;public class QuartzManager {Logger logger = LoggerFactory.getLogger(this.getClass());private Scheduler scheduler;@Autowiredprivate FxActivityService fxActivityService;//新增定时任务@SuppressWarnings({ "unchecked", "rawtypes" })
public void addJob(String jobName,String jobGroupName,String triggerName,String triggerGroupName,Class jobClass,String cron, Date open_time, Date end_time, Date open_time_join, Date end_time_join, String id) {//该方法中除了String jobName,String jobGroupName,String triggerName,String triggerGroupName,Class jobClass,String cron 固定以外其他参数可以删除,可以新增//注意  Class jobClass  即为自己下边继承JOB接口的实体类try {SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");//设置任务的开始时间Date startDate = open_time;//设置任务的结束时间Date endDate = end_time;System.out.println("结束时间:"+endDate);Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();//指定要运行的任务,设置人物名,任务组名JobDetail jobDetail= JobBuilder.newJob(jobClass).withIdentity(jobName, jobGroupName).usingJobData("open_time",sdf.format(open_time)).//将参数存入jondetail中传递到voteJob中,借助  JobDataMap map = context.getJobDetail().getJobDataMap();*取出usingJobData("end_time",sdf.format(end_time)).usingJobData("open_time_join",sdf.format(open_time_join)).usingJobData("end_time_join",sdf.format(end_time_join)).usingJobData("id",id).build();//配置触发器//1新建一个触发器构造类TriggerBuilder<Trigger> triggerBuilder = TriggerBuilder.newTrigger();//2设置触发器名,触发器组名triggerBuilder.withIdentity(triggerName, triggerGroupName);//也可以在这里携带参数,方法与jobdetail中相同//设置任务立即执行//triggerBuilder.startNow();//设置任务开始时间triggerBuilder.startAt(startDate);//设置任务结束时间triggerBuilder.endAt(endDate);//3设置触发器时间规则triggerBuilder.withSchedule(CronScheduleBuilder.cronSchedule(cron));//4触发器构造类创建trigger对象CronTrigger trigger = (CronTrigger) triggerBuilder.build();//上边创建好的任务和构造器注入到调度器scheduler.scheduleJob(jobDetail, trigger);//全局监听scheduler.getListenerManager().addJobListener(new MyJobListener(),EverythingMatcher.allJobs());//局部监听//scheduler.getListenerManager().addJobListener(new MyJobListener(),KeyMatcher.keyEquals(JobKey.jobKey(jobName, jobGroupName)));//启动调度器if(!scheduler.isShutdown()) {scheduler.start();}//挂起定时任务//scheduler.standby();} catch (Exception e) {e.printStackTrace();}}
//修改定时任务cron表达式
public void modifyJobTime (String jobName,String jobGroupName,String triggerName,String triggerGroupName,String cron, Date open_time, Date end_time, Date open_time_join, Date end_time_join) {//该方法中除了String jobName,String jobGroupName,String triggerName,String triggerGroupName,String cron固定以外其他参数可以删除try {SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); //设置任务的开始时间Date startDate = open_time;//设置任务的结束时间Date endDate = end_time;Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();TriggerKey triggerKey = TriggerKey.triggerKey(triggerName,triggerGroupName);CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey);logger.info("定时任务组名:"+trigger);if(trigger == null) {logger.info("trigger为空:"+trigger);return;}String oldTime = trigger.getCronExpression();if(!oldTime.equalsIgnoreCase(cron)) {TriggerBuilder<Trigger> triggerBuilder = TriggerBuilder.newTrigger();triggerBuilder.withIdentity(triggerName,triggerGroupName).usingJobData("open_time",sdf.format(open_time)).usingJobData("end_time",sdf.format(end_time)).usingJobData("open_time_join",sdf.format(open_time_join)).usingJobData("end_time_join",sdf.format(end_time_join));//triggerBuilder.startNow();triggerBuilder.startAt(open_time);triggerBuilder.endAt(end_time);triggerBuilder.withSchedule(CronScheduleBuilder.cronSchedule(cron));trigger = (CronTrigger) triggerBuilder.build();scheduler.rescheduleJob(triggerKey, trigger);}} catch (Exception e) {e.printStackTrace();}}
//删除定时任务
public void removeJob(String jobName,String jobGroupName,String triggerName,String triggerGroupName) {try {Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();TriggerKey triggerKey = TriggerKey.triggerKey(triggerName,triggerGroupName);scheduler.pauseTrigger(triggerKey);//停止定时任务scheduler.unscheduleJob(triggerKey);//移除定时人体五scheduler.deleteJob(JobKey.jobKey(jobName, jobGroupName));//删除任务} catch (Exception e) {throw new   RuntimeException(e);}}
//启动所有定时任务
public void startJob() {try {Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();scheduler.start();} catch (Exception e) {throw new RuntimeException(e);}}
//关闭所有定时任务
public void shutdownJobs() {try {Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();if(!scheduler.isShutdown()) {/*** true等待所有job结束后关闭,false直接关闭不等待所有job结束* scheduler.shutdown(true);* scheduler.shutdown(false);*/scheduler.shutdown();}} catch (Exception e) {throw new RuntimeException(e);}}
//得到所有定时任务
public Scheduler getScheduler() {return scheduler;
}//写入定时任务
public void setScheduler(Scheduler scheduler) {this.scheduler = scheduler;
}
}

Vote工作类,将定时任务需要执行的代码放到这里,交给quartz管理到时间可以自动执行,

import java.text.SimpleDateFormat;
import java.util.Date;import org.quartz.Job;
import org.quartz.JobDataMap;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.quartz.JobKey;
import org.quartz.TriggerKey;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;import cn.com.sinosoft.service.FxActivityService;

public class VoteJob implements Job {
private Logger logger = LoggerFactory.getLogger(this.getClass());

@Autowired
private FxActivityService fxActivityService;@Override
public void execute(JobExecutionContext context) throws JobExecutionException {/*** 新增活动,加入到quartz中管理,定期执行,判断活动时间是否超期限,如果超过期限则修改活动状态*/logger.info("新增定时任务Vote");try {// 获取时间范围//对应quartzManager中传递过来的数据JobDataMap map = context.getJobDetail().getJobDataMap();*String open_time = (String) map.get("open_time");String end_time = (String) map.get("end_time");String open_time_join = (String) map.get("open_time_join");String end_time_join = (String) map.get("end_time_join");String id = (String) map.get("id");// 将字符串转换为dateSimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");Date open_times = sdf.parse(open_time);Date end_times = sdf.parse(end_time);Date open_time_joins = sdf.parse(open_time_join);Date end_time_joins = sdf.parse(end_time_join);Date nowtime = new Date();sdf.format(nowtime);//比较date大小,如果前端大于后边返回值为1,前边小于后边返回-1,相等返回0int compareTo = nowtime.compareTo(end_times);//当前时间等于结束时间,修改活动状态为无效JobKey jobKey = context.getJobDetail().getKey();logger.info("工作任务名称:"+jobKey.getName());logger.info("工作组名称:"+jobKey.getGroup());logger.info("任务类名称(全路径):"+context.getJobDetail().getJobClass().getName());logger.info("任务类名称:"+context.getJobDetail().getJobClass().getSimpleName());TriggerKey triggerKey = context.getTrigger().getKey();logger.info("触发器任务名称:"+triggerKey.getName());logger.info("触发器组名称:"+triggerKey.getGroup());if(compareTo == 1) {logger.info("到期自动结束定时任务");//修改活动状态为无效int u =  fxActivityService.updateActivityStates(id);if(u==1) {logger.info("修改任务状态成功");}}//比较开始和结束时间的大小判断活动是否有效} catch (Exception e) {logger.info("VoteJob逻辑异常");e.printStackTrace();}}}

注意:一个job可以对应多个trigger 但是一个trigger只能对应一个job

工具类

data和cron格式转换

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;import org.slf4j.Logger;
import org.slf4j.LoggerFactory;/**
* 该类提供Quartz的cron表达式与Date之间的转换
* Created by zhangzh on 2016/8/2.
*/
public class CronDateUtils {private static final String CRON_DATE_FORMAT = "ss mm HH dd MM ? yyyy";private static Logger logger = LoggerFactory.getLogger(CronDateUtils.class);/***** @param date 时间* @return  cron类型的日期*/public static String getCron(final Date  date){SimpleDateFormat sdf = new SimpleDateFormat(CRON_DATE_FORMAT);String formatTimeStr = "";if (date != null) {formatTimeStr = sdf.format(date);}return formatTimeStr;}/***** @param cron Quartz cron的类型的日期* @return  Date日期*/public static Date getDate(final String cron) {if(cron == null) {return null;}SimpleDateFormat sdf = new SimpleDateFormat(CRON_DATE_FORMAT);Date date = null;try {date = sdf.parse(cron);} catch (ParseException e) {logger.info("cron的类型的日期格式转换异常");return null;// 此处缺少异常处理,自己根据需要添加}return date; }}

进阶

初始化时候通过监听启动quartz

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.stereotype.Component;import cn.com.sinosoft.controller.QuartzManager;
import cn.com.sinosoft.po.Vote;
import cn.com.sinosoft.quartz.job.VoteJob;
import cn.com.sinosoft.service.FxActivityService;
import cn.com.sinosoft.service.VoteService;
import cn.com.sinosoft.util.CronDateUtils;
@Component
public class IniterListener implements ApplicationListener<ContextRefreshedEvent>{private Logger logger = LoggerFactory.getLogger(this.getClass());@Autowiredprivate FxActivityService fxActivityService;@Autowiredprivate VoteService voteService;@Overridepublic void onApplicationEvent(ContextRefreshedEvent arg0) {logger.info("bean容器初始化完成之后执行");try {//查询数据库中所有的活动,判断活动的有效状态,超期的置为无效,//Vote vote = new Vote();List<Vote> v = voteService.selectAllVoteForUsers();for(Vote votes : v) {Date date = new Date();SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");//当前系统时间Date d = sdf.parse(sdf.format(date));//Date open = sdf.parse(votes.getOpen_time());Date end = sdf.parse(votes.getEnd_time());//当前时间大于等于结束时间int i = d.compareTo(end);if(i==1||i==0) {//修改当前活动状态置为无效int j = fxActivityService.updateActivityStates(votes.getId());if(j==1) {logger.info("修改活动状态成功");}else {logger.info("修改活动状态失败,失败的活动名称为:"+votes.getId()+"名称:"+votes.getName());}}//截止时间大于当前时间,同时活动状态为有效if(i==-1&&votes.getStatus().equals("0")) {logger.info("添加活动到qz:活动名称为:"+votes.getName());//有效活动添加到qz中执行QuartzManager qm = new QuartzManager();qm.addJob(votes.getName(), "group"+votes.getName(), "trigger"+votes.getName(), "triggerGroup"+votes.getName(), VoteJob.class,CronDateUtils.getCron(sdf.parse(votes.getEnd_time())),sdf.parse(votes.getOpen_time()), sdf.parse(votes.getEnd_time()),sdf.parse(votes.getOpen_time_join()),sdf.parse(votes.getEnd_time_join()),votes.getId());}else {logger.info("无效活动名称为:"+votes.getName());}}//未超期的活动注入到qz中动态加载} catch (Exception e) {// TODO Auto-generated catch blocke.printStackTrace();}
}}

在springmvc.xml中注入监听

<context:component-scan base-package="cn.com.sinosoft.controller"></context:component-scan>
<!-- 初始化完成之后执行监听   bean中为监听器路径    -->
<bean class="cn.com.sinosoft.lisener.IniterListener"/>

拓展

### 类似java定时任务,固定时间间隔执行定时任务,使用simpleScheduler调度器来执行import org.quartz.CronScheduleBuilder;
import org.quartz.CronTrigger;
import org.quartz.JobBuilder;
import org.quartz.JobDetail;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.quartz.JobKey;
import org.quartz.JobListener;
import org.quartz.Scheduler;
import org.quartz.SchedulerFactory;
import org.quartz.SimpleScheduleBuilder;
import org.quartz.Trigger;
import org.quartz.TriggerBuilder;
import org.quartz.TriggerKey;
import org.quartz.impl.StdSchedulerFactory;
import org.quartz.impl.matchers.EverythingMatcher;
import org.quartz.impl.matchers.KeyMatcher;
import org.springframework.beans.factory.annotation.Autowired;import com.sun.net.ssl.KeyManager;import cn.com.sinosoft.lisener.MyJobListener;public class QuartzManagerSimple {private static SchedulerFactory schedulerFactory = new StdSchedulerFactory();
/*** @Description: 添加一个定时任务** @param jobName 任务名* @param jobGroupName  任务组名* @param triggerName 触发器名* @param triggerGroupName 触发器组名* @param jobClass  任务* @param cron   时间设置,参考quartz说明文档*/
@SuppressWarnings({ "unchecked", "rawtypes" })
public  void addJob(String jobName, String jobGroupName,String triggerName, String triggerGroupName, Class jobClass, String cron) {try {//调度器,从工厂中获取调度实例,默认new stschedulerFactory()Scheduler sched = StdSchedulerFactory.getDefaultScheduler();//sched.setJobFactory(myJobFactory);// 任务名,任务组,任务执行类JobDetail jobDetail= JobBuilder.newJob(jobClass).withIdentity(jobName, jobGroupName).usingJobData("message","测试jobdateMap").build();//logger.info("名称:"+ jobDetail.getKey().getName());//logger.info("组名称:"+ jobDetail.getKey().getGroup());//logger.info("任务类:"+ jobDetail.getKey().getClass());// 触发器TriggerBuilder<Trigger> triggerBuilder = TriggerBuilder.newTrigger();// 触发器名,触发器组triggerBuilder.withIdentity(triggerName, triggerGroupName).usingJobData("triggerMessage","trigger中传递的参数");triggerBuilder.startNow();//马上启动// 触发器时间设定//triggerBuilder.withSchedule(CronScheduleBuilder.cronSchedule(cron));triggerBuilder.withSchedule(SimpleScheduleBuilder.simpleSchedule().repeatSecondlyForever(5).withRepeatCount(3));//5s重复执行,执行三次// 创建Trigger对象//CronTrigger trigger = (CronTrigger) triggerBuilder.build();Trigger trigger = triggerBuilder.build();// 调度容器设置JobDetail和Triggersched.scheduleJob(jobDetail, trigger);//每次新建任务之后设置监听属性//全局监听//sched.getListenerManager().addJobListener(new MyJobListener(),EverythingMatcher.allJobs());//局部监听//sched.getListenerManager().addJobListener(new MyJobListener(),KeyMatcher.keyEquals(JobKey.jobKey(jobName, jobGroupName)));// 启动if (!sched.isShutdown()) {sched.start();}} catch (Exception e) {throw new RuntimeException(e);}
}/*** @Description: 修改一个任务的触发时间** @param jobName* @param jobGroupName* @param triggerName 触发器名* @param triggerGroupName 触发器组名* @param cron   时间设置,参考quartz说明文档*/
public  void modifyJobTime(String jobName,String jobGroupName, String triggerName, String triggerGroupName, String cron) {try {Scheduler sched = schedulerFactory.getScheduler();//sched.setJobFactory(myJobFactory);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);}
}/*** @Description: 移除一个任务** @param jobName* @param jobGroupName* @param triggerName* @param triggerGroupName*/
public  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  void startJobs() {try {Scheduler sched = schedulerFactory.getScheduler();sched.start();} catch (Exception e) {throw new RuntimeException(e);}
}/*** @Description:关闭所有定时任务*/
public  void shutdownJobs() {try {Scheduler sched = schedulerFactory.getScheduler();if (!sched.isShutdown()) {sched.shutdown();}} catch (Exception e) {throw new RuntimeException(e);}
}
}

quartz SpringMvc 动态定时任务(quartz2.2)相关推荐

  1. java 定时任务插件_详解Spring整合Quartz实现动态定时任务

    最近项目中需要用到定时任务的功能,虽然spring 也自带了一个轻量级的定时任务实现,但感觉不够灵活,功能也不够强大.在考虑之后,决定整合更为专业的Quartz来实现定时任务功能. 普通定时任务 首先 ...

  2. Quartz实现动态定时任务

    一. 说明 由于最近工作要实现定时任务的执行,而且要求定时周期是不固定的,所以就用到了quartz来实现这个功能: spring3.1以下的版本必须使用quartz1.x系列,3.1以上的版本才支持q ...

  3. springboot和quartz整合实现动态定时任务(持久化单节点)

    Quartz是一个完全由java编写的开源作业调度框架,为在Java应用程序中进行作业调度提供了简单却强大的机制,它支持定时任务持久化到数据库,从而避免了重启服务器时任务丢失,支持分布式多节点,大大的 ...

  4. Quartz在Spring中设置动态定时任务 .

    什么是动态定时任务: 是由客户制定生成的,服务端只知道该去执行什么任务,但任务的定时是不确定的(是由客户制定).这样总不能修改配置文件每定制个定时任务就增加一个trigger吧,即便允许客户修改配置文 ...

  5. Quartz在Spring中动态设置cronExpression (spring设置动态定时任务)

    2019独角兽企业重金招聘Python工程师标准>>> 什么是动态定时任务:是由客户制定生成的,服务端只知道该去执行什么任务,但任务的定时是不确定的(是由客户制定). 这样总不能修改 ...

  6. java quartz 动态执行,浅谈SpringBoot集成Quartz动态定时任务

    SpringBoot自带schedule 沿用的springboot少xml配置的优良传统,本身支持表达式等多种定时任务 注意在程序启动的时候加上@EnableScheduling @Schedule ...

  7. Spring 3整合Quartz 2实现定时任务--转

    常规整合 http://www.meiriyouke.net/?p=82 最近工作中需要用到定时任务的功能,虽然Spring3也自带了一个轻量级的定时任务实现,但感觉不够灵活,功能也不够强大.在考虑之 ...

  8. Spring 3整合Quartz 2实现定时任务(转)

    http://www.meiriyouke.net/?p=82 最近工作中需要用到定时任务的功能,虽然Spring3也自带了一个轻量级的定时任务实现,但感觉不够灵活,功能也不够强大.在考虑之后,决定整 ...

  9. Quartz SpringMvc Mybatis操作数据库异常

    Quartz SpringMvc Mybatis操作数据库,空指针(nullpointexception)异常 quartz动态定时任务在执行时是以线程的形式在后台定期执行,Mybatis链接数据库基 ...

最新文章

  1. git push 的符号笔有什么用_Git 标签(tag)作用、分支区别及常用命令
  2. 在Completablefuture和Observable之间转换
  3. java ecdh秘钥交换_DH密钥交换和ECDH原理(转)
  4. Java发送Post请求,参数JSON,接收JSON
  5. android用sax解析xml,详解android使用SAX解析XML文件
  6. Java 多线程 - 线程 - 守护线程
  7. c++语言取整为什么要加0.5_蛋鸡饲料要加石粉,那你知道为什么加?要加什么石粉?我来告诉你...
  8. 谋哥:这个时代没有比程序员更适合创业
  9. 聚类-----KMeans
  10. mysql 查看事件_Mysql中的事件
  11. 人生之路1.20代码 第二部分
  12. Oblog 4.5-4.6 accessmssql getshell 0day
  13. 快速找回WINDOWS 7快速启动栏
  14. 易语言清理IEcookies 缓存等 可用于IE清理cookies
  15. Pixelmator for Mac(强大的图像处理软件)
  16. Python爬虫爬取表情包
  17. MIMO-UNet学习
  18. 【Zookeeper】分布式集群(详细图文)
  19. Markdown进阶
  20. 数据分析师是否是青春饭,对年龄有限制吗?

热门文章

  1. 自定义alert提示框
  2. javascript单元测试:jasminejs 2.0的烦恼
  3. 7.1.8860.142
  4. mkhd中的matrix
  5. 《又见一帘幽梦》高清视频
  6. readyState属性和status属性
  7. phpstudy 启动mysql服务问题
  8. Dex文件格式扫描器:特征API的检测和扫描-小工具一枚(转载)
  9. C++中公有继承、保护继承、私有继承
  10. python中{%%}在HTML中的用法