2009年3月25日 星期三

Marshalling

http://www.faqs.org/docs/artu/ch05s03.html#id2908194
http://www.codeproject.com/KB/IP/Marshal.aspx
http://blog.carrion.ws/2006/11/06/marshalling-problem-explained/

2009年3月23日 星期一

Linux 下jdk6 和tomcat6的安装配置

linux 下安装jdk6

1、到 sun 网站下载 jdk rpm 软件包 jdk-6u11-linux-i586-rpm.bin;
2、在/usr下建立一个java目录,拷贝 jdk-6u11-linux-i586-rpm.bin 到 java目录;
3、给 jdk-6u11-linux-i586-rpm.bin 加上执行权限,
命令:chmod a+x jdk-6u11-linux-i586-rpm.bin
4、执行: ./jdk-6u11-linux-i586-rpm.bin,得到 jdk-6u11-linux-i586.rpm
5、执行: rmp -ivh jdk-6u11-linux-i586.rpm
6、至此,安装成功,设置环境变量;
7、设置linux的全局环境变量,需要root权限,可在命令行下输入su 切换到root用户;
8、修改etc/profile 文件,在最后加入如下代码:

#set java environment
export JAVA_HOME=/usr/java/jdk1.6.0_11
export PATH=$JAVA_HOME/bin:$JAVA_HOME/jre/bin:$PATH
export CLASSPATH=$CLASSPATH:$JAVA_HOME/lib:$JAVA_HOME/jre/lib

linux 下安装tomcat6
1、到apache网站下载tomcat文件 apache-tomcat-6.0.18.tar.gz;
2、在/usr目录下建立tomcat目录;
3、解压apache-tomcat-6.0.18.tar.gz 文件,
命令 tar -xvzf apache-tomcat-6.0.18.tar.gz
4、修改etc/profile 文件,在最后加入如下代码:
export TOMCAT_HOME=/usr/tomcat
5、如果需要使用manager功能,需修改Tomcat_HOME/conf/tomcat-users.xml 文件,加入


6、启动tomcat,命令行方式改变到安装目录,运行
./catalina.sh run 命令 启动tomcat 有控制台
./catalina.sh start 命令 启动tomcat 无控制台
./startup.sh 启动tomcat 无控制台
7、关闭tomcat,执行
./shutdown.sh 或者 ./catalina.sh stop
8、测试tomcat安装是否成功
http://localhost:8080

source : http://www.blogjava.net/mecury

JVM內存的設置的原理

默認的java虛擬機的大小比較小,在對大數據進行處理時java就會報錯:java.lang.OutOfMemoryError。

設置jvm內存的方法,對於單獨的.class,可以用下面的方法對Test運行時的jvm內存進行設置。
java -Xms64m -Xmx256m Test

-Xms是設置內存初始化的大小
-Xmx是設置最大能夠使用內存的大小(最好不要超過物理內存大小)

在weblogic中,可以在startweblogic.cmd中對每個domain虛擬內存的大小進行設置,默認的設置是在commEnv.cmd裡面。

JVM內存的調優

1. Heap設定與垃圾回收
Java Heap分為3個區,Young,Old和Permanent。 Young保存剛實例化的對象。當該區被填滿時,GC會將對象移到Old區。 Permanent區則負責保存反射對象,本文不討論該區。
JVM的Heap分配可以使用-X參數設定,
-Xms初始Heap大小
-Xmx java heap最大值
-Xmn young generation的heap大小

JVM有2個GC線程。
第一個線程負責回收Heap的Young區。
第二個線程在Heap不足時,遍歷Heap,將Young區升級為Older區。 Older區的大小等於-Xmx減去-Xmn,不能將-Xms的值設的過大,因為第二個線程被迫運行會降低JVM的性能。
為什麼一些程序頻繁發生GC?有如下原因:
程序內調用了System.gc()或Runtime.gc()。
一些中間件軟件調用自己的GC方法,此時需要設置參數禁止這些GC。
Java的Heap太小,一般默認的Heap值都很小。
頻繁實例化對象,Release對象。此時盡量保存並重用對象,例如使用StringBuffer()和String()。
如果你發現每次GC後,Heap的剩餘空間會是總空間的50%,這表示你的Heap處於健康狀態。許多Server端的Java程序每次GC後最好能有65%的剩餘空間。

經驗之談:
1. Server端JVM最好將-Xms和-Xmx設為相同值。為了優化GC,最好讓-Xmn值約等於-Xmx的1/3[2]。
2.一個GUI程序最好是每10到20秒間運行一次GC,每次在半秒之內完成[2]。
注意:
1.增加Heap的大小雖然會降低GC的頻率,但也增加了每次GC的時間。並且GC運行時,所有的用戶線程將暫停,也就是GC期間,Java應用程序不做任何工作。
2. Heap大小並不決定進程的內存使用量。進程的內存使用量要大於-Xmx定義的值,因為Java為其他任務分配內存,例如每個線程的Stack等。

2. Stack的設定
每個線程都有他自己的Stack。
-Xss每個線程的Stack大小

Stack的大小限制著線程的數量。如果Stack過大就好導致內存溢漏。 -Xss參數決定Stack大小,例如-Xss1024K。如果Stack太小,也會導致Stack溢漏。

3.硬件環境
硬件環境也影響GC的效率,例如機器的種類,內存,swap空間,和CPU的數量。
如果你的程序需要頻繁創建很多transient對象,會導致JVM頻繁GC。這種情況你可以增加機器的內存,來減少Swap空間的使用[2]。

4.4種GC
第一種為單線程GC,也是默認的GC。 ,該GC適用於單CPU機器。

第二種為Throughput GC,是多線程的GC,適用於多CPU,使用大量線程的程序。第二種GC與第一種GC相似,不同在於GC在收集Young區是多線程的,但在Old區和第一種一樣,仍然採用單線程。 -XX:+UseParallelGC參數啟動該GC。

第三種為Concurrent Low Pause GC,類似於第一種,適用於多CPU,並要求縮短因GC造成程序停滯的時間。這種GC可以在Old區的回收同時,運行應用程序。 -XX:+UseConcMarkSweepGC參數啟動該GC。

第四種為Incremental Low Pause GC,適用於要求縮短因GC造成程序停滯的時間。這種GC可以在Young區回收的同時,回收一部分Old區對象。 -Xincgc參數啟動該GC。
4種GC的具體描述參見[3]。

參考文章:
1. JVM Tuning. http://www.caucho.com/resin-3.0/performance/jvm-tuning.xtp#garbage-collection
2. Performance tuning Java: Tuning steps
http://h21007.www2.hp.com/dspp/tech/tech_TechDocumentDetailPage_IDX/1,1701,1604,00.html
3. Tuning Garbage Collection with the 1.4.2 JavaTM Virtual Machine .
http://java.sun.com/docs/hotspot/gc1.4.2/


