2020-03-16 12:54

@JFinal 倒也是,依赖太多违背精简思想,但是插件机制不知是否有问题,
现在有个bug,用JfinalConfig配置注册插件quartz调度不行,而且启动时也不报错,日志也是DEBUG等级

/**
* 配置插件
*/
public void configPlugin(Plugins me) {
QuartzPlugin quartz = new QuartzPlugin();
me.add(quartz);
}

但是改在main 调用就可以,太诡异。。。

/**
* 启动入口,运行此 main 方法可以启动项目
*/
public static void main(String[] args){
UndertowServer.start(AppConfig.class);

QuartzPlugin quartz = new QuartzPlugin();
quartz.start();
}

2020-03-16 10:17

@JFinal 波总,主要Cron4jPlugin 不支持秒级调度,不然肯定首选官方插件啊。波总秒级调度还是比较常见的场景啊

2020-03-15 15:29

任务死活不执行,找了半天没找到原因,求助大佬 @JFinal @埋头苦干


====================== QuartzPlugin =====================

package com.wjme.app.job.plugin;

import com.jfinal.kit.LogKit;
import com.jfinal.kit.PropKit;
import com.jfinal.kit.StrKit;
import com.jfinal.plugin.IPlugin;
import org.quartz.*;
import org.quartz.impl.StdSchedulerFactory;

import java.util.ArrayList;
import java.util.List;
import java.util.Properties;

public class QuartzPlugin implements IPlugin {
private List jobs = new ArrayList();
private SchedulerFactory sf;
public static Scheduler scheduler;
private String jobConfig;
private String confConfig;
private Properties jobProp;

public QuartzPlugin(String jobConfig, String confConfig) {
this.jobConfig = jobConfig;
this.confConfig = confConfig;
}

public QuartzPlugin(String jobConfig) {
this.jobConfig = jobConfig;
this.confConfig = "quartz.properties";
}

public QuartzPlugin() {
this.jobConfig = "quartz.properties";
this.confConfig = "quartz.properties";
}

public static void addJob(JobBean job) {
try {
TriggerKey triggerKey = TriggerKey.triggerKey(job.getJobDesc(), job.getJobGroup());
CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey);
// 不存在,创建一个
if (null == trigger) {
Class j2 = (Class) Class.forName(job.getJobClass());
JobDetail jobDetail = JobBuilder.newJob(j2).withIdentity(job.getJobDesc(), job.getJobGroup()).build();
jobDetail.getJobDataMap().put("scheduleJob", job);

// 表达式调度构建器
CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(job.getCronExpression());

// 按新的cronExpression表达式构建一个新的trigger
trigger = TriggerBuilder.newTrigger().withIdentity(job.getJobDesc(), job.getJobGroup())
.withSchedule(scheduleBuilder).build();
try {
scheduler.scheduleJob(jobDetail, trigger);
} catch (Exception e) {
e.printStackTrace();
LogKit.error("", e);
}
} else {
// Trigger已存在,那么更新相应的定时设置
// 表达式调度构建器
CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(job.getCronExpression());

// 按新的cronExpression表达式重新构建trigger
trigger = trigger.getTriggerBuilder().withIdentity(triggerKey).withSchedule(scheduleBuilder).build();

// 按新的trigger重新设置job执行
scheduler.rescheduleJob(triggerKey, trigger);
}
} catch (Exception e) {
e.printStackTrace();
LogKit.error("", e);
}
}

@Override
public boolean start() {
loadJobsFromProperties();
startJobs();
return true;
}

private void startJobs() {
try {
if (StrKit.notBlank(confConfig)) {
sf = new StdSchedulerFactory(confConfig);
} else {
sf = new StdSchedulerFactory();
}
scheduler = sf.getScheduler();
} catch (SchedulerException e) {
e.printStackTrace();
LogKit.error("", e);
}
for (JobBean entry : jobs) {
addJob(entry);
}
try {
scheduler.start();
} catch (SchedulerException e) {
e.printStackTrace();
LogKit.error("", e);
}
}

private void loadJobsFromProperties() {
if (StrKit.isBlank(jobConfig)) {
return;
}

jobProp = PropKit.use(jobConfig).getProperties();
String jobArray = PropKit.use(jobConfig).get("jobArray");
if (StrKit.isBlank(jobArray)) {
return;
}
String[] jobArrayList = jobArray.split(",");
for (String jobName : jobArrayList) {
jobs.add(createJobBean(jobName));
}
}

private JobBean createJobBean(String key) {
JobBean job = new JobBean();
job.setJobGroup(key);
job.setJobClass(jobProp.getProperty(key + ".job" , ""));
job.setCronExpression(jobProp.getProperty(key + ".cron" , ""));
job.setJobDesc(jobProp.getProperty(key + ".desc" , ""));
return job;
}

@Override
public boolean stop() {
try {
scheduler.shutdown();
} catch (SchedulerException e) {
e.printStackTrace();
LogKit.error("", e);
}
return true;
}
}



============ job 类====================


package com.wjme.app.job;

import com.jfinal.kit.HttpKit;
import com.jfinal.kit.JsonKit;
import com.jfinal.kit.PropKit;
import com.jfinal.server.undertow.UndertowConfig;
import com.wjme.App;
import com.wjme.app.busi.DataInfo;
import com.wjme.app.util.DES3Util;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class AutoIP implements Job {

Logger log = LoggerFactory.getLogger(getClass());

private static String currIP = "";
private String serverPath = PropKit.get("serverPath");
private String clientPath = PropKit.get("clientPath");
private int cPort = new UndertowConfig(App.class).getPort();
private int port =PropKit.getInt("clientPort", cPort);
private boolean clientRedirect =PropKit.getBoolean("clientPort", false);

@Override
public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
System.out.println("xxxxx");


}
}



===============JfinalConfig ====================


/**
* 配置插件
*/
public void configPlugin(Plugins me) {

QuartzPlugin quartz = new QuartzPlugin();
me.add(quartz);

}

=================quartz.properties ======================

#开启的任务列表“,”隔开
jobArray = autoip


autoip.job=com.wjme.app.job.AutoIP
autoip.cron= 0/10 * * * * ?
autoip.desc=autoip




#============================================================================
# 配置主要调度程序属性
#============================================================================
org.quartz.scheduler.instanceName = DefaultQuartzScheduler
org.quartz.scheduler.instanceId = AUTO
org.quartz.scheduler.rmi.export = false
org.quartz.scheduler.rmi.proxy = false
org.quartz.scheduler.wrapJobExecutionInUserTransaction = false

#============================================================================
# 配置线程池
#============================================================================
org.quartz.threadPool.threadCount = 5
org.quartz.threadPool.threadPriority = 5

#============================================================================
# 配置任务
#============================================================================
org.quartz.jobStore.misfireThreshold = 1800
org.quartz.scheduler.skipUpdateCheck = true

2017-09-30 08:57

@JFinal 框架中应该蛮多地方可以加一些的

2017-09-30 08:56

@JFinal 建议波总默认多加一些序列化的实现,如

/**
* 验证码
*/
public class Captcha 类

在做一些服务化框架和缓存处理时没办法直接用,还需创建子类再实现序列化使用

2017-09-28 15:05

@JFinal 哈哈,已采用如下方式:

public void afterJFinalStart() {
try {
JFinal.me().getConstants().setCaptchaCache(new RedisCaptchaCache());
RedisCaptchaCache.setCaptchaCache(Redis.use("captcha"));

} catch (TemplateModelException e) {
e.printStackTrace();
}
}