作者归档:Rick

认识消息中间件

原文转载http://www.uml.org.cn/j2ee/2009008071.asp

1、消息中间件是什麽 

   消息中间件是指利用高效可靠的消息传递机制进行平台无关的数据交流,并基于数据通信来进行分布式系统的集成。通过提供消息传递和消息排队模型,它可以在分布式环境下扩展进程间的通信。 
消息中间件可以即支持同步方式,又支持异步方式。异步中间件比同步中间件具有更强的容错性,在系 统故障时可以保证消息的正常传输。异步中间件技术又分为两类:广播方式和发布/订阅方式。由于发布/订阅方式可以指定哪种类型的用户可以接受哪种类型的消 息,更加有针对性,事实上已成为异步中间件的非正式标准。 

2、消息中间件原理 

    面向消息的中间件(MOM),提供了以松散耦合的灵活方式集成应用程序的一种机制。它们提供了基 于存储和转发的应用程序之间的异步数据发送,即应用程序彼此不直接通信,而是与作为中介的MOM通信。MOM提供了有保证的消息发送(至少是在尽可能地做 到这一点),应用程序开发人员无需了解远程过程调用(PRC)和网络/通信协议的细节。 

2.1 消息中间件简介 

    消息中间件利用高效可靠的消息传递机制进行平台无关的数据交流,并基于数据通信来进行分布式系统的集成。通过提供消息传递和消息排队模型,它可以在分布式环境下扩展进程间的通信。 
    消息中间件适用于需要可靠的数据传送的分布式环境。采用消息中间件机制的系统中,不同的对象之间通过传递消息来激活对方的事件,完成相应的操作。发送者将 消息发送给消息服务器,消息服务器将消息存放在若干队列中,在合适的时候再将消息转发给接收者。消息中间件能在不同平台之间通信,它常被用来屏蔽掉各种平 台及协议之间的特性,实现应用程序之间的协同,其优点在于能够在客户和服务器之间提供同步和异步的连接,并且在任何时刻都可以将消息进行传送或者存储转 发,这也是它比远程过程调用更进一步的原因。 
如下图所示,应用程序A与应用程序B通过使用 MOM 的应用程序编程接口(API)发送消息进行通信。 
 
    MOM将消息路由给应用程B,这样消息就可以存在于完全不同的计算机上,MOM 负责处理网络通信。如果网络连接不可用,MOM会存储消息,直到连接变得可用时,再将消息转发给应用程序B。 
    灵活性的另一方面体现在,当应用程序A发送其消息时,应用程序B甚至可以不处于执行状态。MOM将保留这个消息,直到应用程序B开始执行并试着检索消息为止。这还防止了应用程序A因为等待应用程序B检索消息而出现阻塞。 这种异步通信要求应用程序的设计与现在大多数应用程序不同,不过,对于时间无关或并行处理,它可能是一个极其有用的方法。 

2.2 消息中间件与分布式对象调用的比较 

    分布式对象调用,如CORBA,RMI和DCOM,提供了一种通讯机制,透明地在异构的分布式计 算环境中传递对象请求,而这些对象可以位于本地或远程机器。它通过在对象与对象之间提供一种统一的接口,使对象之间的调用和数据共享不再关心对象的位置、 实现语言及所驻留的操作系统。这个接口就是面向对象的中间件。 
尽管面向对象的中间件是一种很强大的规范被广泛应用,但是面对大规模的复杂分布式系统,这些技术也显示出了局限性: 
1.同步通信:客户发出调用后,必须等待服务对象完成处理并返回结果后才能继续执行。 
2.客户和服务对象的生命周期紧密耦合:客户进程和服务对象进程都必须正常运行,如果由于服务对象崩溃或网络故障导致客户的请求不可达,客户会接收到异常。 
    为了解决这些问题,出现了面向消息的中间件,它较好地解决了以上的问题。 
消息中间件作为一个中间层软件,它为分布式系统中创建、发送、接收消息提供了一套可靠通用的方 法,实现了分布式系统中可靠的、高效的、实时的跨平台数据传输。消息中间件减少了开发跨平台和网络协议软件的复杂性,它屏蔽了不同操作系统和网络协议的具 体细节,面对规模和复杂度都越来越高的分布式系统,消息中间件技术显示出了它的优越性: 
1.采用异步通信模式:发送消息者可以在发送消息后进行其它的工作,不用等待接收者的回应,而接收者也不必在接到消息后立即对发送者的请求进行处理; 
2.客户和服务对象生命周期的松耦合关系:客户进程和服务对象进程不要求都正常运行,如果由于服务对象崩溃或者网络故障导致客户的请求不可达,客户不会接收到异常,消息中间件能保证消息不会丢失。 
2.3 消息中间件的传递模式 
    消息中间件一般有两种传递模型:点对点模型(PTP)和发布-订阅模型(Pub/Sub)[2]。 
