yxhxj2006

常用链接

统计

最新评论

#

Quartz 框架快速入门(四)

Spring的scheduling.quartz包中对Quartz框架进行了封装,使得开发时不用写任何QuartSpring的代码就可以实现定时任务。Spring通过JobDetailBean,MethodInvokingJobDetailFactoryBean实现Job的定义。后者更加实用,只需指定要运行的类,和该类中要运行的方法即可,Spring将自动生成符合Quartz要求的JobDetail。
在上一篇文章《Quartz 框架快速入门(三)》中我们将示例迁移到Web环境下了,但使用的是Quartz的启动机制,这一篇中我们将让Web服务器启动Spring,通过Spring的配置文件来进行任务的调度
1,创建一个Web项目,加入spring.jar,quartz-1.6.0.jar,commons-collections.jar,jta.jar ,commons-logging.jar这几个包.
     2,创建一个类,在类中添加一个方法execute,我们将对这个方法进行定时调度.

package com.vista.quartz;

import java.util.Date;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;

public class HelloWorld 
{
    private static Log logger = LogFactory.getLog(HelloWorld.class);//日志记录器
    public HelloWorld()
    {
    }
    public void execute()
    {
        logger.info("Kick your ass and Fuck your mother! - " + new Date()); 
    }
}

2. Spring配置文件applicationContext.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"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd">

    <!-- 要调用的工作类 -->
    <bean id="quartzJob" class="com.vista.quartz.HelloWorld"></bean>
    <!-- 定义调用对象和调用对象的方法 -->
    <bean id="jobtask" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
        <!-- 调用的类 -->
        <property name="targetObject">
            <ref bean="quartzJob"/>
        </property>
        <!-- 调用类中的方法 -->
        <property name="targetMethod">
             <value>execute</value>
        </property>
    </bean>
    <!-- 定义触发时间 -->
    <bean id="doTime" class="org.springframework.scheduling.quartz.CronTriggerBean">
        <property name="jobDetail">
            <ref bean="jobtask"/>
        </property>
        <!-- cron表达式 -->
        <property name="cronExpression">
            <value>10,15,20,25,30,35,40,45,50,55 * * * * ?</value>
        </property>
    </bean>
    <!-- 总管理类 如果将lazy-init='false'那么容器启动就会执行调度程序  -->
    <bean id="startQuertz" lazy-init="false" autowire="no" class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
        <property name="triggers">
            <list>
               <ref bean="doTime"/>
            </list>
        </property>
    </bean>
</beans>

3,先在控制台中对上面的代码进行测试,我们要做的只是加载Spring的配置文件就可以了,代码如下:

package com.vista.quartz;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Test 
{
    public static void main(String[] args) 
    {
         System.out.println("Test start.");
            ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
            //如果配置文件中将startQuertz bean的lazy-init设置为false 则不用实例化
            
//context.getBean("startQuertz");
         System.out.print("Test end..");
    }
}

4,然后将Web.xml修改如下,让tomcat在启动时去初始化Spring:

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.4" 
    xmlns="http://java.sun.com/xml/ns/j2ee" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee 
    http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
     <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>
            /WEB-INF/classes/applicationContext.xml
        </param-value>
    </context-param> 
    
    <servlet>
        <servlet-name>SpringContextServlet</servlet-name>
        <servlet-class>org.springframework.web.context.ContextLoaderServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet> 

  <welcome-file-list>
    <welcome-file>index.jsp</welcome-file>
  </welcome-file-list>
</web-app>

5,最后启动Tomcat,测试结果如下图所示:
 


posted @ 2012-09-14 18:31 奋斗成就男人 阅读(175) | 评论 (0)编辑 收藏

Quartz 框架快速入门(三)

  在前面两篇文章中简单介绍了在java应用程序中如何使用Quartz框架,这一篇中我们将看到如何在web环境下通过配置文件来完成Quartz的后台作业调度,而不必手工去创建Trigger和Scheduler,其步骤如下:
首先创建一个Web项目,将quartz-1.6.0.jar,以及lib目录下面core下所有jar,optional目录下的所有commons-beanutils.jar和commons-digester-1.7.jar,build目录下的jta.jar都放入Web项目的WEB-INF"lib目录下。
创建一个简单的job类HelloWorld,它的功能很简单,就是输出当前的时间,代码如下:

package com.vista.quartz;

import java.util.Date;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;

public class Helloworld implements Job
{
    private static Log logger = LogFactory.getLog(Helloworld.class);//日志记录器
    public Helloworld()
    {
    }
    public void execute(JobExecutionContext context) throws JobExecutionException 
    {
        logger.info("Hello World! - " + new Date()); 
    }
}

然后按照上一篇文章《Quartz 框架快速入门(二)》中所讲述的内容编写quartz.properties文件。如果启动项目的时候,Quartz没有在工程中找到该文件,就会从自己的jar包下面读取其默认的properties文件,其内容如下

#============================================================================
# Configure Main Scheduler Properties  
#============================================================================
org.quartz.scheduler.instanceName = QuartzScheduler
org.quartz.scheduler.instanceId = AUTO
#============================================================================
# Configure ThreadPool  
#============================================================================
org.quartz.threadPool.class = org.quartz.simpl.SimpleThreadPool
org.quartz.threadPool.threadCount = 5
org.quartz.threadPool.threadPriority = 5
#============================================================================
# Configure JobStore  
#============================================================================
org.quartz.jobStore.misfireThreshold = 60000
org.quartz.jobStore.class = org.quartz.simpl.RAMJobStore
#============================================================================
# Configure Plugins 
#============================================================================
org.quartz.plugin.triggHistory.class = org.quartz.plugins.history.LoggingJobHistoryPlugin
org.quartz.plugin.jobInitializer.class = org.quartz.plugins.xml.JobInitializationPlugin
org.quartz.plugin.jobInitializer.fileNames = jobs.xml
org.quartz.plugin.jobInitializer.overWriteExistingJobs = true
org.quartz.plugin.jobInitializer.failOnFileNotFound = true
org.quartz.plugin.jobInitializer.scanInterval = 10
org.quartz.plugin.jobInitializer.wrapInUserTransaction = false

然后编写任务配置文件jobs.xml,内容如下:

<?xml version='1.0' encoding='utf-8'?>
<quartz xmlns="http://www.opensymphony.com/quartz/JobSchedulingData"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://www.opensymphony.com/quartz/JobSchedulingData
  http://www.opensymphony.com/quartz/xml/job_scheduling_data_1_5.xsd"
  version="1.5">   
 <job>      
    <job-detail>      
     <name>HelloWorld</name>      
     <group>DEFAULT</group>      
     <description>      
           A job that just for test       
     </description>      
     <job-class>      
            com.vista.quartz.Helloworld      
     </job-class>      
     <volatility>false</volatility>      
     <durability>false</durability>      
     <recover>false</recover>          
  </job-detail>      
  <trigger>      
    <simple>      
     <name>HelloTrigger1</name>      
     <group>DEFAULT</group>      
     <job-name>HelloWorld</job-name>      
     <job-group>DEFAULT</job-group>      
     <start-time>2008-09-03T15:56:30</start-time>      
     <!-- repeat indefinitely every 10 seconds -->      
     <repeat-count>-1</repeat-count>      
     <repeat-interval>10000</repeat-interval>      
    </simple>      
  </trigger>      
