<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    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 奮斗成就男人 閱讀(179) | 評論 (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 奮斗成就男人 閱讀(170) | 評論 (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 奮斗成就男人 閱讀(227) | 評論 (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 奮斗成就男人 閱讀(194) | 評論 (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 奮斗成就男人 閱讀(126) | 評論 (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 奮斗成就男人 閱讀(5148) | 評論 (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 奮斗成就男人 閱讀(1495) | 評論 (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 奮斗成就男人 閱讀(2872) | 評論 (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 奮斗成就男人 閱讀(817) | 評論 (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 奮斗成就男人 閱讀(474) | 評論 (0)編輯 收藏

    僅列出標題
    共23頁: First 上一頁 12 13 14 15 16 17 18 19 20 下一頁 Last 
    主站蜘蛛池模板: 久久电影网午夜鲁丝片免费| 亚洲国产成人超福利久久精品| 18勿入网站免费永久| 一区二区三区在线免费观看视频| 久久精品国产亚洲av麻豆蜜芽 | 亚洲色欲色欲www在线播放| 亚洲高清在线观看| 亚洲视频在线免费| 国产成人精品男人免费| 国产成人A在线观看视频免费| 无码国产精品一区二区免费3p | 卡1卡2卡3卡4卡5免费视频| **实干一级毛片aa免费| 黄色网页在线免费观看| 一级人做人a爰免费视频| 亚洲成aⅴ人片久青草影院按摩| 亚洲国产精品乱码在线观看97| 亚洲AV无码欧洲AV无码网站| 久久久久亚洲爆乳少妇无| 亚洲AⅤ永久无码精品AA| 国产精品成人免费综合| 暖暖在线日本免费中文| 岛国大片免费在线观看| 久久天天躁狠狠躁夜夜免费观看| 午夜免费1000部| 亚洲精品视频在线观看免费| 99爱在线精品视频免费观看9| 久久午夜免费鲁丝片| 日韩中文字幕免费视频| 亚洲免费精彩视频在线观看| 日本高清免费观看| 无码A级毛片免费视频内谢| 日韩免费在线视频| 亚洲精品免费在线| 一色屋成人免费精品网站| 免费99精品国产自在现线| AV片在线观看免费| 国产色爽免费视频| 亚洲精品成人片在线观看| 色噜噜亚洲精品中文字幕| 久久噜噜噜久久亚洲va久|