2.3.1. 点对点模型(PTP) 
    点对点模型用于消息生产者和消息消费者之间点到点的通信。消息生产者将消息发动到由某个名字标识 的特定消费者。这个名字实际上对应于消息服务中的一个队列(Queue),在消息传动给消费者之前它被存储在这个队列中。队列可以是持久的,以保证在消息 服务出现故障时仍然能够传递消息。 
2.3.2. 发布-订阅模型(Pub/Sub) 
    发布-订阅模型用称为主题(topic)的内容分层结构代替了PTP模型中的惟一目的地,发送应 用程序发布自己的消息,指出消息描述的是有关分层结构中的一个主题的信息。希望接收这些消息的应用程序订阅了这个主题。订阅包含子主题的分层结构中的主题 的订阅者可以接收该主题和其子主题发表的所有消息。 
下图展示了发布和订阅模型: 


   多个应用程序可以就一个主题发布和订阅消息,而应用程序对其他人仍然是匿名的。MOM 起着代理(broker)的作用,将一个主题已发表的消息路由给该主题的所有订阅者。 

2.4 消息中间件产品与JMS 

    从上个世纪90年代初,随着不同厂商消息中间件大量上市,消息中间件技术得到了长足的发展。目 前,IBM和BEA的中间件产品在银行、证券、电信等高端行业,以及IT等行业中得到广泛应用。IBM凭借其在1999年推出的应用服务器 WebSphere,扎根金融、证券等行业,在超大型以及系统整合型应用方面优势突出;BEA则是专门从事中间件开发的公司,它的应用服务器 WebLogic在美国市场占有率超过60%,在国内电信及证券行业占据主要地位;Sun、Oracle、Sybase和Borland等厂商也都有自己 的应用服务器;近年来,以金蝶、东方通等公司为代表的国产中间件产品也发展迅速。[3] 
   由于没有统一的规范和标准,基于消息中间件的应用不可移植,不同的消息中间件也不能互操作,这大 大阻碍了消息中间件的发展。 Java Message Service(JMS, Java消息服务)是SUN及其伙伴公司提出的旨在统一各种消息中间件系统接口的规范。它定义了一套通用的接口和相关语义,提供了诸如持久、验证和事务的 消息服务,它最主要的目的是允许Java应用程序访问现有的消息中间件。JMS规范没有指定在消息节点间所使用的通讯底层协议,来保证应用开发人员不用与 其细节打交道,一个特定的JMS实现可能提供基于TCP/IP、HTTP、UDP或者其它的协议。 
   目前许多厂商采用并实现了JMS API,现在,JMS产品能够为企业提供一套完整的消息传递功能,下面是一些比较流行的JMS商业软件和开源产品。 
1.IBM MQSeries 
        IBM MQ系列产品提供的服务使得应用程序可以使用消息队列进行相互交流,通过一系列基于Java的API,提供了MQSeries在Java中应用开发的方 法。它支持点到点和发布/订阅两种消息模式,在基本消息服务的基础上增加了结构化消息类,通过工作单元提供数据整合等内容。 
2.WebLogic 
        WebLogic是BEA公司实现的基于工业标准的J2EE应用服务器,支持大多数企业级JavaAPI,它完全兼容JMS规范,支持点到点和发布/订阅消息模式,它具有以下一些特点: 
1) 通过使用管理控制台设置JMS配置信息; 
2) 支持消息的多点广播; 
3) 支持持久消息存储的文件和数据库; 
4) 支持XML消息,动态创建持久队列和主题。 
3.SonicMQ 
       SonicMQ是Progress公司实现的JMS产品。除了提供基本的消息驱动服务之外,SonicMQ也提供了很多额外的企业级应用开发工具包,它具有以下一些基本特征: 
1) 提供JMS规范的完全实现,支持点到点消息模式和发布/订阅消息模式; 
2) 支持层次安全管理; 
3) 确保消息在Internet上的持久发送; 
4) 动态路由构架(DRA)使企业能够通过单个消息服务器动态的交换消息; 
5) 支持消息服务器的集群。 
4.Active MQ 
       Active MQ是一个基于Apcache 2.0 licenced发布,开放源码的JMS产品。其特点为: 