</job>      
</quartz>

可以看到,在配置文件中把jobdetail和trigger都作了完整的定义,并组合成一个job。下面,我们把上面两个文件都放入/WEB-INF/classes目录下,然后按照api中的说明修改一下web.xml,内容如下

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.4" 
    xmlns="http://java.sun.com/xml/ns/j2ee" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee 
    http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
    <servlet>  
        <servlet-name>QuartzInitializer</servlet-name>  
        <display-name>Quartz Initializer Servlet</display-name>
        <servlet-class>  
             org.quartz.ee.servlet.QuartzInitializerServlet  
        </servlet-class>  
        <load-on-startup>1</load-on-startup>  
        <init-param>  
            <param-name>config-file</param-name>  
            <param-value>/quartz.properties</param-value>  
        </init-param>  
        <init-param>  
            <param-name>shutdown-on-unload</param-name>  
            <param-value>true</param-value>  
       </init-param>  
    </servlet>  
  <welcome-file-list>
    <welcome-file>index.jsp</welcome-file>
  </welcome-file-list>
</web-app>

这样,在启动Tomcat的时候,QuartzInitializerServlet这个Servlet就会自动读取quartz.properties这个配置文件,并初始化调度信息,启动Scheduler。
启动tomcat后,就可以看到输出的结果:
 

posted @ 2012-09-14 18:29 奋斗成就男人 阅读(166) | 评论 (0)编辑 收藏

Quartz 框架快速入门(二)

尽可能的用声明式处理软件配置,其次才考虑编程式的方式。在上一篇《Quartz 框架快速入门(一)》中,如果我们要在 Job 启动之后改变它的执行时间和频度,必须去修改源代码重新编译。这种方式只适用于小的例子程序,但是对于一个大且复杂的系统,这就成了一个问题了。因此,假如能以声明式部署 Quart Job 时,并且也是需求允许的情况下,你应该每次都选择这种方式 
·配置 quartz.properties 文件
文件 quartz.properties 定义了 Quartz 应用运行时行为,还包含了许多能控制 Quartz 运转的属性。这个文件应该放在classpath所指的路径下,比如我们这个java工程,就将它和下面将介绍的jobs.xml一起放在项目根目录下就是。如果不清楚就查看.classpath文件,它里面就配置了你的项目的classpath。
我们来看看最基础的 quartz.properties 文件,并讨论其中一些设置。下面是一个修剪版的 quartz.propertis文件

#============================================================================
# Configure Main Scheduler Properties  
#============================================================================
org.quartz.scheduler.instanceName = TestScheduler
org.quartz.scheduler.instanceId = AUTO
#============================================================================
# Configure ThreadPool  
#============================================================================
org.quartz.threadPool.class = org.quartz.simpl.SimpleThreadPool
org.quartz.threadPool.threadCount = 3
org.quartz.threadPool.threadPriority = 5
#============================================================================
# Configure JobStore  
#============================================================================
org.quartz.jobStore.misfireThreshold = 60000
org.quartz.jobStore.class = org.quartz.simpl.RAMJobStore
#============================================================================
# Configure Plugins 
#============================================================================
org.quartz.plugin.triggHistory.class = org.quartz.plugins.history.LoggingJobHistoryPlugin
org.quartz.plugin.jobInitializer.class = org.quartz.plugins.xml.JobInitializationPlugin
org.quartz.plugin.jobInitializer.fileNames = jobs.xml
org.quartz.plugin.jobInitializer.overWriteExistingJobs = true
org.quartz.plugin.jobInitializer.failOnFileNotFound = true
org.quartz.plugin.jobInitializer.scanInterval = 10
org.quartz.plugin.jobInitializer.wrapInUserTransaction = false