C:\>java -X
-Xmixed mixed mode execution (default)
-Xint interpreted mode execution only
-Xbootclasspath:
set search path for bootstrap classes and resources
-Xbootclasspath/a:
append to end of bootstrap class path
-Xbootclasspath/p:
prepend in front of bootstrap class path
-Xnoclassgc disable class garbage collection
-Xincgc enable incremental garbage collection
-Xbatch disable background compilation
-Xms set initial Java heap size
-Xmx set maximum Java heap size
-Xss set java thread stack size
-Xprof output cpu profiling data
-Xrunhprof[:help]|[:

2009年3月20日 星期五

java.lang.OutOfMemoryError: PermGen space及其解決方法

1、PermGen space的全稱是Permanent Generation space,是指記憶體的永久保存區域OutOfMemoryError: PermGen space從表面上看就是記憶體益出,解決方法也一定是加大記憶體。說說為什麼會記憶體益出:這一部分用於存放Class和Meta的資訊,Class在被 Load的時候被放入PermGen space區域,它和和存放Instance的Heap區域不同,GC(Garbage Collection)不會在主程序運行期對PermGen space進行清理,所以如果你的APP會LOAD很多CLASS的話,就很可能出現PermGen space錯誤。這種錯誤常見在web伺服器對JSP進行pre compile的時候。
改正方法:-Xms256m -Xmx256m -XX:MaxNewSize=256m -XX:MaxPermSize=256m

2、在tomcat中redeploy時出現outofmemory的錯誤. 可以有以下幾個方面的原因:

1. 使用了proxool,因為proxool內部包含了一個老版本的cglib.
2. log4j,最好不用,只用common-logging
3. 老版本的cglib,快點更新到最新版。
4. 更新到最新的hibernate3.2

3、這裏以tomcat環境為例,其他WEB伺服器如jboss,weblogic等是同一個道理。

一、java.lang.OutOfMemoryError: PermGen space

PermGen space的全稱是Permanent Generation space,是指記憶體的永久保存區域,這塊記憶體主要是被JVM存放Class和Meta資訊的,Class在被Loader時就會被放到 PermGen space中,它和存放類實例(Instance)的Heap區域不同,GC(Garbage Collection)不會在主程序運行期對PermGen space進行清理,所以如果你的應用中有很多CLASS的話,就很可能出現PermGen space錯誤,這種錯誤常見在web伺服器對JSP進行pre compile的時候。如果你的WEB APP下都用了大量的第三方jar, 其大小超過了jvm默認的大小(4M)那麼就會產生此錯誤資訊了。

解決方法: 手動設置MaxPermSize大小
修改TOMCAT_HOME/bin/catalina.sh
在“echo "Using CATALINA_BASE: $CATALINA_BASE"”上面加入以下行:

JAVA_OPTS="-server -XX:PermSize=64M -XX:MaxPermSize=128m
建議:將相同的第三方jar檔移置到tomcat/shared/lib目錄下,這樣可以達到減少jar 文檔重複佔用記憶體的目的。
二、java.lang.OutOfMemoryError: Java heap space
Heap size 設置
JVM堆的設置是指java程式運行過程中 JVM可以調配使用的記憶體空間的設置.JVM在啟動的時候會自動設置Heap size的值,其初始空間(即-Xms)是實體記憶體的1/64,最大空間(-Xmx)是實體記憶體的1/4。可以利用JVM提供的-Xmn -Xms -Xmx等選項可進行設置。Heap size 的大小是Young Generation 和Tenured Generaion 之和。

提示:在JVM中如果98%的時間是用於GC且可用的Heap size 不足2%的時候將拋出此異常資訊。

提示:Heap Size 最大不要超過可用實體記憶體的80%,一般的要將-Xms和-Xmx選項設置為相同,而-Xmn為1/4的-Xmx值。
解決方法:手動設置Heap size
修改TOMCAT_HOME/bin/catalina.sh
在“echo "Using CATALINA_BASE: $CATALINA_BASE"”上面加入以下行:
JAVA_OPTS="-server -Xms800m -Xmx800m -XX:MaxNewSize=256m"
三、實例,以下給出1G記憶體環境下java jvm 的參數設置參考:
JAVA_OPTS="-server -Xms800m -Xmx800m -XX:PermSize=64M -XX:MaxNewSize=256m -XX:MaxPermSize=128m -Djava.awt.headless=true "

三、相關資料
/show/3/7/20061112220131.htm
/show/3/7/20061112220054.htm
/show/3/7/20061112220201.htm

Source: http://www.soezblog.com/plate/group/web/papermsg.jsp?UI=markcool&GI=47&PI=827

2009年3月19日 星期四

Java 建立由 LDAP AD 認證的機制

環境:
OS : Windows Server 2k3
Domain: mydomain.com
Host : x.x.x.x(此為指定 ip address)

以 Java 程式撰寫 對 LDAP-AD 的認證, 程式碼如下:


import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import javax.naming.directory.Attribute;
import javax.naming.directory.Attributes;
import javax.naming.directory.BasicAttribute;
import javax.naming.directory.DirContext;
import javax.naming.directory.InitialDirContext;
import javax.naming.directory.ModificationItem;
import javax.naming.directory.SearchControls;
import javax.naming.directory.SearchResult;
import javax.naming.ldap.InitialLdapContext;
import javax.naming.ldap.LdapContext;
 /**
     * AD LDAP 登入認證
     *
     * @param ldap_url   like ldap://x.x.x.x:389/DC=mydomain,DC=com
     * @param account
     * @param password
     * @return String[0] array 0 :0 success,1 fail,2 LDAP connect fail,3 unknow
     */
    public String[] LDAP_AUTH_AD(String ldap_url, String account, String password) {
        String[] returnStr = new String[2];
        Hashtable env = new Hashtable();
        env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
        env.put(Context.PROVIDER_URL, ldap_url);
        env.put(Context.SECURITY_AUTHENTICATION, "simple");
        env.put(Context.SECURITY_PRINCIPAL, account+"@mydomain.com");
        env.put(Context.SECURITY_CREDENTIALS, password);

        LdapContext ctx = null;
        try {
            ctx = new InitialLdapContext(env, null);
            returnStr[0] = "0";
        } catch (javax.naming.AuthenticationException e) {
            returnStr[0] = "1";

            return returnStr;
        } catch (javax.naming.CommunicationException e) {
            // System.out.println("Can't connect to ldap server!");
            returnStr[0] = "2";

            return returnStr;
        } catch (Exception e) {
            System.out.println("error");
            e.printStackTrace();
            returnStr[0] = "3";

            return returnStr;
        } finally {
            if (ctx != null) {
                try {
                    ctx.close();
                } catch (NamingException e) {

                }
            }
        }
    }




From: Polin Wei

Java Filtering 過濾器的使用

Servlet 2.3 規則中最重要的新特性- Filtering , 它相容於 Servlet 2.3 規格的 J2EE 容器(Context)間快速地成為最常被用到的增值特性.

過濾器 (Filtering) 可以在資源被取出前或取出後插手檢查, 以 HTTP 為主的 請求(Request) / 回應(Response) 的中間層伺服器來說, 過濾器 (Filtering) 可以用來:

1. 在請求(Request)的表頭到達資源手中前先看看其中的內容

2. 在請求(Request)的表頭被送達資源時看看其中的內容

3. 提供修改過的請求(Request)被容器(Context)所處理過的資源

4. 在回應(Response)被傳回前, 先行存取並修改

5. 在請求(Request)到逹資源前全部加以終止

過濾器 (Filtering) 為 javax.servlet.Filter 的介面類別, 這類別所該實作的部份有三個方法:

1. doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
這是 過濾器 (Filtering) 的主要方法, 幾乎所有 過濾器 (Filtering) 的工作都在此完成. 在這個方法中需呼叫 chain.doFilter(request, response) 這個方法, 以便將控制傳給下一個過濾器 ( Pass control on to the next filter )

2. init(FilterConfig fConfig)
在 doFilter() 方法被第一次呼叫前設定 FilterConfig 物件. FilterConfig 物件提供 過濾器 (Filtering) 的初始化參數, 並允許它存取相關的 ServletContext.

3. destroy()
當 過濾器 (Filtering) 被帶出服務前, 容器(Context)會呼叫 destroy()

上述所提的 FilterConfig 物件在 init(FilterConfig fConfig) 時會取得, 而 FilterConfig 可以被 過濾器 (Filtering) 用來取得這個 過濾器 (Filtering) 的初始化參數, 文字型名稱, 或正在執行的 ServletContext. 它主要有四個方法:

1. getFilterName()
取得 過濾器 (Filtering) 定義於配置描述檔 web.xml 中的文字型名稱.

2. getInitParameter(String paramName)
取得所指定的初始化參數的字串值. 找不到則回傳 null

3. getInitParameterNames()
取得一個 java.util.Enumeration , 其中含有所有這個實體中所具有的初始化參數的名稱. 這些參數都是在配置描述元 web.xml 中的 定義中所指定的. 若無則回傳 null

4. getServletContext()
取得正在其中執行的 ServletConext . 這個內容通常是在伺服器上的 server.xml 檔中指定.


程式實作:
step 01: 先建立一個 LoggerFilter.java 

package com.demos.filter;

import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;

/**
 * Servlet Filter implementation class LoggerFilter
 */
public class LoggerFilter implements Filter {
    
    protected FilterConfig filterConfig = null;

    /**
     * @see Filter#destroy()
     */
    public void destroy() {
        // TODO Auto-generated method stub
        this.filterConfig = null;
    }

    /**
     * @see Filter#doFilter(ServletRequest, ServletResponse, FilterChain)
     */
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {

        if (filterConfig==null)
            return;

        long bef = System.currentTimeMillis();
        ServletContext context = filterConfig.getServletContext();
        context.log("in LoggerFilter Class");

        // Pass control on to the next filter
        chain.doFilter(request, response);
   
        long aft = System.currentTimeMillis();
        context.log("Request to " + request.getRemoteHost() + "Total time(ms): " + (aft - bef));

    }

    /**
     * @see Filter#init(FilterConfig)
     */
    public void init(FilterConfig fConfig) throws ServletException {
        // TODO Auto-generated method stub
        this.filterConfig = fConfig;
    }
}


step 02: 在 web.xml 上加入Filter的參數

    loggerFilter
    com.demos.filter.LoggerFilter


    loggerFilter
    /*


的樣式可以對 URL 或 servlet 來作 Filter:

/*
action



step 03: 在 console 中看的結果如下:
2009/3/18 下午 6:36:30 org.apache.catalina.core.ApplicationContext log
資訊: in LoggerFilter Class
2009/3/18 下午 6:36:31 org.apache.catalina.core.ApplicationContext log
資訊: Request to 127.0.0.1Total time(ms): 234


實際系統上運用 Filtering 可以讓系統在每一個網頁在載入時, 塞入編碼原則為 UTF-8 , 以避免網頁出現亂碼. 程式碼SetCharacterEncodingFilter.java如下:
/*
* Copyright 2004 The Apache Software Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*     http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
 * @author Craig McClanahan
 * @version $Revision: 1.2 $ $Date: 2004/03/18 16:40:28 $
 */

package com.demos.filters;

import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;

public class SetCharacterEncodingFilter implements Filter {


    // ----------------------------------------------------- Instance Variables


    /**
     * The default character encoding to set for requests that pass through
     * this filter.
     */
    protected String encoding = null;


    /**
     * The filter configuration object we are associated with.  If this value
     * is null, this filter instance is not currently configured.
     */
    protected FilterConfig filterConfig = null;


    /**
     * Should a character encoding specified by the client be ignored?
     */
    protected boolean ignore = true;


    // --------------------------------------------------------- Public Methods

    /**
     * Take this filter out of service.
     */
    public void destroy() {

        this.encoding = null;
        this.filterConfig = null;

    }


    /**
     * Select and set (if specified) the character encoding to be used to
     * interpret request parameters for this request.
     *
     * @param request The servlet request we are processing
     * @param result The servlet response we are creating
     * @param chain The filter chain we are processing
     *
     * @exception IOException if an input/output error occurs
     * @exception ServletException if a servlet error occurs
     */
    public void doFilter(ServletRequest request, ServletResponse response,
                         FilterChain chain)
    throws IOException, ServletException {

        // Conditionally select and set the character encoding to be used
        if (ignore || (request.getCharacterEncoding() == null)) {
            String encoding = selectEncoding(request);
            if (encoding != null)
                request.setCharacterEncoding(encoding);
        }
    // Pass control on to the next filter
        chain.doFilter(request, response);

    }

    /**
     * Place this filter into service.
     *
     * @param filterConfig The filter configuration object
     */
    public void init(FilterConfig filterConfig) throws ServletException {

    this.filterConfig = filterConfig;
        this.encoding = filterConfig.getInitParameter("encoding");
        String value = filterConfig.getInitParameter("ignore");
        if (value == null)
            this.ignore = true;
        else if (value.equalsIgnoreCase("true"))
            this.ignore = true;
        else if (value.equalsIgnoreCase("yes"))
            this.ignore = true;
        else
            this.ignore = false;

    }

    // ------------------------------------------------------ Protected Methods
    protected String selectEncoding(ServletRequest request) {
        return (this.encoding);
    }
}


而 web.xml 也要相對的加入

    Set Character Encoding
   
        com.gu.filters.SetCharacterEncodingFilter
   

   
        encoding
        utf-8
   

   
        ignore
        true
   



    Set Character Encoding
    action




From: Polin Wei

2009年3月16日 星期一

How to setup SVN server

  • 先去Subversion的網站抓SVN Server
  • 把SVN加入到環境變數PATH中,如C:\Program Files\Subversion\bin\
  • 選一個目錄,專門用來放許多案子用的,假設為D:\projects
  • 建立你現在要產生的專案repository, 比如要建PostEX專案
    • svnadmin create d:\projects\PostEX
  • 修改權限檔案
    • 到d:\projects\PostEX\conf裡,修改passwd
      • 在[users]裡,加上你們案子要用的帳號和密碼
        • 如: padsmember = padspassword
    • 修改svnserve.conf,如果你不想讓任意路人甲都可以看到你的程式,在[General]中找到一個anon-access,把它改成none
      • anon-access = none
    • 找到一行 password-db = passwd,把前面的井號去掉,這樣前面修改的passwd檔才會有啟用
  • 啟動SVN Server
    • D:\>svnserve -d -r d:\Projects --listen-port 9000
  • 所有要參與計畫的人,都裝上TortoiseSVN
  • 建立一個目錄,用來抓SVN Server上已經有寫的程式 (別人可能之前先傳上去的)
  • 做checkout,把URL of repository的protocol改成SVN
    • 如: svn://pads15.cs.nthu.edu.tw:9000/PostEX
    • 幾個主要的功能
      • checkout剛加入許畫的人,第一次去把檔案抓下來用的
      • update是已經有checkout的人,後來用來抓SVN Server上更新版用的
      • commit 是你做了更新後,要send到SVN Server上用的


Start up SVN Server command:

C:\Program Files\Subversion>
svnserve -d -r "C:\Documents and Settings\user\My Documents\SvnRepository\projects" --listen-port 9000

Source:
http://yoshiblog.blogspot.com
http://blog.roodo.com/jaceju/archives/2150759.html
http://www.blogjava.net/youxia/category/26691.html

2009年3月12日 星期四

Ping a server in Java

Ping a server

It's not possible to really "ping" a machine to check if it's alive or not (it's a long story, but to keep it short I will just say that the Socket class is not low-level enough for that operation). But we can emulate a ping by talking the "echo port". On a server, the echo port is always port 7. We write a string to that port and the server will echo the string.
import java.io.*;
import java.net.*;

public class PseudoPing {
public static void main(String args[]) {
try {
Socket t = new Socket(args[0], 7);
DataInputStream dis = new DataInputStream(t.getInputStream());
PrintStream ps = new PrintStream(t.getOutputStream());
ps.println("Hello");
String str = dis.readLine();
if (str.equals("Hello"))
System.out.println("Alive!") ;
else
System.out.println("Dead or echo port not responding");
t.close();
}
catch (IOException e) {
e.printStackTrace();}
}
}
}
NOTE: To make this a more "complete PING", you may want to check this How-to to display the response time.

Since JDK1.5, java.net.InetAddress.isReachable(int) can be used to check if a server is reachable or not.

import java.io.*;
import java.net.*;

public class ReachableTest {
public static void main(String args[]) {
try {
InetAddress address = InetAddress.getByName("web.mit.edu");
System.out.println("Name: " + address.getHostName());
System.out.println("Addr: " + address.getHostAddress());
System.out.println("Reach: " + address.isReachable(3000));
}
catch (UnknownHostException e) {
System.err.println("Unable to lookup web.mit.edu");
}
catch (IOException e) {
System.err.println("Unable to reach web.mit.edu");
}
}
}
isReachable() will use ICMP ECHO REQUESTs if the privilege can be obtained, otherwise it will try to establish a TCP connection on port 7 (Echo) of the destination host. But most Internet sites have disabled the service or blocked the requests (except some university web sites like the example above) .

String host = "172.16.0.2"
int timeOut = 3000; // I recommend 3 seconds at least
boolean status = InetAddress.getByName(host).isReachable(timeOut)


source
http://www.rgagnon.com/javadetails
http://blog.wu-boy.com/2008/12/11/620/
http://www.lslnet.com/linux/f/docs1/i25/big5216009.htm

2009年3月10日 星期二

Regular Expression 基礎知識

一個規則運算式就是由普通字元(例如字元 a z)以及特殊字元(稱為元字元)組成的文字模式。該模式描述在查找文字主體時待匹配的一個或多個字串。規則運算式作為一個範本,將某個字元模式與所搜索的字串進行匹配。如:

JScript

VBScript

匹配

/^\[ \t]*$/

"^\[ \t]*$"

匹配一個空白行。

/\d{2}-\d{5}/

"\d{2}-\d{5}"

驗證一個ID 號碼是否由一個2位元數字,一個連字號以及一個5位元數字組成。

/<(.*)>.*<\/\1>/

"<(.*)>.*<\/\1>"

匹配一個 HTML 標記。


下表是元字元及其在規則運算式上下文中的行為的一個完整列表:

字元

描述

\

將下一個字元標記為一個特殊字元、或一個原義字元、或一個 向後引用、或一個八進制轉義符。例如,'n' 匹配字元 "n"'\n' 匹配一個分行符號。序列 '\\' 匹配 "\" "\(" 則匹配 "("

^

匹配輸入字串的開始位置。如果設置了 RegExp 物件的 Multiline 屬性,^ 也匹配 '\n' '\r' 之後的位置。

$

匹配輸入字串的結束位置。如果設置了RegExp 物件的 Multiline 屬性,$ 也匹配 '\n' '\r' 之前的位置。

*

匹配前面的子運算式零次或多次。例如,zo* 能匹配 "z" 以及 "zoo"* 等價於{0,}

+

匹配前面的子運算式一次或多次。例如,'zo+' 能匹配 "zo" 以及 "zoo",但不能匹配 "z"+ 等價於 {1,}

?

匹配前面的子運算式零次或一次。例如,"do(es)?" 可以匹配 "do" "does" 中的"do" ? 等價於 {0,1}

{n}

n 是一個非負整數。匹配確定的 n 次。例如,'o{2}' 不能匹配 "Bob" 中的 'o',但是能匹配 "food" 中的兩個 o

{n,}

n 是一個非負整數。至少匹配n 次。例如,'o{2,}' 不能匹配 "Bob" 中的 'o',但能匹配 "foooood" 中的所有 o'o{1,}' 等價於 'o+''o{0,}' 則等價於 'o*'

{n,m}

m n 均為非負整數,其中n <= m。最少匹配 n 次且最多匹配 m 次。例如,"o{1,3}" 將匹配 "fooooood" 中的前三個 o'o{0,1}' 等價於 'o?'。請注意在逗號和兩個數之間不能有空格。

?

當該字元緊跟在任何一個其他限制符 (*, +, ?, {n}, {n,}, {n,m}) 後面時,匹配模式是非貪婪的。非貪婪模式盡可能少的匹配所搜索的字串,而預設的貪婪模式則盡可能多的匹配所搜索的字串。例如,對於字串 "oooo"'o+?' 將匹配單個 "o",而 'o+' 將匹配所有 'o'

.

匹配除 "\n" 之外的任何單個字元。要匹配包括 '\n' 在內的任何字元,請使用象 '[.\n]' 的模式。

(pattern)

匹配 pattern 並獲取這一匹配。所獲取的匹配可以從產生的 Matches 集合得到,在VBScript 中使用 SubMatches 集合,在JScript 中則使用 $0$9 屬性。要匹配圓括號字元,請使用 '\(' '\)'

(?:pattern)

匹配 pattern 但不獲取匹配結果,也就是說這是一個非獲取匹配,不進行存儲供以後使用。這在使用 "" 字元 (|) 來組合一個模式的各個部分是很有用。例如, 'industr(?:y|ies) 就是一個比 'industry|industries' 更簡略的運算式。

(?=pattern)

正向預查,在任何匹配 pattern 的字串開始處匹配查找字串。這是一個非獲取匹配,也就是說,該匹配不需要獲取供以後使用。例如,'Windows (?=95|98|NT|2000)' 能匹配 "Windows 2000" 中的 "Windows" ,但不能匹配 "Windows 3.1" 中的 "Windows"。預查不消耗字元,也就是說,在一個匹配發生後,在最後一次匹配之後立即開始下一次匹配的搜索,而不是從包含預查的字元之後開始。

(?!pattern)

負向預查,在任何不匹配 pattern 的字串開始處匹配查找字串。這是一個非獲取匹配,也就是說,該匹配不需要獲取供以後使用。例如'Windows (?!95|98|NT|2000)' 能匹配 "Windows 3.1" 中的 "Windows",但不能匹配 "Windows 2000" 中的 "Windows"。預查不消耗字元,也就是說,在一個匹配發生後,在最後一次匹配之後立即開始下一次匹配的搜索,而不是從包含預查的字元之後開始

x|y

匹配 x y。例如,'z|food' 能匹配 "z" "food"'(z|f)ood' 則匹配 "zood" "food"

[xyz]

字元集合。匹配所包含的任意一個字元。例如, '[abc]' 可以匹配 "plain" 中的 'a'

[^xyz]

負值字元集合。匹配未包含的任意字元。例如, '[^abc]' 可以匹配 "plain" 中的'p'

[a-z]

字元範圍。匹配指定範圍內的任意字元。例如,'[a-z]' 可以匹配 'a' 'z' 範圍內的任意小寫字母字元。

[^a-z]

負值字元範圍。匹配任何不在指定範圍內的任意字元。例如,'[^a-z]' 可以匹配任何不在 'a' 'z' 範圍內的任意字元。

\b

匹配一個單詞邊界,也就是指單詞和空格間的位置。例如, 'er\b' 可以匹配"never" 中的 'er',但不能匹配 "verb" 中的 'er'

\B

匹配非單詞邊界。'er\B' 能匹配 "verb" 中的 'er',但不能匹配 "never" 中的 'er'

\cx

匹配由 x 指明的控制字元。例如, \cM 匹配一個 Control-M 或回車符。x 的值必須為 A-Z a-z 之一。否則,將 c 視為一個原義的 'c' 字元。

\d

匹配一個數位字元。等價於 [0-9]

\D

匹配一個非數位字元。等價於 [^0-9]

\f

匹配一個換頁符。等價於 \x0c \cL

\n

匹配一個分行符號。等價於 \x0a \cJ

\r

匹配一個回車符。等價於 \x0d \cM

\s

匹配任何空白字元,包括空格、定位字元、換頁符等等。等價於 [ \f\n\r\t\v]

\S

匹配任何非空白字元。等價於 [^ \f\n\r\t\v]

\t

匹配一個定位字元。等價於 \x09 \cI

\v

匹配一個垂直定位字元。等價於 \x0b \cK

\w

匹配包括底線的任何單詞字元。等價於'[A-Za-z0-9_]'

\W

匹配任何非單詞字元。等價於 '[^A-Za-z0-9_]'

\xn

匹配 n,其中 n 為十六進位轉義值。十六進位轉義值必須為確定的兩個數位長。例如,'\x41' 匹配 "A"'\x041' 則等價於 '\x04' & "1"。規則運算式中可以使用 ASCII 編碼。.

\num

匹配 num,其中 num 是一個正整數。對所獲取的匹配的引用。例如,'(.)\1' 匹配兩個連續的相同字元。

\n

標識一個八進制轉義值或一個向後引用。如果 \n 之前至少 n 個獲取的子運算式,則 n 為向後引用。否則,如果 n 為八進位數字 (0-7),則 n 為一個八進制轉義值。

\nm

標識一個八進制轉義值或一個向後引用。如果 \nm 之前至少有 nm 個獲得子運算式,則 nm 為向後引用。如果 \nm 之前至少有 n 個獲取,則 n 為一個後跟文字 m 的向後引用。如果前面的條件都不滿足,若 n m 均為八進位數字 (0-7),則 \nm 將匹配八進制轉義值 nm

\nml

如果 n 為八進位數字 (0-3),且 m l 均為八進位數字 (0-7),則匹配八進制轉義值 nml

\un

匹配 n,其中 n 是一個用四個十六進位數位表示的 Unicode 字元。例如, \u00A9 匹配版權符號 (©)


下面看幾個例子:
"^The"
:表示所有以"The"開始的字串("There""The cat"等);
"of despair$"
:表示所以以"of despair"結尾的字串;
"^abc$"
:表示開始和結尾都是"abc"的字串——呵呵,只有"abc"自己了;
"notice"
:表示任何包含"notice"的字串。

'*'
'+''?'這三個符號,表示一個或一序列字元重複出現的次數。它們分別表示沒有或
更多一次或更多還有沒有或一次。下面是幾個例子:

"ab*":表示一個字串有一個a後面跟著零個或若干個b。("a", "ab", "abbb",……);
"ab+"
:表示一個字串有一個a後面跟著至少一個b或者更多;
"ab?"
:表示一個字串有一個a後面跟著零個或者一個b
"a?b+$"
:表示在字串的末尾有零個或一個a跟著一個或幾個b

也可以使用範圍,用大括弧括起,用以表示重複次數的範圍。

"ab{2}":表示一個字串有一個a跟著2b"abb");
"ab{2,}"
:表示一個字串有一個a跟著至少2b
"ab{3,5}"
:表示一個字串有一個a跟著35b

請注意,你必須指定範圍的下限(如:"{0,2}"而不是"{,2}")。還有,你可能注意到了,'*''+'
'?'
相當於"{0,}""{1,}""{0,1}"
還有一個'¦',表示操作:

"hi¦hello":表示一個字串裡有"hi"或者"hello"
"(b¦cd)ef"
:表示"bef""cdef"
"(a¦b)*c"
:表示一串"a""b"混合的字串後面跟一個"c"

'.'可以替代任何字元:

"a.[0-9]":表示一個字串有一個"a"後面跟著一個任意字元和一個數位;
"^.{3}$"
:表示有任意三個字元的字串(長度為3個字元);

方括號表示某些字元允許在一個字串中的某一特定位置出現:

"[ab]":表示一個字串有一個"a""b"(相當於"a¦b");
"[a-d]"
:表示一個字串包含小寫的'a''d'中的一個(相當於"a¦b¦c¦d"或者"[abcd]");
"^[a-zA-Z]"
:表示一個以字母開頭的字串;
"[0-9]%"
:表示一個百分號前有一位元的數字;
",[a-zA-Z0-9]$"
:表示一個字串以一個逗號後面跟著一個字母或數位結束。

你也可以在方括號裡用'^'表示不希望出現的字元,'^'應在方括號裡的第一位。(如:"%[^a-zA-Z]%"
示兩個百分號中不應該出現字母)。

為了逐字表達,必須在"^.$()¦*+?{\"這些字元前加上轉移字元'\'

請注意在方括號中,不需要轉義字元。

source: http://hi.baidu.com/ismayday/blog

2009年3月4日 星期三

Write Java WebStart Application in 5 minutes

They say, the best way of learning is to do-it-yourself. When I was assigned to write an article on Java Webstart, I thought to truly understand what's happening with Java Web Start, let's create a program and try to deploy it through any web server.

Pre-requisities

  1. You need to have the latest version of JDK installed on your system before you can proceed. We use JDK 1.6. Here is a guide to install JDK 1.6 / Java SE 6 in Linux under 5 minutes.
  2. You will ideally need a source code editor like JEdit. At the least use notepad or vi (on *nix) to edit the source code. Do not use any word processing programs like Microsoft Word or Open Office Writer.
  3. Create a Java file that you want to run using JNLP. This can be a regular Swing or AWT based application. It can even be a console application if you wish.
  4. Compile and test your source code(s) as you would with a regular program.

Create a Jar file

Java Web Start applications need to be packaged within a jar file. You can create a .jar file from your class file(s) using this command (assume you class file is named Test.class):

   jar cvf test.jar Test.class
Note: v is for verbose mode. You can omit it if you want.

Create a key

You need to create a keystore which will then be used to sign the jar files:

      keytool -genkey -keystore myKeys -alias jdc

When prompted, fill in your name. You can skip the other details if you want.

Note: myKeys is the name of your keystore. You will need it in the next step to sign the jar file(s).

Now let's sign the jar file(s)

Run the command below to sign the jar file. When prompted for password, give it a six letter, easy to remember (just for demo not for production) password.

 jarsigner -keystore myKeys *.jar jdc

Create a JNLP file

jnlp

A JNLP file provides the specification for your Java Web Start application. We will not cover the details of a JNLP file in this brief guide. However we will provide you with a simple jnlp file which you can use for many occassions. JNLP file is in XML format. Use a source code editor to edit the file. Let's save it as test.jnlp on the document root of your local web server. You can use JWS, a simple web server that ships with Java Web Start, Apache, Tomcat or any other web server. The web server itself doesn't need any special capability to serve Java Web Start applications.

Note:

1. The main-class (test) is the main class of your application
2. We have used to allow the JNLP application to access all client resource. This is not something you may want to do in production environment. In production you should only ask for permissions that you really need to give customers peace of mind. Check the documentation of j2ee-application-client-permissions for details.

Create html file and run the baby!

Create a html file in the same location as the other files containing just the link to your jnlp file on your web server like say http://localhost/test.jnlp in this example. Now gather around your peers and boss (if you are feeling adventurous) and open the html file you just created in any browser. You will be prompted to open it in Java Web Start. Agree to it and also agree to any subsequent message asking you to grant permission to the application.

That's it guys! Wasn't that easy?


source: http://blog.taragana.com/

2009年3月1日 星期日

Oracle SQL裡常用的時間函數

Oracle SQL裡常用的時間函數,經典推薦

相信很多人都有過統計某些數據的經歷,比如,要統計財務的情況,可能要按每年,每季度,每月,甚至每個星期來分別統計。 那在oracle中應該怎麼來寫sql語句呢,這個時候Oracle的日期函數會給我們很多幫助。

常用日期型函數
1。 Sysdate當前日期和時間
SQL> Select sysdate from dual;

SYSDATE
----------
21-6月-05

2。 Last_day本月最後一天
SQL> Select last_day(sysdate) from dual;

LAST_DAY(S
----------
30-6月-05

3。 Add_months(d,n)當前日期d後推n個月用於從一個日期值增加或減少一些月份
date_value:=add_months(date_value,number_of_months)

SQL> Select add_months(sysdate,2) from dual;

ADD_MONTHS
----------
21-8月-05

4。 Months_between(f,s)日期f和s間相差月數
SQL> select months_between(sysdate,to_date('2005-11-12','yyyy-mm-dd'))from dual;

MONTHS_BETWEEN(SYSDATE,TO_DATE('2005-11-12','YYYY-MM-DD'))
-------------------------------------------------- --------
-4.6966741

5。 NEXT_DAY(d, day_of_week)
返回由"day_of_week"命名的,在變量"d"指定的日期之後的第一個工作日的日期。 參數"day_of_week"必須為該星期中的某一天。
SQL> SELECT next_day(to_date('20050620','YYYYMMDD'),1) FROM dual;

NEXT_DAY(T
----------
26-6月-05

6。 current_date()返回當前會話時區中的當前日期
date_value:=current_date
SQL> column sessiontimezone for a15
SQL> select sessiontimezone,current_date from dual;

SESSIONTIMEZONE CURRENT_DA
--------------- ----------
+08:00 13-11月-03


SQL> alter session set time_zone='-11:00' 2 /
會話已更改。

SQL> select sessiontimezone,current_timestamp from dual;

SESSIONTIMEZONE CURRENT_TIMESTAMP
--------------- ----------------------------------- -
-11:00 12-11月-03 04.59.13.668000下午-11:00

7。 current_timestamp()以timestamp with time zone數據類型返回當前會話時區中的當前日期
SQL> select current_timestamp from dual;

CURRENT_TIMESTAMP
-------------------------------------------------- -------------------------
21-6月-05 10.13.08.220589上午+08:00

8。 dbtimezone()返回時區
SQL> select dbtimezone from dual;

DBTIME
------
-08:00

9。 extract()找出日期或間隔值的字段值
date_value:=extract(date_field from [datetime_value|interval_value])
SQL> select extract(month from sysdate) "This Month" from dual;

This Month
----------
6

SQL> select extract(year from add_months(sysdate,36)) " Years" from dual;

Years
----------
2008

10。 localtimestamp()返回會話中的日期和時間
SQL> select localtimestamp from dual;

LOCALTIMESTAMP
-------------------------------------------------- -------------------------
21-6月-05 10.18.15.855652上午

11。取得week number
TO_CHAR(TO_DATE('2007/05/16','YYYY/MM/DD'),'IW') AS WEEK




常用日期數據格式(該段為摘抄)

Y或YY或YYY年的最後一位,兩位或三位Select to_char(sysdate,’YYY’) from dual; 002表示2002年
SYEAR或YEAR SYEAR使公元前的年份前加一負號Select to_char(sysdate,’SYEAR’) from dual; -1112表示公元前111 2年
Q季度,1~3月為第一季度Select to_char(sysdate,’Q’) from dual; 2表示第二季度①
MM月份數Select to_char(sysdate,’MM’) from dual; 12表示12月
RM月份的羅馬錶示Select to_char(sysdate,’RM’) from dual; IV表示4月
Month用9個字符長度表示的月份名Select to_char(sysdate,’Month’) from dual; May後跟6個空格表示5月
WW當年第幾週Select to_char(sysdate,’WW’) from dual; 24表示2002年6月13日為第24週
W本月第幾週Select to_char(sysdate,’W’) from dual; 2002年10月1日為第1週
DDD當年第幾, 1月1日為001,2月1日為032 Select to_char(sysdate,’DDD’) from dual; 363 2002年1 2月2 9日為第363天
DD當月第幾天Select to_char(sysdate,’DD’) from dual; 04 10月4日為第4天
D週內第幾天Select to_char(sysdate,’D’) from dual; 5 2002年3月14日為星期一
DY週內第幾天縮寫Select to_char(sysdate,’DY’) from dual; SUN 2002年3月24日為星期天
HH或HH12 12進制小時數Select to_char(sysdate,’HH’) from dual; 02午夜2點過8分為02
HH24 24小時制Select to_char(sysdate,’HH24’) from dual; 14下午2點08分為14
MI分鐘數(0~59) Select to_char(sysdate,’MI’) from dual; 17下午4點17分
SS秒數(0~59) Select to_char(sysdate,’SS’) from dual; 22 11點3分22秒提示注意不要將MM格式用於分鐘(分鐘應該使用MI)。 MM是用於月份的格式,將它用於分鐘也能工作,但結果是錯誤的。


現在給出一些實踐後的用法:

1。 上月末天:
SQL> select to_char(add_months(last_day(sysdate),-1),'yyyy-MM-dd') LastDay from dual;

LASTDAY
----------
2005-05-31

2。 上月今天
SQL> select to_char(add_months(sysdate,-1),'yyyy-MM-dd') PreToday from dual;


PRETODAY
----------
2005-05-21

3.上月首天
SQL> select to_char(add_months(last_day(sysdate)+1,-2),'yyyy-MM-dd') firstDay from dual;

FIRSTDAY
----------
2005-05-01

4.按照每週進行統計
SQL> select to_char(sysdate,'ww') from dual group by to_char(sysdate,'ww');

TO
--
25

5。 按照每月進行統計
SQL> select to_char(sysdate,'mm') from dual group by to_char(sysdate,'mm');

TO
--
06

6。 按照每季度進行統計
SQL> select to_char(sysdate,'q') from dual group by to_char(sysdate,'q');

T
-
2

7。 按照每年進行統計
SQL> select to_char(sysdate,'yyyy') from dual group by to_char(sysdate,'yyyy');

TO_C
----
2005

8.要找到某月中所有周五的具體日期
select to_char(td,'YY-MM-DD') from (
select trunc(sysdate, 'MM')+rownum-1 as d
from dba_objects
where rownum <>

and trim(to_char(td, 'Day')) = '星期五'
--------
03-05-02
03-05-09
03-05-16
03-05-23
03-05-30

如果把where to_char(td, 'MM') = to_char(sysdate, 'MM')改成sysdate-90,即為查找當前月份的前三個月中的每週五的日期。

9.oracle中時間運算

內容如下:
1、oracle支持對日期進行運算
2、日期運算時是以天為單位進行的
3、當需要以分秒等更小的單位算值時,按時間進制進行轉換即可
4、進行時間進制轉換時注意加括號,否則會出問題

SQL> alter session set nls_date_format='yyyy-mm-dd hh:mi:ss';

會話已更改。

SQL> set serverout on
SQL> declare
2 DateValue date;
3 begin
4 select sysdate into DateValue from dual;
5 dbms_output.put_line('原時間:'||to_char(DateValue));
6 dbms_output.put_line('原時間減1天:'||to_char(DateValue-1));
7 dbms_output.put_line('原時間減1天1小時:'||to_char(DateValue-1-1/24));
8 dbms_output.put_line('原時間減1天1小時1分:'||to_char(DateValue-1-1/24-1/(24*60)));
9 dbms_output.put_line('原時間減1天1小時1分1秒:'||to_char(DateValue-1-1/24-1/(24*60)-1/(24*60*60))) ;
10 end;
11 /
原時間:2003-12-29 11:53:41
原時間減1天:2003-12-28 11:53:41
原時間減1天1小時:2003-12-28 10:53:41
原時間減1天1小時1分:2003-12-28 10:52:41
原時間減1天1小時1分1秒:2003-12-28 10:52:40

PL/SQL過程已成功完成。


在Oracle中實現時間相加處理
--名稱:Add_Times
--功能:返回d1與NewTime相加以後的結果,實現時間的相加
--說明:對於NewTime中的日期不予考慮
--日期:2004-12-07
--版本:1.0
--作者:Kevin


create or replace function Add_Times(d1 in date,NewTime in date) return date
is
hh number;
mm number;
ss number;
hours number;
dResult date;
begin
--下面依次取出時、分、秒
select to_number(to_char(NewTime,'HH24')) into hh from dual;
select to_number(to_char(NewTime,'MI')) into mm from dual;
select to_number(to_char(NewTime,'SS')) into ss from dual;
--換算出NewTime中小時總和,在一天的百分幾
hours := (hh + (mm / 60) + (ss / 3600))/ 24;
--得出時間相加後的結果
select d1 + hours into dResult from dual;
return(dResult);
end Add_Times;


--測試用例
-- select Add_Times(sysdate,to_date('2004-12-06 03:23:00','YYYY-MM-DD HH24:MI:SS')) from dual


在Oracle9i中計算時間差計算時間差是Oracle DATA數據類型的一個常見問題。 Oracle支持日期計算,你可以創建諸如“日期1-日期2”這樣的表達式來計算這兩個日期之間的時間差。


一旦你發現了時間差異,你可以使用簡單的技巧來以天、小時、分鐘或者秒為單位來計算時間差。 為了得到數據差,你必須選擇合適的時間度量單位,這樣就可以進行數據格式隱藏。

使用完善複雜的轉換函數來轉換日期是一個誘惑,但是你會發現這不是最好的解決方法。

round(to_number(end-date-start_date))-消逝的時間(以天為單位)

round(to_number(end-date-start_date)*24)-消逝的時間(以小時為單位)

round(to_number(end-date-start_date)*1440)-消逝的時間(以分鐘為單位)

顯示時間差的默認模式是什麼? 為了找到這個問題的答案,讓我們進行一個簡單的SQL *Plus查詢。

SQL> select sysdate-(sysdate-3) from dual;

SYSDATE-(SYSDATE-3)
-------------------
3

這裡,我們看到了Oracle使用天來作為消逝時間的單位,所以我們可以很容易的使用轉換函數來把它轉換成小時或者分鐘。 然而,當分鐘數不是一個整數時,我們就會遇到放置小數點的問題。

Select
(sysdate-(sysdate-3.111))*1440
from
dual;

(SYSDATE-(SYSDATE-3.111))*1440
------------------------------
4479.83333

當然,我們可以用ROUND函數(即取整函數)來解決這個問題,但是要記住我們必須首先把DATE數據類型轉換成NUMBER數據類型。

Select
round(to_number(sysdate-(sysdate-3.111))*1440)
from
dual;

ROUND(TO_NUMBER(SYSDATE-(SYSDATE-3.111))*1440)
----------------------------------------------
4480

我們可以用這些函數把一個消逝時間近似轉換成分鐘並把這個值寫入Oracle表格中。 在這個例子裡,我們有一個離線(logoff)系統級觸發機制來計算已經開始的會話時間並把它放入一個Oracle STATSPACK USER_LOG擴展表格之中。

Update
perfstat.stats$user_log
set
elapsed_minutes =
round(to_number(logoff_time-logon_time)*1440)
where
user = user_id
and
elapsed_minutes is NULL;

查出任一年月所含的工作日
CREATE OR REPLACE FUNCTION Get_WorkingDays(
ny IN VARCHAR2
) RETURN INTEGER IS
/*------------------------------------------------ ------------------------------------------
函數名稱:Get_WorkingDays
中文名稱:求某一年月中共有多少工作日作者姓名: XINGPING
編寫時間: 2004-05-22
輸入參數:NY:所求包含工作日數的年月,格式為yyyymm,如200405
返回值:整型值,包含的工作日數目。
算法描述:
1).列舉出參數給出的年月中的每一天。 這裡使用了一個表(ljrq是我的庫中的一張表。這個表可以是有權訪問的、記錄條數至少為31的任意一張表或視圖)來構造出某年月的每一天。
2).用這些日期和一個已知星期幾的日期相減(2001-12-30是星期天),所得的差再對7求模。 如果所求年月在2001-12-30以前,那麼所得的差既是負數,求模後所得值範圍為大於-6,小於0,如-1表示星期六,故先將求模的結果加7,再求7的模.
3).過濾掉結果集中值為0和6的元素,然後求count,所得即為工作日數目。
-------------------------------------------------- -----------------------------------------------*/
Result INTEGER;
BEGIN
SELECT COUNT(*) INTO Result
FROM (SELECT MOD(MOD(q.rq-to_date('2001-12-30','yyyy-mm-dd'),7),7) weekday
FROM ( SELECT to_date(ny||t.dd,'yyyymmdd') rq
FROM (SELECT substr(100+ROWNUM,2,2) dd
FROM ljrq z WHERE Rownum<=31 ) t WHERE to_date(ny||t.dd,'yyyymmdd') BETWEEN to_date(ny,'yyyymm') AND last_day(to_date(ny,'yyyymm')) )q ) a WHERE a.weekday NOT IN(0,6); RETURN Result; END Get_WorkingDays;

______________________________________

還有一個版本
CREATE OR REPLACE FUNCTION Get_WorkingDays(
ny IN VARCHAR2
) RETURN INTEGER IS
/*------------------------------------------------ -----------------------------------------
函數名稱:Get_WorkingDays
中文名稱:求某一年月中共有多少工作日作者姓名: XINGPING
編寫時間: 2004-05-23
輸入參數:NY:所求包含工作日數的年月,格式為yyyymm,如200405
返回值:整型值,包含的工作日數目。
算 法描述:使用Last_day函數計算出參數所給年月共包含多少天,根據這個值來構造一個循環。 在這個循環中先求這個月的每一天與一個已知是星期天的日期(2001-12-30是星期天)的差,所得的差再對7求模。 如果所求日期在2001-12-30以前,那麼所得的差既是負數,求模後所得值範圍為大於-6,小於0,如-1表示星期六,故先將求模的結果加7,再求7 的模.如過所得值不等於0和6(即不是星期六和星期天),則算一個工作日。
-------------------------------------------------- --------------------------------------*/
Result INTEGER := 0;
myts INTEGER; --所給年月的天數
scts INTEGER; --某天距2001-12-30所差的天數
rq DATE;
djt INTEGER := 1; --
BEGIN
myts := to_char(last_day(to_date(ny,'yyyymm')),'dd');
LOOP
rq := TO_date(ny||substr(100+djt,2),'yyyymmdd');
scts := rq - to_date('2001-12-30','yyyy-mm-dd');
IF MOD(MOD(scts,7)+7,7) NOT IN(0,6) THEN
Result := Result + 1;
END IF;
djt := djt + 1;
EXIT WHEN djt>myts;
END LOOP;
RETURN Result;
END Get_WorkingDays;

以上兩個版本的比較

第一個版本一條SQL語句就可以得出結果,不需要編程就可以達到目的。 但需要使用任意一張有權訪問的、記錄條數至少為31的一張表或視圖。
第二個版本需要編程,但不需要表或者視圖。
這兩個版本都還存在需要完善的地方,即沒有考慮節日,如五一、十一、元旦、春節這些節假期都沒有去除。 這些節假日應該維護成一張表,然後通過查表來去除這些節假日。

求一段連續日期,但排除六日
自已標記一下,方便以後查尋

select allday from (
select to_date('2007-02-15','yyyy-mm-dd')+rownum allday from
(select to_date('2007-02-15','yyyy-mm-dd'),to_date('2007-02-28','yyyy-mm-dd') from dual)
connect by rownum <>1 and to_char(allday,'D') <7>



source: http://oracled2k.pixnet.net/blog