1) 提供点到点消息模式和发布/订阅消息模式; 
2) 支持JBoss、Geronimo等开源应用服务器,支持Spring框架的消息驱动; 
3) 新增了一个P2P传输层,可以用于创建可靠的P2P JMS网络连接; 
4) 拥有消息持久化、事务、集群支持等JMS基础设施服务。 
5.OpenJMS 
       OpenJMS是一个开源的JMS规范的实现,它包含以下几个特征: 
1) 它支持点到点模型和发布/订阅模型; 
2) 支持同步与异步消息发送; 
3) 可视化管理界面,支持Applet; 
4) 能够与Jakarta Tomcat这样的Servlet容器结合; 
5) 支持RMI、TCP、HTTP与SSL协议。 

如何正确地处理时间

转载:http://www.liaoxuefeng.com/article/0014132675721847f569c3514034f099477472c73b5dee2000

日期和时间在程序中应用广泛,每种程序开发语言都自带处理日期和时间的相关函数,很多开发者把日期和时间存入数据库中,但是,一旦涉及到跨时区的日期和时间的处理时,大多数开发者根本就不明白如何正确地处理日期和时间。

首先,我们来看大部分的程序都是这么创建当前时间并存入数据库的:

Date date = new Date();
store2db(date);

这么做的问题在于,数据库的DateTime类型没有时区(time zone)信息,因此,存入的是本地时间,并且丢掉了时区信息。如果你把数据库服务器的时区改了,或者把应用服务器的时区改了,读出来的日期和时间就是错误的。如果以Timestamp类型存储,各数据库的实现也不相同,有的进行了内部时区自动转换,而且,存储的时间不超过2037年。

如果应用服务器的时区和数据库服务器的时区不一致,你无法确定数据库驱动程序会不会自动帮你转换。

大多数开发者遇到这个问题不是去探索正确的解决方法,而是自作聪明地在存入数据库之前先来个“调整”,比如把当前时间减掉8小时,在显示的时候遇到不正确的时间时,又来个“调整”,以“负负得正”的方式来掩盖错误。在遇到夏令时的时区时,还需要写更复杂的代码来调整小时。

正确的做法是先理解时间和时区的概念。

时区的概念

之所以有时区的概念是因为住在地球上不同地方的人看到太阳升起的时间是不一样的。我们假设北京人民在早上8:00看到了太阳刚刚升起,而此刻欧洲人民还在夜里,他们还需要再过7个小时才能看到太阳升起,所以,此刻欧洲人民的手表上显示的是凌晨1:00。如果你强迫他们用北京时间那他们每天看到日出的时间就是下午3点。

也就是说,东8区的北京人民的手表显示的8:00和东1区欧洲人民手表显示的1:00是相同的时刻:

"2014-10-14 08:00 +8:00" = "2014-10-14 01:00 +1:00"

这就是本地时间的概念。

但是,在计算机中,如果用本地时间来存储日期和时间,在遇到时区转换的问题上,即便你非常清楚地知道如何转换,也非常麻烦,尤其是矫情的美国人还在采用夏令时。

所以我们需要引入“绝对时间”的概念。绝对时间不需要年月日,而是以秒来计时。当前时间是指从一个基准时间(1970-1-1 00:00:00 +0:00),到现在的秒数,用一个整数表示。

当我们用绝对时间表示日期和时间时,无论服务器在哪个时区,任意时刻,他们生成的时间值都是相等的。所有编程语言都提供了方法来生成这个时间戳,Java和JavaScript输出以毫秒计算的Long型整数,Python等输出标准的Unix时间戳,以秒计算的Float型浮点数,这两者转换只存在1000倍的关系。

实际上,操作系统内部的计时器也是这个标准的时间戳,只有在显示给用户的时候,才转换为字符串格式的本地时间。

正确的存储方式

基于“数据的存储和显示相分离”的设计原则,我们只要把表示绝对时间的时间戳(无论是Long型还是Float)存入数据库,在显示的时候根据用户设置的时区格式化为正确的字符串。

数据的存储和显示相分离是非常基本的设计原则,却常常被大多数开发人员忽略。举个例子,在Excel中编写一个表格,表格的数据可视为数据的存储格式,你可以把表格的数据以柱状图或饼图表示出来,这些不同的图表是数据的不同显示格式,存储数据的时候,我们应该存储表格数据,绝不应该存储柱状图等图片信息。