·调度器属性
第一部分有两行,分别设置调度器的实例名(instanceName) 和实例 ID (instanceId)。属性 org.quartz.scheduler.instanceName 可以是你喜欢的任何字符串。它用来在用到多个调度器区分特定的调度器实例。多个调度器通常用在集群环境中。(Quartz 集群将会在第十一章,“Quartz 集群”中讨论)。现在的话,设置如下的一个字符串就行:org.quartz.scheduler.instanceName = QuartzScheduler
实际上,这也是当你没有该属性配置时的默认值。
调度器的第二个属性是 org.quartz.scheduler.instanceId。和 instaneName 属性一样,instanceId 属性也允许任何字符串。这个值必须是在所有调度器实例中是唯一的,尤其是在一个集群当中。假如你想 Quartz 帮你生成这个值的话,可以设置为 AUTO。如果 Quartz 框架是运行在非集群环境中,那么自动产生的值将会是 NON_CLUSTERED。假如是在集群环境下使用 Quartz,这个值将会是主机名加上当前的日期和时间。大多情况下,设置为 AUTO 即可。
·线程池属性
接下来的部分是设置有关线程必要的属性值,这些线程在 Quartz 中是运行在后台担当重任的。threadCount 属性控制了多少个工作者线程被创建用来处理 Job。原则上是,要处理的 Job 越多,那么需要的工作者线程也就越多。threadCount 的数值至少为 1。Quartz 没有限定你设置工作者线程的最大值,但是在多数机器上设置该值超过100的话就会显得相当不实用了,特别是在你的 Job 执行时间较长的情况下。这项没有默认值,所以你必须为这个属性设定一个值。
threadPriority 属性设置工作者线程的优先级。优先级别高的线程比级别低的线程更优先得到执行。threadPriority 属性的最大值是常量 java.lang.Thread.MAX_PRIORITY,等于10。最小值为常量 java.lang.Thread.MIN_PRIORITY,为1。这个属性的正常值是 Thread.NORM_PRIORITY,为5。大多情况下,把它设置为5,这也是没指定该属性的默认值。
最后一个要设置的线程池属性是 org.quartz.threadPool.class。这个值是一个实现了 org.quartz.spi.ThreadPool 接口的类的全限名称。Quartz 自带的线程池实现类是 org.quartz.smpl.SimpleThreadPool,它能够满足大多数用户的需求。这个线程池实现具备简单的行为,并经很好的测试过。它在调度器的生命周期中提供固定大小的线程池。你能根据需求创建自己的线程池实现,如果你想要一个随需可伸缩的线程池时也许需要这么做。这个属性没有默认值,你必须为其指定值。
·作业存储设置
作业存储部分的设置描述了在调度器实例的生命周期中,Job 和 Trigger 信息是如何被存储的。我们还没有谈论到作业存储和它的目的;因为对当前例子是非必的,所以我们留待以后说明。现在的话,你所要了解的就是我们存储调度器信息在内存中而不是在关系型数据库中就行了。
把调度器信息存储在内存中非常的快也易于配置。当调度器进程一旦被终止,所有的 Job 和 Trigger 的状态就丢失了。要使 Job 存储在内存中需通过设置  org.quartz.jobStrore.class 属性为 org.quartz.simpl.RAMJobStore。假如我们不希望在 JVM 退出之后丢失调度器的状态信息的话,我们可以使用关系型数据库来存储这些信息。这需要另一个作业存储(JobStore) 实现,我们在后面将会讨论到。第五章“Cron Trigger 和其他”和第六章“作业存储和持久化”会提到你需要用到的不同类型的作业存储实现。
·插件配置
在这个简单的 quartz.properties 文件中最后一部分是你要用到的 Quart 插件的配置。插件常常在别的开源框架上使用到,比如 Apache 的 Struts 框架(见 http://struts.apache.org/)。
一个声明式扩框架的方法就是通过新加实现了 org.quartz.spi.SchedulerPlugin 接口的类。SchedulerPlugin  接口中有给调度器调用的三个方法。
要在我们的例子中声明式配置调度器信息,我们会用到一个 Quartz 自带的叫做 org.quartz.plugins.xml.JobInitializationPlugin 的插件。
默认时,这个插件会在 classpath 中搜索名为 quartz_jobs.xml 的文件并从中加载 Job 和 Trigger 信息。在下下面中讨论 quartz_jobs.xml 文件,这是我们所参考的非正式的 Job 定义文件。
·为插件修改 quartz.properties 配置
JobInitializationPlugin 找寻 quartz_jobs.xml 来获得声明的 Job 信息。假如你想改变这个文件名,你需要修改 quartz.properties 来告诉插件去加载那个文件。例如,假如你想要 Quartz 从名为 my_quartz_jobs.xml 的 XML 文件中加载 Job 信息,你不得不为插件指定这一文件

org.quartz.plugin.triggHistory.class = org.quartz.plugins.history.LoggingJobHistoryPlugin
org.quartz.plugin.jobInitializer.class = org.quartz.plugins.xml.JobInitializationPlugin
org.quartz.plugin.jobInitializer.fileNames = jobs.xml
org.quartz.plugin.jobInitializer.overWriteExistingJobs = true
org.quartz.plugin.jobInitializer.failOnFileNotFound = true
org.quartz.plugin.jobInitializer.scanInterval = 10
org.quartz.plugin.jobInitializer.wrapInUserTransaction = false

我们添加了属性 org.quartz.plugin.jobInitializer.fileName 并设置该属性值为我们想要的文件名。这个文件名要对 classloader 可见,也就是说要在 classpath 下。
当 Quartz 启动后读取 quartz.properties 文件,然后初始化插件。它会传递上面配置的所有属性给插件,这时候插件也就得到通知去搜寻不同的文件。
下面就是目录扫描例子的 Job 定义的 XML 文件。正如上一篇所示例子那样,这里我们用的是声明式途径来配置 Job 和 Trigger 信息的

<?xml version='1.0' encoding='utf-8'?>
<quartz xmlns="http://www.opensymphony.com/quartz/JobSchedulingData"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://www.opensymphony.com/quartz/JobSchedulingData
  http://www.opensymphony.com/quartz/xml/job_scheduling_data_1_5.xsd"
  version="1.5">   
  <job>      
    <job-detail>      
     <name>ScanDirectory</name>      
     <group>DEFAULT</group>      
     <description>      
          A job that scans a directory for files       
     </description>      
     <job-class>      
            com.vista.quartz.ScanDirectoryJob       
     </job-class>      
     <volatility>false</volatility>      
     <durability>false</durability>      
     <recover>false</recover>      
     <job-data-map allows-transient-data="true">      
         <entry>      
         <key>SCAN_DIR</key>      
         <value>D:\conf1</value>      
       </entry>      
     </job-data-map>      
    </job-detail>      
      
    <trigger>      
     <simple>      
       <name>scanTrigger</name>      
       <group>DEFAULT</group>      
       <job-name>ScanDirectory</job-name>      
       <job-group>DEFAULT</job-group>      
       <start-time>2008-09-03T14:43:00</start-time>      
       <!-- repeat indefinitely every 10 seconds -->      
       <repeat-count>-1</repeat-count>      
       <repeat-interval>10000</repeat-interval>      
     </simple>      
    </trigger>      
  </job>      
</quartz>

在jobs.xml 中 <start-time> 的格式是:
<start-time>2008-09-03T14:43:00</start-time>
其中T隔开日期和时间,默认时区 
或者:
<start-time>2008-09-03T14:43:00+08:00</start-time> 
其中+08:00 表示东八区
<job> 元素描述了一个要注册到调度器上的 Job,相当于我们在前面章节中使用 scheduleJob() 方法那样。你所看到的<job-detail> 和  <trigger> 这两个元素就是我们在代码中以编程式传递给方法 schedulerJob() 的参数。前面本质上是与这里一样的,只是现在用的是一种较流行声明的方式。<trigger>元素也是非常直观的:它使用前面同样的属性,但更简单的建立一个 SimpleTrigger。因此仅仅是一种不同的(可论证的且更好的)方式做了上一篇代码 中同样的事情。显然,你也可以支持多个 Job。在上一篇代码 中我们编程的方式那么做的,也能用声明的方式来支持


<?xml version='1.0' encoding='utf-8'?>
<quartz xmlns="http://www.opensymphony.com/quartz/JobSchedulingData"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://www.opensymphony.com/quartz/JobSchedulingData
  http://www.opensymphony.com/quartz/xml/job_scheduling_data_1_5.xsd"
  version="1.5">   
 <job>      
    <job-detail>      
     <name>ScanDirectory1</name>      
     <group>DEFAULT</group>      
     <description>      
           A job that scans a directory for files       
     </description>      
     <job-class>      
            com.vista.quartz.ScanDirectoryJob       
     </job-class>      
     <volatility>false</volatility>      
     <durability>false</durability>      
     <recover>false</recover>      
      
     <job-data-map allows-transient-data="true">      
     <entry>      
       <key>SCAN_DIR</key>      
         <value>D:\dyk\Java\Tomcat\conf</value>      
     </entry>      
    </job-data-map>      
  </job-detail>      
  <trigger>      
    <simple>      
     <name>scanTrigger1</name>      
     <group>DEFAULT</group>      
     <job-name>ScanDirectory1</job-name>      
     <job-group>DEFAULT</job-group>      
     <start-time>2008-09-03T15:00:10</start-time>      
     <!-- repeat indefinitely every 10 seconds -->      
     <repeat-count>-1</repeat-count>      
     <repeat-interval>10000</repeat-interval>      
    </simple>      
  </trigger>      
</job>       
<job>      
  <job-detail>      
    <name>ScanDirectory2</name>      
    <group>DEFAULT</group>      
    <description>      
          A job that scans a directory for files       
    </description>      
    <job-class>      
          com.vista.quartz.ScanDirectoryJob       
    </job-class>      
    <volatility>false</volatility>      
    <durability>false</durability>      
    <recover>false</recover>      
    <job-data-map allows-transient-data="true">      
      <entry>      
       <key>SCAN_DIR</key>      
       <value>D:\dyk\Java\Tomcat\webapps\MyTest\WEB-INF</value>      
     </entry>      
    </job-data-map>      
  </job-detail>      
  <trigger>      
    <simple>      
     <name>scanTrigger2</name>      
     <group>DEFAULT</group>      
     <job-name>ScanDirectory2</job-name>      
     <job-group>DEFAULT</job-group>      
     <start-time>2008-09-03T15:00:20</start-time>      
     <!-- repeat indefinitely every 15 seconds -->      
     <repeat-count>-1</repeat-count>      
     <repeat-interval>15000</repeat-interval>      
    </simple>      
  </trigger>      
 </job>   
</quartz>

最后我们来看看原来的代码简化成如何了:

package com.vista.quartz;

import java.util.Date;       

import org.apache.commons.logging.Log;       
import org.apache.commons.logging.LogFactory;       
import org.quartz.JobDetail;
import org.quartz.Scheduler;       
import org.quartz.SchedulerException;       
import org.quartz.Trigger;
import org.quartz.TriggerUtils;
import org.quartz.impl.StdSchedulerFactory;

public class SimpleScheduler 
{
    static Log logger = LogFactory.getLog(SimpleScheduler.class);         
    public static void main(String[] args) 
    {       
         SimpleScheduler simple = new SimpleScheduler();       
         try 
         {       
             // Create a Scheduler and schedule the Job       
             Scheduler scheduler = simple.createScheduler();         
             // Jobs can be scheduled after Scheduler is running       
             scheduler.start();          
             logger.info("Scheduler started at " + new Date());         
        } 
        catch (SchedulerException ex)
        {       
             logger.error(ex);       
        }       
    }       
    public Scheduler createScheduler() throws SchedulerException 
    {//创建调度器       
        return StdSchedulerFactory.getDefaultScheduler();
    }   
}

posted @ 2012-09-14 18:28 奋斗成就男人 阅读(224) | 评论 (0)编辑 收藏

Quartz 框架快速入门(一)

创建一个 Java 工程,引入几个 JAR 到工程中才能成功构建它们。首先,你需要 Quartz 的二进制版本,包的名字是 quartz-<version>.jar。Quartz 还需要几个第三方库;这依赖于你要用到框架的什么功能而定,Commons Digester 库可以在<QUARTZ_HOME>/lib/core 和 <QUARTZ_HOME>/lib/optional 目录中找到。如果出现java.lang.NoClassDefFoundError: javax/transaction/UserTransaction的错误,解决办法是:引入jta.jar包,这个包在quartz-1.6.0/lib/build 下。
·创建一个 Quartz Job 类
每一个 Quartz Job 必须有一个实现了 org.quartz.Job 接口的具体类。这个接口仅有一个要你在 Job 中实现的方法,execute(),方法 execute() 的原型如下:
public void execute(JobExecutionContext context) throws JobExecutionException;
当 Quartz 调度器确定到时间要激发一个 Job 的时候,它就会生成一个 Job 实例,并调用这个实例的 execute() 方法。调度器只管调用 execute() 方法,而不关心执行的结果,除了在作业执行中出问题抛出的 org.quartz.JobExecutionException 异常。
下面是我们的第一个 Quartz job,它被设计来扫描一个目录中的文并显示文件的详细信息.
package com.vista.quartz;

import java.io.File;       

import java.io.FileFilter;

import java.util.Date;       

      

import org.apache.commons.logging.Log;       

import org.apache.commons.logging.LogFactory;       

import org.quartz.Job;       

import org.quartz.JobDataMap;       

import org.quartz.JobDetail;       

import org.quartz.JobExecutionContext;       

import org.quartz.JobExecutionException;  



public class ScanDirectoryJob implements Job 

{

    static Log logger = LogFactory.getLog(ScanDirectoryJob.class);//日志记录器

    

    public void execute(JobExecutionContext context) throws JobExecutionException 

    {

        //Every job has its own job detail       

        JobDetail jobDetail = context.getJobDetail();       

        // The name is defined in the job definition       

        String jobName = jobDetail.getName();//任务名称       

        
// Log the time the job started       

        logger.info(jobName + " fired at " + new Date());//记录任务开始执行的时间       

        
// The directory to scan is stored in the job map       

        JobDataMap dataMap = jobDetail.getJobDataMap();//任务所配置的数据映射表       

        String dirName = dataMap.getString("SCAN_DIR");//获取要扫描的目录       

        
// Validate the required input       

        if (dirName == null

        {//所需要的扫描目录没有提供       

             throw new JobExecutionException( "Directory not configured" );       

        }       

        // Make sure the directory exists       

        File dir = new File(dirName);       

        if (!dir.exists()) 

        {//提供的是错误目录       

            throw new JobExecutionException( "Invalid Dir "+ dirName);       

        }       

        // Use FileFilter to get only XML files       

        FileFilter filter = new FileExtensionFileFilter(".xml");       

        //只统计xml文件

        File[] files = dir.listFiles(filter);       

        if (files == null || files.length <= 0) 

        {//目录下没有xml文件       

            logger.info("No XML files found in " + dir);       

            // Return since there were no files       

            return;

        }       

        // The number of XML files       

        int size = files.length;          

        // Iterate through the files found       

        for (int i = 0; i < size; i++) 

        {

            File file = files[i];       

            // Log something interesting about each file.       

            File aFile = file.getAbsoluteFile();       

            long fileSize = file.length();       

            String msg = aFile + " - Size: " + fileSize;       

            logger.info(msg);//记录下文件的路径和大小

        } 

    }

}
当 Quartz 调用 execute() 方法,会传递一个 org.quartz.JobExecutionContext 上下文变量,里面封装有 Quartz 的运行时环境和当前正执行的 Job。通过 JobexecutionContext,你可以访问到调度器的信息,作业和作业上的触发器的信息,还有更多更多的信息。在代码中,JobExecutionContext 被用来访问 org.quartz.JobDetail 类,JobDetail 类持有 Job 的详细信息,包括为 Job 实例指定的名称,Job 所属组,Job 是否被持久化(易失性),和许多其他感兴趣的属性。
JobDetail 又持有一个指向 org.quartz.JobDataMap 的引用。JobDataMap 中有为指定 Job 配置的自定义属性。例如,在代码中我们从 JobDataMap 中获得欲扫描的目录名,我们可以在 ScanDirectoryJob 中硬编码这个目录名,但是这样的话我们难以重用这个 Job 来扫描别的目录了。在后面你将会看到目录是如何配置到 JobDataMap 的。
execute() 方法中剩下的就是标准 Java 代码了:获得目录名并创建一个 java.io.File 对象。它还对目录名作为简单的校验,确保是一个有效且存在的目录。接着调用 File 对象的 listFiles() 方法得到目录下的文件。还创建了一个 java.io.FileFilter 对象作为参数传递给 listFiles() 方法。org.quartzbook.cavaness.FileExtensionFileFilter 实现了 java.io.FileFilter 接口,它的作用是过滤掉目录仅返回 XML 文件。默认情况下,listFiles() 方法是返回目录中所有内容,不管是文件还是子目录,所以我们必须过滤一下,因为我们只对 XML 文件感兴趣。
FileExtensionFileFilter 被用来屏蔽名称中不含字符串 “.xml” 的文件。它还屏蔽了子目录--这些子目录原本会让 listFiles() 方法正常返回。过滤器提供了一种很便利的方式选择性的向你的 Quartz 作业提供它能接受的作为输入的文件.
package com.vista.quartz;

import  java.io.File;       

import  java.io.FileFilter;   



public class FileExtensionFileFilter implements  FileFilter 

{

     private  String extension;//文件后缀     

     

     public  FileExtensionFileFilter(String extension)

     {       

         this.extension = extension;

     }             

     public   boolean  accept(File file)

     {//只接受指定后缀的文件       

         
// Lowercase the filename for easier comparison       

         String lCaseFilename = file.getName().toLowerCase();//小写化

         return  (file.isFile() &&(lCaseFilename.indexOf(extension) >  0 )) ?  true : false ;       

     }       

}
到目前为止,我们已经创建了一个 Quartz job,但还没有决定怎么处置它--明显地,我们需以某种方式为这个 Job 设置一个运行时间表。时间表可以是一次性的事件,或者我们可能会安装它在除周日之外的每个午夜执行。你即刻将会看到,Quartz Schduler 是框架的心脏与灵魂。所有的 Job 都通过 Schduler 注册;必要时,Scheduler 也会创建 Job 类的实例,并执行实例的 execute() 方法。
·编程式安排一个 Quartz Job
所有的要 Quartz 来执行的作业必须通过调度器来注册。大多情况下,这会在调度器启动前做好。正如前面说过,这一操作也提供了声明式与编程式两种实现途径的选择。
因为每一个 Job 都必须用 Scheduler 来注册,所以先定义一个 JobDetail,并关联到这个 Scheduler 实例。
下面的程序提供了一个理解如何编程式安排一个 Job 很好的例子。代码首先调用 createScheduler() 方法从 Scheduler 工厂获取一个 Scheduler 的实例。得到 Scheduler 实例之后,把它传递给 schedulerJob() 方法,由它把 Job 同 Scheduler 进行关联。
首先,创建了我们想要运行的 Job 的 JobDetail 对象。JobDetail 构造器的参数中包含指派给 Job 的名称,逻辑组名,和实现 org.quartz.Job 接口的全限类名称。我们可以使用 JobDetail 的别的构造器。
在前面有说过,JobDetail 扮演着某一 Job 定义的角色。它带有 Job 实例的属性,能在运行时被所关联的 Job 访问到。其中在使用 JobDetail 时,的一个最重要的东西就是 JobDataMap,它被用来存放 Job 实例的状态和参数。在代码中,待扫描的目录名称就是通过  scheduleJob() 方法存入到 JobDataMap 中的。
Job 只是一个部分而已。注意我们没有在 JobDetail 对象中为 Job 设定执行日期和次数。这是 Quartz Trigger 该做的事。顾名思义,Trigger 的责任就是触发一个 Job 去执行。当用 Scheduler 注册一个 Job 的时候要创建一个 Trigger 与这个 Job 相关联。Quartz 提供了四种类型的 Trigger,但其中两种是最为常用的,它们就是在下面要用到的 SimpleTrigger 和  CronTrigger.
SimpleTrigger 是两个之中简单的那个,它主要用来激发单事件的 Job,Trigger 在指定时间激发,并重复 n 次--两次激发时间之间的延时为 m,然后结束作业。CronTrigger 非常复杂且强大。它是基于通用的公历,当需要用一种较复杂的时间表去执行一个 Job 时用到。例如,四月至九月的每个星期一、星期三、或星期五的午夜。
为更简单的使用 Trigger,Quartz 包含了一个工具类,叫做 org.quartz.TriggerUtils. TriggerUtils 提供了许多便捷的方法简化了构造和配置 trigger. 本文的例子中有用的就是 TriggerUtils 类;SimpleTrigger 和 CronTrigger 会在后面用到。
正如你看到的那样,调用了 TriggerUtils 的方法 makeSecondlyTrigger() 来创建一个每10秒种激发一次的 trigger(实际是由 TriggerUtils 生成了一个 SimpleTrigger 实例,但是我们的代码并不想知道这些)。我们同样要给这个 trigger 实例一个名称并告诉它何时激发相应的 Job;与之关联的 Job 会立即启动,因为由方法 setStartTime() 设定的是当前时间
package com.vista.quartz;



import java.util.Date;       



import org.apache.commons.logging.Log;       

import org.apache.commons.logging.LogFactory;       

import org.quartz.JobDetail;

import org.quartz.Scheduler;       

import org.quartz.SchedulerException;       

import org.quartz.Trigger;

import org.quartz.TriggerUtils;

import org.quartz.impl.StdSchedulerFactory;



public class SimpleScheduler 

{

    static Log logger = LogFactory.getLog(SimpleScheduler.class);         

    public static void main(String[] args) 

    {       

         SimpleScheduler simple = new SimpleScheduler();       

         try

         {       

             // Create a Scheduler and schedule the Job       

             Scheduler scheduler = simple.createScheduler();       

             simple.scheduleJob(scheduler);       

    

             // Start the Scheduler running       

             scheduler.start();       

    

             logger.info( "Scheduler started at " + new Date());       

    

        } catch (SchedulerException ex) {       

             logger.error(ex);       

        }   

        

    }       

    public Scheduler createScheduler() throws SchedulerException 

    {//创建调度器       

        return StdSchedulerFactory.getDefaultScheduler();

    }   

    

    //Create and Schedule a ScanDirectoryJob with the Scheduler       

    private void scheduleJob(Scheduler scheduler) throws SchedulerException 

    {       

         // Create a JobDetail for the Job       

         JobDetail jobDetail = new JobDetail("ScanDirectory",Scheduler.DEFAULT_GROUP,ScanDirectoryJob.class); 

         // Configure the directory to scan       

         jobDetail.getJobDataMap().put("SCAN_DIR","D:\\Tomcat\\conf"); //set the JobDataMap that is associated with the Job.            

         
// Create a trigger that fires every 10 seconds, forever       

         Trigger trigger = TriggerUtils.makeSecondlyTrigger(10);//每10秒触发一次       

         trigger.setName("scanTrigger");       

         // Start the trigger firing from now       

         trigger.setStartTime(new Date());//设置第一次触发时间            

         
// Associate the trigger with the job in the scheduler       

         scheduler.scheduleJob(jobDetail, trigger);       

    }       

}
假如你有不只一个个 Job (你也许就是),你将需要为每一个 Job 创建各自的 JobDetail。每一个 JobDetail 必须通过 scheduleJob() 方法一一注册到 Scheduler 上。而如果你想重用了一个 Job 类,让它产生多个实例运行,那么你需要为每个实例都创建一个 JobDetail。例如,假如你想重用 ScanDirectoryJob 让它检查两个不同的目录,你需要创建并注册两个 JobDetail 实例
package com.vista.quartz;



import java.util.Date;       



import org.apache.commons.logging.Log;       

import org.apache.commons.logging.LogFactory;       

import org.quartz.JobDetail;

import org.quartz.Scheduler;       

import org.quartz.SchedulerException;       

import org.quartz.Trigger;

import org.quartz.TriggerUtils;

import org.quartz.impl.StdSchedulerFactory;



public class SimpleScheduler 

{

    static Log logger = LogFactory.getLog(SimpleScheduler.class);         

    public static void main(String[] args) 

    {       

         SimpleScheduler simple = new SimpleScheduler();       

         try 

         {       

             // Create a Scheduler and schedule the Job       

             Scheduler scheduler = simple.createScheduler();         

             // Jobs can be scheduled after Scheduler is running       

             scheduler.start();          

             logger.info("Scheduler started at " + new Date());         

             // Schedule the first Job       

             simple.scheduleJob(scheduler, "ScanDirectory1",ScanDirectoryJob.class,"D:\\conf1", 10);          

             // Schedule the second Job       

             simple.scheduleJob(scheduler, "ScanDirectory2",ScanDirectoryJob.class,"D:\\conf2 ", 15);       

        } 

        catch (SchedulerException ex)

        {       

             logger.error(ex);       

        }       

    }       

    public Scheduler createScheduler() throws SchedulerException 

    {//创建调度器       

        return StdSchedulerFactory.getDefaultScheduler();

    }   

    

    private void scheduleJob(Scheduler scheduler, String jobName,Class jobClass, String scanDir, int scanInterval) throws SchedulerException 

    {         

        // Create a JobDetail for the Job       

       JobDetail jobDetail = new JobDetail(jobName,Scheduler.DEFAULT_GROUP, jobClass);         

       // Configure the directory to scan       

       jobDetail.getJobDataMap().put("SCAN_DIR", scanDir);         

       // Trigger that repeats every "scanInterval" secs forever       

       Trigger trigger = TriggerUtils.makeSecondlyTrigger(scanInterval);         

       trigger.setName(jobName + "-Trigger");         

       // Start the trigger firing from now       

       trigger.setStartTime(new Date());         

       // Associate the trigger with the job in the scheduler       

       scheduler.scheduleJob(jobDetail, trigger);       

  }       

}



posted @ 2012-09-14 18:27 奋斗成就男人 阅读(189) | 评论 (0)编辑 收藏

使用Jquery实现复选框的全选和反选

使用JQuery实现复选框的全选和反选
     jQuery(document).ready(function($) {
          $("#checkAll").click(function(){
             if(this.checked){
                  $("[name='complaintReasonVO.complaintReasons']").attr("checked",'true');  // 全选
             }else {
                 $("[name='complaintReasonVO.complaintReasons']").removeAttr("checked");    // 反选
             }
         });







posted @ 2012-09-10 09:47 奋斗成就男人 阅读(124) | 评论 (0)编辑 收藏

ibatis动态参数和集合参数配置

iterate 

// 此处必须要$,不能用#property<result property="" column=""/>    ibatis是轻量的ORM,类似于一个半自动化化数据操作框架。而hibernate是全自动的ORM。
    ibatis主要是让实体类与数据库的字段名称一一对应,然后在xml编写操作数据库的SQL语句。
    ibatis数据库操作主要包括增删查改。
   主要包括:一:在代码中:
                     通过sqlMapper.queryForList("sql_id",param),其中:sql_id就是我们在xml中编写的sql语句id号(通过此id找到数据库sql语句)
                     parm就是查询条件参数值(一般是一个参数(也有两个参数或者无参数)),参数值可以使对象,int或者String类型。
                二:在xml编写sql语句,主要包括增删查改
                    在写sql语句前,可以做一些其他的简单说明:比如,类别名(类似给类弄一个简称,方法类以后使用),实体类与数据字段一一对应说明等等。
                    <sqlMap namespace="空间名称">
                <typeAlias alias="teacher" type="com.wsw.ibatis.bean.Teacher"/>        // 给类取一个别名,方便以后在后来使用。
                <resultMap class="" id="">                                                             // 给返回的类定一个id号,以后就可以直接用该id表示这个类    
                <result property="属性名" column="数据库字段名"/>                      // 返回的实体类的属性与数据库字段匹配,两者名称可相同或者不同 
                               
<result property="属性名" column=" 数据库字段名"/>
                </resultMap>
                <parameterMap class="" id="">                                                       // 参数类,用于执行sql的参数值,与上面的返回类不同。
            <parameter property="属性名" jdbcType="属性类型"/>                                        
                </parameterMap>
                   </sqlMap>
                  还有就是: parameterClass 表示参数类,用于做参数值。
                                parameterClass  表示返回值类,用于返回值。
                                在这种情况下 ,没有把实体类属性和数据库的字段一一写出,表示实体类属性和数据库的字段名称和类型完全一致。
               ----------------------------------------------------------------------------------------------------------------------------
                    (1):增:     <insert id="addTeacher" parameterClass="com.wsw.ibatis.bean.Teacher">
                                           insert into teacher (id,username, age)values (#id#,#username#,#age#)
                                        </insert>
                             
                    (2):删:   <delete id="deleteAccountById" parameterClass="String">
delete from teacher where id = #id#
</delete>

                   (3):改: <update id="updateTeacher" parameterClass="com.wsw.ibatis.bean.Teacher">
update teacher set username=#username#,age= #age# where id=#id#
</update>

                   (4):查:    <!-- 查找某一条记录 -->
                                <select id="selectTeacherById" parameterClass="int" resultClass="com.wsw.ibatis.bean.Teacher">
                            select * from teacher where id = #id#
</select>
                                       <!-- 查询所有记录 -->
                                <select id="selectAllTeacher" resultClass="com.wsw.ibatis.bean.Teacher">
select * from teacher
</select>
              ===============================================================================================
                    (5):动态按照条件查询 (如果需要循环迭代,最好用list,不要用数组)
                                       <!-- 按照提交参数记录 -->
<select id="selectSomeTeacher" parameterClass="com.wsw.ibatis.bean.Teacher"                                                                   resultClass="com.wsw.ibatis.bean.Teacher" >
                                            select * from teacher 
                                <dynamic prepend="WHERE">                 // 表示动态
                              <isNotEmpty prepend="AND" property="username">        // isNotEmpty 表示如果非空,property表示类属性名
                              <![CDATA[ username in ]]>        
                                                                      <iterate conjunction="," open="(" close=")" property="username" >  // iterate 表示迭代
                                            $usernames[]$              // 此处必须要$,不能用#                     // 迭代必须是集合list 千万不能
                                        </iterate>                                                                                             //是数组
                               <![CDATA[]]>
                                                </isNotEmpty>
<isNotEmpty prepend="AND" property="age">
(age = #age#)                              // 此处最好用#,不要用$
</isNotEmpty>
</dynamic>
</select>
  

posted @ 2012-08-31 00:19 奋斗成就男人 阅读(5139) | 评论 (0)编辑 收藏

struts2表单传值

    struts2表单传值类似栈,然后在action中把表单的各个名称用类属性表示就可以了。然后只需要加上get和set方法
   (1): 文本框:<s:textfield />
              提交: <s:textfield name="paramname"/> 
              Ation处理:用String或者int类型的paramname 表示
              接收:(1):<s:textfield name="paramname "  value="%{paramname }"/>
                      (2):<s:property value="paramname" / "# paramname">
   (2):单选框:<s:radio />
            提交和接受:<s:radio list="{'男','女'}" name="sex" label="性别"/> 
           
   (3):多选框:<s:select />
             提交和接收:<s:checkboxlist name="hobby" listKey="key" listValue="value" list="#{'1':'篮球', '2':'足球', '3':'乒乓球'}"  label="爱好"/>其中key表示值,而value指显示的文字。
            Action处理:用一个list集合表示(注意:千万不要用String[] 数组表示,否则,值无法传回)
   (4):下拉框:<s:select />
           提交和接受:<s:select list="#{1:'北京',2:'上海',3:'广东'}"  label="abc" listKey="key"  listValue="value"  name="address"/>
          Action处理:可以用一个list数组或者String 字符串表示都可以。
=====================================================================================
其中:一般的表单都有三种方式传值:
(1):类似于set集合,只显示值,其中里面就是值

<s:select list="{'aa','bb','cc'}" theme="simple" headerKey="00" headerValue="00"></s:select>

 (2):类似于map,list前面是value值,后面是显示的值

 <s:select list="#{1:'aa',2:'bb',3:'cc'}"  label="abc" listKey="key" listValue="value"  headerKey="0" headerValue="aabb">

 3.从action-->jsp页面:

 <%

 HashMap map = new LinkedHashMap();

map.put(1,"aaa");map.put(2,"bbb");

map.put(3,"ccc");

request.setAttribute("map",map);

request.setAttribute("aa","2");

%>

JSP页面:
 <s:select list="#request.map"  label="abc" listKey="key" listValue="value" value="#request.aa"  headerKey="0" headerValue="aabb"></s:select>

posted @ 2012-08-30 22:49 奋斗成就男人 阅读(1480) | 评论 (2)编辑 收藏

Eclipse Debug不为人知的秘密

Debug视图

认识debug视图,红色部分框为线程堆栈视图,黄色部分框为表达式、断点、变量视图,蓝色部分为代码视图。



 线程堆栈视图

分别介绍一下这几个按钮的含义:

1.表示当前实现继续运行直到下一个断点,快捷键为F8。

2.表示打断整个进程

3.表示进入当前方法,快捷键为F5。

4.表示运行下一行代码,快捷键为F6。

5.表示退出当前方法,返回到调用层,快捷键为F7。

6.表示当前线程的堆栈,从中可以看出在运行哪些代码,并且整个调用过程,以及代码行号



 

变量视图

1.为变量名视图,显示当前代码行中所有可以访问的实例变量和局部变量

2.显示所有的变量值

3.可以通过该窗口来改变变量值



 

断点视图

1.显示所有断点

2. 将当前窗口1中选中的端口失效,再次点击启用。

3.异常断点



 

表达式视图

表达式视图:表达式视图是Debug过程中较为常用的一个视图,可以对自己的感兴趣的一些变量进行观察,也可以增加一些自己的表达式,也可以查看一行代码的运行结果。

1.表达式

2. 点击此可以新增一个表达式



 

代码视图

代码视图:用来显示具体的代码。其中绿色部分是指当前将要执行的代码



 

 

场景一:小明辛苦了两天终于将自己的负责的任务完成了,第二天转测后,测试找到了小明说,小明的程序有bug,可以是小明经过仔细调试,发现本地没有任何问题,但是测试的环境上确实有问题,所以小明遇到了难题,测试的环境linux,又不能上去linux去debug,小明这个时候想要是Linux也可以debug就好了.

远程debug

远程debug:远程debug顾名思义,能够将远程操作系统上的任何java进行debug,但是有前提是本地需要有同步的代码。

1.远程debug的步骤是在远程操作系统上启动java进程时增加特殊的

-Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,address=$DEBUG_PORT,server=y,suspend=n

2.在Eclipse中新建一个Remote Java Application

远程debug

1.打开Debug Configurations视图

2.右击Remote Java Application,

New

3.选择源码工程

4.输入远程IP和端口,端口即服务

端的$DEBUG_PORT,点击OK。




 
 

 

场景一:小明写了一个任务执行者,该执行者不间断的执行一些任务,在现网上运行了一段时间后,发现有概率的出现一些故障,发现运行一段时间后,该任务者异常退出了,退出的因为是空指针,可以小明想要在本地debug,不知道断点打在哪里,该问题是概率事件,不一定会出现,所以小明debug几遍下来后,头晕眼花,连代码都看不清楚了,小明想要是能有个断点每当出现空指针异常的时候就停下来让他发现问题,那该多好呀。

异常断点

异常断点:在定位问题的过程中,常常会遇到断点无法打到合适的位置,以至于和问题的触发点千差万别,所以这个时候不妨试试异常断点,顾名思义,异常断点是指抛出某种异常后自动挂起的断点。

点击红色部位,增加一个异常断点



 

输入想要定位的异常类型,例如NullPointerException,这样系统中抛出任何NullPointerException异常后,都会挂起当前线程,给你机会去定位问题。

 

场景一:小明写了一个巨大的循环,在调测代码时,小明发现每当循环到第100000次的时候,就是出现问题,没有达到自己的预期,于是小明在循环里打了个断点,想看看到底怎么回事,可小明万万没有想到,想要到达100000次循环是多么的困难,小明这个时候已经开始浮想联翩,如果能有这样的断点:

             If 循环次数== 100000,线程停下来

条件断点

如右图,循环1000次,如果想要在循环到500

次的时候停下来,可以创建一个条件断点,右

击断点悬着Breakpoint Properties。



 

选中Enable Condition

在空白处,添加你自己的条件,如果条件返回true,线程会被挂起,如果为false,则忽略该异常

Hit Count为该断点经过多少次后,正式挂起线程,如果设置为500,则表达前499次,经过该断点都不会停下,当第500次,该断点会挂起当前线程。

 

 

表达式

表达式可以查看一些在当前代码中没有的命令行,方便定位问题。

 

场景一:小明最近遇到一个难题,在调用一个第三方插件时总是会有问题,小明怀疑是第三方插件的bug,但小明没有找到源码不能进行debug,小明该怎么办呢?

Debug定位第三方插件的问题

1.使用反编译工具将代码反编译

2.将反编译后的源码进行过滤

3.修复源码编译错误

4.进行debug

Debug一些经验

1.尽量减少debug,少用debug,优秀的程序员总是花80%的时间来思考如何解决问题,20%的时间来动手完成代码,而糟糕的程序员总是用20%的时间去写代码,80%的时间去调试代码,动手之前尽量想好如何去做,并且已经为你自己的思路做了充分的实验。

2.尽可能的提高debug的效率,设置合适的断点,使用快捷键。

3.debug的F6快捷键经常用到,它与金山词霸的快捷键冲突,所以在debug的时候最好将金山词霸关掉。

4.debug的表达式是可执行代码,将会对代码结果产生永久性影响,在调试时注意,经常将不用的表达式清除掉。

posted @ 2012-08-30 18:16 奋斗成就男人 阅读(2858) | 评论 (0)编辑 收藏

通过存储过程对SQLSERVER2005分页

1 通过select top进行分页查询   
/*查询原理:需要查询第N页时,首先取到前N页的所有数据,然后排除前N-1页的数据,就是第N页的数据*/  
create  PROCEDURE GetDataWithPage  
(   
       @pageIndex  int = 1,           -- 页码  
      @pageSize   int = 20,          -- 页尺寸    
)  
as  
    begin  
     if @pageIndex < 1  
begin  
Set @pageIndex=1  
end                   
  
  
--如果是第一页时要执行的语句  
  if @PageIndex = 1  
      begin  
              select top ((@PageIndex)*@PageSize)   
               field1,field2,--查询字段  
               fieldOrderby --排序字段,按什么字段分页的字段,建议使用主键,或者唯一键  
               from tableName --查询表名称  
              where id>100 --查询条件  
              order by fieldOrderby --排序字段,按什么字段分页的字段,  
             select count(*) as Total from tableName where id>100--返回总记录数  
    end  
  else    
         begin  
                 select top ((@PageIndex)*@PageSize) --取出前PageIndex页的数据  
                            field1,field2,--查询字段  
                            fieldOrderby --排序字段,按什么字段分页的字段,建议使用主键,或者唯一键  
                            into #tempTable --插入临时表  
                            from tableName --查询表名称  
                            where id>100 --查询条件  
                           order by fieldOrderby --排序字段,按什么字段分页的字段,  
                  -----取出前pageIndex页数据插入临时表  
  
                 ------排除前pageIndex-1页的数据,取出第pageIndex的数据  
                  select top (@PageIndex) --  
                             field1,field2,--排序字段  
                            fieldOrderby --  
                           from #tempTable --从临时表中取数据  
                          where fieldOrderby --  
                          not in (select  top ((@PageIndex-1)*@PageSize) fieldOrderby from #tempTable)  
                        ---- 从临时表取出 pageIndex的数据   
                            ----可以根据升序或者降序把not in 改为 <min(fieldOrderby)或者>max(fieldOrderby)  
                 select count(*) as Total from tableName where id>100--返回总记录数  
       end  
end  


2通过系统存储过程进行分页查询

[sql] view plaincopy
 /*  
 一共返回三个表第一个表为空 查询字符串的条件中有 like ,in 可能出现问题,具体出现原因不明,第二个表包含总页数,总行数,  
当前页第三个表包含查询记录  
  
*/  
create   procedure [dbo].[GetOnePageData]  
   @sqlstr nvarchar(4000), --查询字符串  ,就是一般的查询语句,不需要top关键字  
   @currentpage int, --第N页  
   @pagesize int --每页行数  
as  
   set nocount on  
   declare @P1 int, --P1是游标的id  
   @rowcount int--  
    exec sp_cursoropen @P1 output,@sqlstr,@scrollopt=1,@ccopt=1,@rowcount=@rowcount output  
   --定义与游标和游标选项相关联的 SQL 语句,然后填充游标。  
   --选择总页数,总行数,当前页  
    select ceiling(1.0*@rowcount/@pagesize) as TotalPages,@rowcount as TotalRows,@currentpage as CurPage  
    set @currentpage=(@currentpage-1)*@pagesize+1  
   --查询记录  
    exec sp_cursorfetch @P1,16,@currentpage,@pagesize --从游标中提取一行或一个行块。  
   --返回值  
    exec sp_cursorclose @P1--关闭并释放游标  
     set nocount off  
go  


3 通过新函数ROW_NUMBER()进行分页查询

[sql] view plaincopy
/*  
适用于sql2005,据调查此方法限制最少,性能最佳  
返回两个表,第一个表包含总行数,第二个表是查询到的记录  
--分页查询的原理:  
--1.先将预分页内容按照排序条件加上自增列导入到临时表中(或表变量)  
--2.针对临时表操作,找到相应的N页对应的自增列编码范围  
--3.根据第N页对应的自增列编码范围,查找第N页内容  
   
--需要注意的是:  
--第一是添加自增列,确定行号  
--第二缩减中间处理过程的操作数据量  
  
*/  
  
create  proc [dbo].[GetOnePageData]--//  
(  
    @page int,  
    @pagesize int  
)  
as  
begin      
        select top  (@pagesize*@page)  ROW_NUMBER() --可以减少处理的数据,加快速度  
         OVER(ORDER BY NodeID) as rowNum,--按什么字段分页的字段,不需要唯一性  
        NodeID,NodeName,ControlIP --查询字段  
        into #temp --插入临时表  
        from TableName   --  查询表名称   
        where NodeID>100 --查询条件  
         
       select count(*) from #temp--总记录条数  
       select * from #temp where rowNum>@pagesize*(@page-1) and rowNum<=@pagesize*@page--  
end   

  综述,如果需要通用的存储过程,可以把第一或者第三种分页方法进行改写,在数据库拼字符串,但性能会差好多。这或许就是通用和性能之间的矛盾吧。















posted @ 2012-08-29 21:31 奋斗成就男人 阅读(801) | 评论 (0)编辑 收藏

SQL分页语句

有关分页 SQL 的资料很多,有的使用存储过程,有的使用游标。本人不喜欢使用游标,我觉得它耗资、效率低;使用存储过程是个不错的选择,因为存储过程是经过预编译的,执行效率高,也更灵活。先看看单条 SQL 语句的分页 SQL 吧。

方法1:
适用于 SQL Server 2000/2005
SELECT TOP 页大小 *
FROM table1
WHERE id NOT IN
          (
          
SELECT TOP 页大小*(数排序-1) id FROM table1 ORDER BY id
          )
ORDER BY id
原理:其中id最好是主键或者索引,这样查询速度比较快)。由页码数,通过sELECT TOP 页大小*(页数排序-1) id FROM tablename ORDER BY id 获取最前面的那几行(top),然后通过id not in 表示要查询的那一页是最后的那一部分,而通过top +页大小表示去最后那一部分记录的最前面的那几天记录(每页记录数)。
为什么直接取最后那一部分的,因为sql只有去前面几条记录top,而没有去最后几条记录的关键字。
方法2:
适用于 SQL Server 2000/2005
--顺序写法:
 SELECT TOP 页大小 *
 FROM table1
 WHERE id >=
 (
 SELECT ISNULL(MAX(id),0) 
 FROM 
 (
 SELECT TOP 页大小*(页数-1)+1 id FROM table1 ORDER BY id
 ) A
 )
 ORDER BY id
 
 --降序写法:
 SELECT TOP 页大小 *
 FROM table1
 WHERE id <=
 (
 SELECT ISNULL(MIN(id),0) 
 FROM 
 (
 SELECT TOP 页大小*(页数-1)+1 id FROM table1 ORDER BY id Desc
 ) A
 )
 ORDER BY id Desc

方法3:
适用于 SQL Server 2005

SELECT TOP 页大小 * 
FROM 
        (
        
SELECT ROW_NUMBER() OVER (ORDER BY id) AS RowNumber,* FROM table1
        ) A
WHERE RowNumber > 页大小*(页数-1)


说明,页大小:每页的行数;页数:第几页。使用时,请把“页大小”和“页大小*(页数-1)”替换成数字。

 

 

 

其它的方案:如果没有主键,可以用临时表,也可以用方案三做,但是效率会低。
建议优化的时候,加上主键和索引,查询效率会提高。

通过SQL 查询分析器,显示比较:我的结论是:
分页方案二:(利用ID大于多少和SELECT TOP分页)效率最高,需要拼接SQL语句
分页方案一:(利用Not In和SELECT TOP分页)   效率次之,需要拼接SQL语句
分页方案三:(利用SQL的游标存储过程分页)    效率最差,但是最为通用

posted @ 2012-08-29 18:36 奋斗成就男人 阅读(459) | 评论 (0)编辑 收藏

仅列出标题
共23页: First 上一页 12 13 14 15 16 17 18 19 20 下一页 Last