jeecg-boot-2.3使用心得
jeecg-boot
公司发展了3年,大大小小很多项目都没有形成统一的前后台脚手架方案,随之而来的问题项目中功能同质化比较严重,后期很难维护,所以决定寻找一个统一的脚手架方案方便开发的统一,公司李总发来一些开源的产品,花点时间研究了下决定其中有一个就是jeecg-boot挺有意思的,且目前还支持微服务方案,使用了一段时间后还是发型了其中有些不足
任务调度功能的建议
springboot的方案中只有system一个模块,里面集成了quartz的任务调度功能,任务的创建,执行都只能在system系统中完成,如果升级成微服务方案,增加其他的微服务模块后,其他的微服务模板无法完成任务的调度,目前的建议:
- quartz从sytem中剥离出来形成一个独立的任务调度微服务;
- 配置任务的表结构需要增加实例ID字段,用于保存任务所在的微服务
- 任务调度微服务通过Feign调度各微服务的任务代码;
具体实施方案
- 需要增加两个maven工程:quartz-api、quartz-client供微服务依赖
- 微服务实现quartz-api中的IJob接口
- Quartz Scheduler任务表添加了任务所在的微服务实例,任务类名,任务参数
- 统一由Quartz Scheduler中的MasterQuartzJob调度
- 这些参数通过Feign调用quartz-client中的IJobCloudController
- quartz-client中的IJobCloudController再通过接收到的参数调用具体的任务实现
主要代码:
quartz-api: IJob
/**
* Slave Job be implemented by client
*/
public interface IJob {
void run(String jobParams);
}
微服务: TestIJob
@Slf4j
public class TestIJob implements IJob {
@Override
public void run(String jobParams) {
log.info("TestIJob");
}
}
quartz-client: IJobCloudController
@Slf4j
@RestController
public class IJobCloudController {
@Resource
private ApplicationContext applicationContext;
@PostMapping(value = "/runJob")
public @ResponseBody JobResult runJob(@RequestParam("iJobClass") String iJobClass, @RequestParam("jobParams") String jobParams) {
JobResult result = JobResult.value(JobState.CALLED);
try {
IJob job = (IJob)applicationContext.getBean(Class.forName(iJobClass));
job.run(jobParams);
} catch (Exception e) {
log.error("Exception", e);
result = JobResult.value(JobState.CALL_EXEP, ExceptionUtils.getStackTrace(e));
}
return result;
}
}
Quartz Scheduler: MasterQuartzJob
@Slf4j
@SuppressWarnings("unchecked")
public class MasterQuartzJob extends QuartzJobBean {
@Override
protected void executeInternal(JobExecutionContext jobExecutionContext) throws JobExecutionException {
// 获取参数
JobDataMap jobDataMap = jobExecutionContext.getJobDetail().getJobDataMap();
String jobName = (String)jobDataMap.get("jobName");
String serviceId = (String)jobDataMap.get("serviceId");
String iJobClass = (String)jobDataMap.get("iJobClass");
String jobParams = (String)jobDataMap.get("jobParams");
JobResult result = JobResult.value(JobState.CALLED);
try {
Class<IJob> jobClass = (Class<IJob>) Class.forName(iJobClass);
IJob job = SpringExBeanUtil.getBean(jobClass);
job.run(jobParams);
} catch (Exception e1) {
log.warn("Exception("+JSONObject.toJSONString(jobDataMap)+") "+ e1);
try {
IJobCloudFeignService jobService = SpringExBeanUtil.getBean(IJobCloudFeignService.class);
result = jobService.runJob(serviceId, iJobClass, jobParams);
} catch (Exception e) {
log.error("Exception("+JSONObject.toJSONString(jobDataMap)+")", e);
result = JobResult.value(JobState.FAIL, ExceptionUtils.getStackTrace(e));
}
}
log.info("{}, {}, {} => {}", serviceId, jobName, iJobClass, result);
}
}
Quartz Scheduler: IJobCloudFeignService
@Service
public class IJobCloudFeignService {
@Autowired
private Feign.Builder builder;
public JobResult runJob(String serviceId, String iJobClass, String jobParams) {
IJobCloudFeignClient client = builder.target(IJobCloudFeignClient.class, "http://" + serviceId);
return client.runJob(iJobClass, jobParams);
}
}