HTML和CSS也是数据的存储和显示相分离的设计思想。

所以,数据库存储时间和日期时,只需要把Long或者Float表示的时间戳存到BIGINTREAL类型的列中,完全不用管数据库自己提供的DATETIMETIMESTAMP,也不用担心应用服务器和数据库服务器的时区设置问题,遇到Oracle数据库你不必去理会with timezonewith local timezone到底有啥区别。

读取时间时,读到的是一个Long或Float,只需要按照用户的时区格式化为字符串就能正确地显示出来:

// Java:
long t = System.currentTimeMillis();
System.out.println("long = " + t);

// current time zone:
SimpleDateFormat sdf_default = new SimpleDateFormat("yyyy-MM-dd HH:mm");
System.out.println(sdf_default.format(t));

// +8:00 time zone:
SimpleDateFormat sdf_8 = new SimpleDateFormat("yyyy-MM-dd HH:mm");
sdf_8.setTimeZone(TimeZone.getTimeZone("GMT+8:00"));
System.out.println("GMT+8:00 = " + sdf_8.format(t));

// +7:00 time zone:
SimpleDateFormat sdf_7 = new SimpleDateFormat("yyyy-MM-dd HH:mm");
sdf_7.setTimeZone(TimeZone.getTimeZone("GMT+7:00"));
System.out.println("GMT+7:00 = " + sdf_7.format(t));

// -9:00 time zone:
SimpleDateFormat sdf_la = new SimpleDateFormat("yyyy-MM-dd HH:mm");
sdf_la.setTimeZone(TimeZone.getTimeZone("America/Los_Angeles"));
System.out.println("America/Los_Angeles = " + sdf_la.format(t));

输出:

long = 1413230086802
2014-10-14 03:54
GMT+8:00 = 2014-10-14 03:54
GMT+7:00 = 2014-10-14 02:54
America/Los_Angeles = 2014-10-13 12:54

基于绝对时间戳的时间存储,从根本上就没有时区的问题。时区只是一个显示问题。额外获得的好处还包括:

  • 两个时间的比较就是数值的比较,根本不涉及时区问题,极其简单;

  • 时间的筛选也是两个数值之间筛选,写出SQL就是between(?, ?)

  • 显示时间时,把Long或Float传到页面,无论用服务端脚本还是用JavaScript都能简单而正确地显示时间。

你唯一需要编写的两个辅助函数就是String->LongLong->StringString->Long的作用是把用户输入的时间字符串按照用户指定时区转换成Long存进数据库。

唯一的缺点是数据库查询你看到的不是时间字符串,而是类似1413266801750之类的数字。



a poem from an unprofessional poet

I use my poor english to complete virgo works,hope you will like it. thanks.

Time flies, things changes, How I wish I could hold all these.
The flower not matter how beautifual it is,it always perish in the end.
Disaster is around us momemt by moment, if you are not able to conquer,then fall into hell.
I’m lazy,my girlfriend is lazy,my family are lazy,these are not the most important,because
we are young and healthy,we always think time and life are both limit. They will go away with nothing left
one day.At that time,fear,failure,helpless stuff our minds. I call this “empty life”,more seriously, “miserable life”

windows下Apache+tomcat集群-基于Proxy的方式

1. 准备工作

1.下载Apache:http://httpd.apache.org/
2. 下载Tomcat:http://httpd.apache.org/
本人用的tomcat7,解压下来复制一份,就可以做两个tomcat的集群。
安装目录如下:

2. 集群配置

Tomcat配置
tomcat-7.0.54_1:
apache-tomcat-7.0.54_1\conf\server.xml:
更改端口,因为两个tomcat使用的默认端口都是8080,所有修改tomcat1的端口8081
Line 70:

<Connector port="8081" protocol="HTTP/1.1"  
              connectionTimeout="20000"  
              redirectPort="8443" />  

接着修改AJP的端口,默认8009,修改成8019,同时打开引擎如下:
Line92:

<Connector port="8109" protocol="AJP/1.3" redirectPort="8443" />  
  
  <!-- An Engine represents the entry point (within Catalina) that processes  
       every request.  The Engine implementation for Tomcat stand alone  
       analyzes the HTTP headers included with the request, and passes them  
       on to the appropriate Host (virtual host).  
       Documentation at /docs/config/engine.html -->  
  
  <!-- You should set jvmRoute to support load-balancing via AJP ie :  
  <Engine name="Catalina" defaultHost="localhost" jvmRoute="jvm1">  
  -->  
  <Engine name="Catalina" defaultHost="localhost" jvmRoute="tomcat1">  

