Job作业调度(导入文件多条商品,在前台进度条显示)

来源:互联网 发布:云存储的元数据是什么 编辑:程序博客网 时间:2024/06/04 19:49

我接触的实际情况是excel文件导入多条商品功能,但是导入可能花费一定的时间,我们就想根据导入的数据做一个进度条,并且可以显示导入第几条,每导入一条,就显示相应的信息。

这里我们就用了作业调度,通过一个Job不断的运行,将我们的‘作业’放在job中,进行一个监控和访问。

我们使用quartz这一技术

那么我们需要一个作业调度器,然后set相应的作业,进行操作。

获取quartz的核心类

Scheduler scheduler = ApplicationContextUtils.getBean(DEFAULT_SCHEDULER_ID);

进行多任务的分组(相当于一个载体,用来存,是哪个作业,作业名称,返回的结果也在其中)

JobScheduleHandler handler = new JobScheduleHandler((String) params.get(ImpexConstants.PN_PLUGINNAME), jobCls.getSimpleName() + UUIDGenerator.getUUID());

// 为了支持并发多任务需要制定不同分组

我们new 一个作业

JobKey jobKey = new JobKey(handler.getName(), handler.getGroup());

如果作业调度已经执行过的作业,直接将调度去set到handle中 (context是作业任务的上下文),这里主要是有一些参数返回值,放到handler。

if (scheduler.checkExists(jobKey)) {        for (JobExecutionContext context : scheduler.getCurrentlyExecutingJobs()) {          if (jobKey.equals(context.getJobDetail().getKey())) {            handler.setScheduled(context.getFireTime());            break;          }        }

如果是新的任务,需要将参数设置到上下文。

       (jobCls是具体实现的作业)

        JobDetail jobDetail = JobBuilder.newJob(jobCls).withIdentity(jobKey).build();        for (Map.Entry<String, Object> entry : params.entrySet()) {          jobDetail.getJobDataMap().put(entry.getKey(), entry.getValue());        }        jobDetail.getJobDataMap().put(ImpexConstants.PN_OPERCTX, JsonUtil.objectToJson(operCtx));        Trigger trigger = TriggerBuilder.newTrigger().startNow().build();  //此处就是开始执行作业        scheduler.scheduleJob(jobDetail, trigger);
最后将执行后的handler返回,这里返回到界面,界面就可以收到改执行时间进行结构返回,包括第几条,等各种信息。
        handler.setScheduled(StringUtil.toDate(          new SimpleDateFormat(JsonUtil.DATE_FORMAT).format(handler.getScheduled()),          StringUtil.DATE_FORMATS[1]));        return handler;


这里是springMVC接受请求的controller这样收到请求和执行的

 @RequestMapping(value = "importForStandard", method = RequestMethod.POST)  public @ResponseBody JobScheduleHandler importForStandard(@RequestBody ImpexParams params)      throws Hdpos4ServiceException {    Map<String, Object> paramsMap = new HashMap<String, Object>();    paramsMap.put(ImpexConstants.PN_LANG, Hdpos4Util.getSysLang());    paramsMap.put(ImpexConstants.PN_PLUGINNAME, params.getPluginName());    paramsMap.put(ImpexConstants.PN_MAXCOUNT, params.getMaxCount());    paramsMap.put(ImpexConstants.PN_FILEURLS, params.getFileUrls());    return JobScheduler.schedule(DiralcImportJob.class, paramsMap, getBeanOperateContext());  }

我们会Return也就是上面的handler

里面的DiralcImportJob,就是具体要执行的job(作业)


而作业当中,比如如何拿到参数等等需要一些基类,将context上下文设置进去。这些公共的方法就在基类中实现。

其中包含一些中断功能

public abstract class AbstractJob implements InterruptableJob {  private static final Logger logger = LoggerFactory.getLogger(AbstractJob.class);  private JobExecutionContext context;  @Override  public void execute(JobExecutionContext context) throws JobExecutionException {    JobContext.initial(context);    this.context = context;    try {      preProcess();      doExecute();      postProcess(JobInstanceResult.completed, null);    } catch (InterruptedException e) {      postProcess(JobInstanceResult.interrupted, e);    } catch (Exception e) {      postProcess(JobInstanceResult.aborted, e);    } finally {      JobContext.free();    }  }  /**   * 执行作业。   */  protected abstract void doExecute() throws InterruptedException, Exception;  /**   * 取得作业结果通知器对象。<br>   * 子类开发者可以通过重写此方法,实现发出作业执行结果通知的功能。   *    * @return 返回null将不会发出通知。   */  protected JobNotifier getNotifier() {    return null;  }  @Override  public void interrupt() throws UnableToInterruptJobException {    logger.info("Try to interrupt the job.");    JobContext.interrupt(context);  }  /**   * 预处理。在{@link #doExecute()}之前被调用。   */  protected void preProcess() {    assert context != null;    saveForStartingJob(context);  }  /**   * 后处理。在{@link #doExecute()}之后被调用。   *    * @param result   *          作业执行结果。禁止传入null。   * @param e   *          异常对象。   * @throws IllegalArgumentException   *           当参数result为null时抛出。   */  protected void postProcess(JobInstanceResult result, Exception e) throws IllegalArgumentException {    assert context != null;    Assert.assertArgumentNotNull(result, "result");    log(result, e);    saveForFinishingJob(context, result);    notify(result, e);  }  private void log(JobInstanceResult result, Exception e) {    if (JobInstanceResult.completed.equals(result)) {      logger.info("Job Completed.");    } else if (JobInstanceResult.interrupted.equals(result)) {      logger.info("Job Interrupted.");    } else if (JobInstanceResult.aborted.equals(result)) {      logger.error("Job Aborted.", e);    } else {      assert false;    }  }  private void saveForStartingJob(JobExecutionContext context) {    assert context != null;    try {      PJobInstance jobInstance = new PJobInstanceConverter().convert(context);      PJobInstanceDao jobInstanceDao = DaoFactory.getInstance().getJobInstanceDao();      jobInstanceDao.save(jobInstance);    } catch (Exception e) {      logger.error("Fail to save for starting job.", e);    }  }  private void saveForFinishingJob(JobExecutionContext context, JobInstanceResult result) {    assert context != null;    assert result != null;    try {      PJobInstance jobInstance = new PJobInstanceConverter().convert(context);      jobInstance.setState(JobInstanceState.over);      jobInstance.setFinishedAt(new Date());      jobInstance.setResult(result);      PJobInstanceDao jobInstanceDao = DaoFactory.getInstance().getJobInstanceDao();      jobInstanceDao.save(jobInstance);    } catch (Exception e) {      logger.error(MessageFormat.format("Fail to save for finishing job: {0}.", result), e);    }  }  private void notify(JobInstanceResult result, Exception caught) {    assert result != null;    JobNotifier notifier = getNotifier();    if (notifier == null) {      return;    }    try {      notifier.nodify(result, caught, context);    } catch (Exception e) {      logger.error("Fail to notify.", e);    }  }}







      

0 0
原创粉丝点击