您的位置:首页 > 编程语言 > Java开发

任务管理模块 quartz + spring

2011-12-18 20:33 162 查看


任务管理模块的需求:实现对任务的crud操作,定时执行,以及执行结果的查看。由于涉及到CRUD操作,因此持久化是必须的。关于quartz持久化的配置,有很多文章可以参考,这里就不说了,本文主要谈谈持久化实现和其中一些很少有人提及的问题。

1. CRUD操作的实现

对于用ssh框架习惯的人来说,一提到CRUD,hibernate就是当仁不让的选择。笔者想说的是quartz已经完成的事情,为啥你非得再去做一次呢? 事实上只要配置好quartz的store,scheduler一操作jobdetail或trigger,scheduler的内存变化就会反映到数据库里。因此,CUD的操作,通过scheduler进行即可。这里比较麻烦的是R的操作该怎么处理。有两种选择: 1.仍然用scheduler,通过一系列的get****方法去取得jobdetail和trigger的信息,封装后再传到页面;2.使用jdbcTemplate或者hsql直接查询数据库。

第一种方法比较简单,但实现相对繁琐;第二种虽然很容易,但又涉及到一个问题:如何读取blob字段?blob字段对于jobdetail来说存放的是jobdatamap的数据,所以读取blob字段是跳不过的一环。既然,quartz已经实现了持久化,当然这个问题也解决了,因此将quartz的类拿来修改下就可以了,不过quartz是通过resultset来实现的,所以最后笔者选择了jdbc这个最原始的东东。

        DriverManagerDataSource dd =(DriverManagerDataSource)webContext.getBean("dataSource1");

blob的处理可以参考quartz中org.quartz.impl.jdbcjobstore.StdJDBCDelegate的源代码,这里将主要的方法提取出来:

public class BlobDataDelagte {

    public Object getObjectFromBlob(ResultSet rs, String colName)

    throws ClassNotFoundException, IOException, SQLException {

     Object obj = null;

 

     Blob blobLocator = rs.getBlob(colName);

     if (blobLocator != null && blobLocator.length() != 0) {

         InputStream binaryInput = blobLocator.getBinaryStream();

 

         if (null != binaryInput) {

             if (binaryInput instanceof ByteArrayInputStream

                 && ((ByteArrayInputStream) binaryInput).available() == 0 ) {

                 //do nothing

             } else {

                 ObjectInputStream in = new ObjectInputStream(binaryInput);

                 try {

                     obj = in.readObject();

                 } finally {

                     in.close();<
4000
br />
                 }

             }

         }

 

     }

     return obj;

 }   

    protected Object getJobDataFromBlob(ResultSet rs, String colName)

    throws ClassNotFoundException, IOException, SQLException {

     if (true) {

         Blob blobLocator = rs.getBlob(colName);

         if (blobLocator != null) {

             InputStream binaryInput = blobLocator.getBinaryStream();

             return binaryInput;

         } else {

             return null;

         }

     }

 

     return getObjectFromBlob(rs, colName);

 }

   

    protected Map<?, ?> convertFromProperty(Properties properties) throws IOException {

        return new HashMap<Object, Object>(properties);

    }

    public Map<?, ?> getMapFromProperties(ResultSet rs, String colName)

    throws ClassNotFoundException, IOException, SQLException {

     Map<?, ?> map;

     InputStream is = (InputStream) getJobDataFromBlob(rs, colName);

     if(is == null) {

         return null;

     }

     Properties properties = new Properties();

     if (is != null) {

         try {

             properties.load(is);

         } finally {

             is.close();

         }

     }

     map = convertFromProperty(properties);

     return map;

 } 

 /**

  * @param args

  */

 public static void main(String[] args) {

  // TODO Auto-generated method stub

 }

}

调用方法如下:

Map<?, ?> map = (Map<?, ?>)   new BlobDataDelagte().getObjectFromBlob(rs, "JOB_DATA");

String tbean =(String)map.get("targetBean");

2. quartz调度 非JOBDETAIL类

quartz调度非JOBDETAIL类,在很多文章都有提及,使用spring的org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean类封装下就可以了。但是

一涉及到quartz持久化的时候,这个类会抛异常:

Caused by: java.io.NotSerializableException: Unable to serialize JobDataMap for insertion into database because the value of property 'methodInvoker' is not serializable: org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean

这个异常的意思就是MethodInvokingJobDetailFactoryBean不支持持久化功能。解决办法:

http://jira.springframework.org/browse/SPR-3797 下载两个文件:

frameworkx.springframework.scheduling.quartz.BeanInvokingJobDetailFactoryBean

frameworkx.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean

这两个class有着不同的应用,对于BeanInvokingJobDetailFactoryBean来说,它可以触发非静态的方法;

而MethodInvokingJobDetailFactoryBean可以触发静态和非静态方法。由于这两个类都是用来改进MethodInvokingJobDetailFactoryBean的,因此对要调用的javabean的查找都是通过applicationContext进行的,因此在使用过程中需要做些修正,在applicationContext找不到javabean的情况下,需要通过反射机制来创建javabean。

 Object bean =null;

    try

    {

     bean = applicationContext.getBean(targetBean);

    }

    catch(Exception e)

    {

     if (bean==null)

     {

      bean =Class.forName(targetBean).newInstance();

     } 

     

    }

3.执行结果的查看

对于用户来说,一个很好的体验就是能够跟踪和了解任务的执行情况和结果。这个属于quartz的题外话,quartz 自身并不提供查看执行结果的功能。若要实现,需要自己处理,这里需要考量两个问题:对于像邮件通知、短信提醒这样的类要怎么提供自身的执行情况和进度?对于数据库存储过程要怎么提供自身的执行情况和进度? 一个最简单的办法就是在数据库建这样的表,然后相关任务类、存储过程不断对这个表进行添加和更新操作,在页面上通过轮询来获取 任务的执行情况和结果。这里只简单的用ORACLE的查询结果进行展示:

 


 4. XML的持久化数据

 使用spring的人都很熟悉怎么使用XML配置各类javabean,但是很少有人会提及将spring容器内的javabean的最新变动存回xml,quartz的数据虽然已经持久化在数据表里了,但是还是有必要将变动情况也存放在XML文件里,毕竟大家都晓得:“不要把所有鸡蛋都放在同一个篮子里”。对于XML的读写,有很多文章可以借鉴,这里不详述了,只是提供个思路,仅供参考。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息