tomcat-7.0.54_2:
端口使用tomcat默认的8080,AJP使用默认的端口8009,
只需要打开Engiee引擎

<Engine name="Catalina" defaultHost="localhost" jvmRoute="tomcat2">  

Apache配置:
Apache的默认端口是80
Apache2.2\conf\httpd.conf最后加入
ProxyRequests Off   

PS:1. 这儿的端口8009和8019是AJP的端口,不是访问Tomcat的HTTP端口。
       

  <proxy balancer://cluster>   
          BalancerMember ajp://127.0.0.1:8009 loadfactor=1 route=tomcat1  
          BalancerMember ajp://127.0.0.1:8109 loadfactor=1 route=tomcat2  
   </proxy>  

2.  route要和Tomcat中配置的名称相同。

集群配置完毕,可以往被集群的Tomcat的webapp下部署文件。启动Apache、Tomcat1、Tomcat2。
访问地址:http://localhost/项目名称。这里其实是访问的Apache服务器,由Apache集群去找Tomcat服务器。

quartz集成spring下的集群配置

写在前头

   
spring3.0
以后就开始支持quartz2.x,因为org.quartz.CronTrigger2.0class变成了一个interface,Spring4.0.6配置文件中使用CronTriggerFactoryBean来集成quartz2.x,使用CronTriggerBean来集成quartz1.8.x及以前版本.

准备环境

我用的是spring4.0.6 + quartz 2.1.7

1. quartz官网:http://www.quartz-scheduler.org/

2. spring集成环境

<dependency> 
    <groupId>org.quartz-scheduler</groupId> 
    <artifactId>quartz</artifactId> 
    <version>2.1.7</version> 
</dependency> 
<dependency> 
    <groupId>org.quartz-scheduler</groupId> 
    <artifactId>quartz-oracle</artifactId> 
    <version>2.1.7</version> 
</dependency> 
<dependency> 
    <groupId>org.quartz-scheduler</groupId> 
    <artifactId>quartz-weblogic</artifactId> 
    <version>2.1.7</version> 
</dependency> 
<dependency> 
    <groupId>org.quartz-scheduler</groupId> 
    <artifactId>quartz-jboss</artifactId> 
    <version>2.1.7</version> 
</dependency> 

环境搭建

1.      创建数据库表结构

文件路径:quartz-2.1.7\docs\dbTables\*.sql

选择对应数据库的脚本,然后执行。我选择的ORACLE.

 

2.      创建quartz.properties文件

#============================================================================ 
# Configure Main Scheduler Properties   
#============================================================================ 
org.quartz.scheduler.instanceName = EventScheduler    
org.quartz.scheduler.instanceId = AUTO   
  
org.quartz.threadPool.class = org.quartz.simpl.SimpleThreadPool  
org.quartz.threadPool.threadCount = 10  
org.quartz.threadPool.threadPriority = 5  
org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread = true  
  
 
#============================================================================ 
# Configure JobStore   
#============================================================================ 
org.quartz.jobStore.misfireThreshold = 60000  
org.quartz.jobStore.class = org.quartz.impl.jdbcjobstore.JobStoreTX 
# mysql  
#org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.StdJDBCDelegate 
# Oracle  
org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.oracle.OracleDelegate   
org.quartz.jobStore.tablePrefix = QRTZ_  
org.quartz.jobStore.maxMisfiresToHandleAtATime=10  
org.quartz.jobStore.isClustered = true   
org.quartz.jobStore.clusterCheckinInterval = 20000  

3.      创建spring配置文件applicationContext-job.xml

<?xml version="1.0" encoding="UTF-8"?> 
<beans xmlns="http://www.springframework.org/schema/beans" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" 
    xmlns:mvc="http://www.springframework.org/schema/mvc" 
    xmlns:p="http://www.springframework.org/schema/p" 
    xmlns:util="http://www.springframework.org/schema/util" 
    xsi:schemaLocation="     

http://www.springframework.org/schema/beans


http://www.springframework.org/schema/beans/spring-beans.xsd


http://www.springframework.org/schema/context


http://www.springframework.org/schema/context/spring-context.xsd


http://www.springframework.org/schema/mvc


http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd


http://www.springframework.org/schema/util

        http://www.springframework.org/schema/util/spring-util-3.2.xsd"> 
    <bean id="jobService" class="com.test.service.TestJobservice"/> 
    <!-- 定义任务 --> 
    <bean id="vcaEventJobTask" class="org.springframework.scheduling.quartz.JobDetailFactoryBean"> 
        <property name="jobClass"> 
            <!-- 上面的任务代理类 --> 
            <value>com.test.service.DetailQuartzJobBean</value> 
        </property> 
        <property name="jobDataAsMap"> 
            <map> 
                <!-- 实际的任务的Bean name,填上EventMonitorService的Bean name --> 
                <entry key="targetObject" value="jobService" /> 
                <!-- 执行Bean中的哪个方法 --> 
                <entry key="targetMethod" value="executeTask" /> 
            </map> 
        </property> 
        <property name="durability" value="true"></property>  
    </bean> 
  
    <!-- 任务触发器 --> 
    <bean id="eventTaskTrigger" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean"> 
        <property name="jobDetail"> 
            <!-- 任务代理Bean name --> 
            <ref bean="vcaEventJobTask" /> 
        </property> 
        <property name="cronExpression"> 
            <!-- 配置表达式,这里表示每五分钟执行一次 --> 
            <value>0 0/1 * * * ?</value> 
        </property> 
    </bean> 
    <!-- 任务调度入口 --> 
    <bean autowire="no" 
        class="org.springframework.scheduling.quartz.SchedulerFactoryBean"> 
        <property name="dataSource"> 
            <ref bean="dataSource" /> 
        </property> 
        <!-- 任务列表,可以配置多个任务加入到该List --> 
        <property name="triggers"> 
            <list> 
               <ref bean="eventTaskTrigger"/>   
            </list> 
        </property> 
        <property name="configLocation" value="classpath:quartz.properties" /> 
        <property name="applicationContextSchedulerContextKey" value="applicationContext" /> 
        <property name="startupDelay" value="30" /> 
        <property name="autoStartup" value="true" /> 
        <property name="overwriteExistingJobs" value="true" /> 
    </bean> 
</beans> 

4.      创建任务类

代理类DetailQuartzJobBean.java

package com.test.service; 
import java.lang.reflect.Method; 
 
 
import org.quartz.JobExecutionContext; 
import org.quartz.JobExecutionException; 
import org.springframework.context.ApplicationContext;  
import org.springframework.scheduling.quartz.QuartzJobBean; 
 
public class DetailQuartzJobBean extends QuartzJobBean { 
     private ApplicationContext applicationContext;   
      
     private String targetObject; 
      
    private String targetMethod; 
      
     public String getTargetObject() { 
        return targetObject; 
    } 
 
 
    public void setTargetObject(String targetObject) { 
        this.targetObject = targetObject; 
    } 
 
    public String getTargetMethod() { 
        return targetMethod; 
    } 
 
    public void setTargetMethod(String targetMethod) { 
        this.targetMethod = targetMethod; 
    } 
 
 
    public ApplicationContext getApplicationContext() {  
        return applicationContext; 
    } 
       
     /** 
       * 从SchedulerFactoryBean注入的applicationContext. 
       */   
     public void setApplicationContext(ApplicationContext applicationContext) {   
        this.applicationContext = applicationContext;   
    }   
       
        @Override   
    protected void executeInternal(JobExecutionContext ctx) 
            throws JobExecutionException { 
        try { 
 
 
            // logger.info("execute [" + targetObject + "] at once>>>>>>"); 
            Object otargetObject = applicationContext.getBean(targetObject); 
            Method m = null; 
            try { 
                m = otargetObject.getClass().getMethod(targetMethod, 
                        new Class[] {}); 
                m.invoke(otargetObject, new Object[] {}); 
            } catch (SecurityException e) { 
                // logger.error(e); 
            } catch (NoSuchMethodException e) { 
                // logger.error(e); 
            } 
 
 
        } catch (Exception e) { 
            throw new JobExecutionException(e); 
        } 
    } 
} 

目标类TestJobservice.java

package com.test.service; 
 
import java.text.SimpleDateFormat; 
import java.util.Date; 
 
import org.slf4j.Logger; 
import org.slf4j.LoggerFactory; 
 
public class TestJobservice { 
 
    private static final transient Logger logger = LoggerFactory.getLogger(TestJobservice.class);   
     
    public void executeTask() { 
        logger.info("executing at " + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date())); 
    } 
}