廣告聯播

顯示具有 Java 標籤的文章。 顯示所有文章
顯示具有 Java 標籤的文章。 顯示所有文章

2015年8月18日 星期二

Oracle Linux 上安裝JDK(Java Development Kit)

From: Polin Wei

 之前的 JBoss 的 JBoss EAP6 Domain Mode Setup 與 JBoss EAP6.x Standalone Mode Cluster Configuration 都在 Windows 平台上作測試,現在起將拋棄 微軟 擁抱 Linux,因為後續的資料庫也是使用 Oracle DataBase,因此 Linux 平台選擇 Oracle Linux,大致的安裝過程可以查看 Oracle Linux Install Using LVM

安裝檔下載:
1. Oracle Linux 的來源可從下面取得:
https://edelivery.oracle.com/linux

2. 下載JDK:

Oracle的官網可以下載到最新的JDK版本,官網網址如下:http://www.oracle.com/technetwork/java/javase/downloads/index.html
所有的版本:http://www.oracle.com/technetwork/java/archive-139210.html

3. 指令:

會使用到 rpm 或 yum 的安裝移除令,可以參考 yum 基本介紹和參數說明

安裝 JDK 方法一開始(建議以此方法為主):

1. 查詢 Oracle Linux 預設的 openJDK : OracleLinux7.1_x86_64 所搭配的 Java 是 openJDK ,用 rpm -qa | grep java 查詢後將它移除

[root@localhost ~]# rpm -qa | grep java
java-1.7.0-openjdk-1.7.0.75-2.5.4.2.0.1.el7_0.x86_64
python-javapackages-3.4.1-6.el7_0.noarch
javapackages-tools-3.4.1-6.el7_0.noarch
tzdata-java-2015a-1.el7.noarch
java-1.7.0-openjdk-headless-1.7.0.75-2.5.4.2.0.1.el7_0.x86_64

2. 移除 openJDK ,可以使用 yum remove java* 或者 rpm -e package_name 指令

[root@localhost ~]# yum remove java*
Loaded plugins: langpacks
Resolving Dependencies
--> Running transaction check
---> Package java-1.7.0-openjdk.x86_64 1:1.7.0.75-2.5.4.2.0.1.el7_0 will be erased
--> Processing Dependency: java-1.7.0-openjdk for package: icedtea-web-1.5.2-0.el7.x86_64
---> Package java-1.7.0-openjdk-headless.x86_64 1:1.7.0.75-2.5.4.2.0.1.el7_0 will be erased
---> Package javapackages-tools.noarch 0:3.4.1-6.el7_0 will be erased
--> Processing Dependency: jpackage-utils for package: rhino-1.7R4-5.el7.noarch
--> Processing Dependency: jpackage-utils for package: rhino-1.7R4-5.el7.noarch
--> Processing Dependency: jpackage-utils for package: tagsoup-1.2.1-8.el7.noarch
--> Processing Dependency: jpackage-utils >= 1.6 for package: tagsoup-1.2.1-8.el7.noarch
--> Processing Dependency: jpackage-utils for package: jline-1.0-8.el7.noarch
--> Running transaction check
---> Package icedtea-web.x86_64 0:1.5.2-0.el7 will be erased
---> Package jline.noarch 0:1.0-8.el7 will be erased
---> Package rhino.noarch 0:1.7R4-5.el7 will be erased
---> Package tagsoup.noarch 0:1.2.1-8.el7 will be erased
--> Finished Dependency Resolution

Dependencies Resolved

================================================================================
 Package                Arch   Version                      Repository     Size
================================================================================
Removing:
 java-1.7.0-openjdk     x86_64 1:1.7.0.75-2.5.4.2.0.1.el7_0 @anaconda/7.1 493 k
 java-1.7.0-openjdk-headless
                        x86_64 1:1.7.0.75-2.5.4.2.0.1.el7_0 @anaconda/7.1  90 M
 javapackages-tools     noarch 3.4.1-6.el7_0                @anaconda/7.1 155 k
Removing for dependencies:
 icedtea-web            x86_64 1.5.2-0.el7                  @anaconda/7.1 1.8 M
 jline                  noarch 1.0-8.el7                    @anaconda/7.1  72 k
 rhino                  noarch 1.7R4-5.el7                  @anaconda/7.1 1.0 M
 tagsoup                noarch 1.2.1-8.el7                  @anaconda/7.1 140 k

Transaction Summary
================================================================================
Remove  3 Packages (+4 Dependent packages)

Installed size: 94 M
Is this ok [y/N]: y
Downloading packages:
Running transaction check
Running transaction test
Transaction test succeeded
Running transaction
Warning: RPMDB altered outside of yum.
  Erasing    : icedtea-web-1.5.2-0.el7.x86_64                               1/7
  Erasing    : rhino-1.7R4-5.el7.noarch                                     2/7
  Erasing    : jline-1.0-8.el7.noarch                                       3/7
  Erasing    : tagsoup-1.2.1-8.el7.noarch                                   4/7
  Erasing    : 1:java-1.7.0-openjdk-1.7.0.75-2.5.4.2.0.1.el7_0.x86_64       5/7
  Erasing    : 1:java-1.7.0-openjdk-headless-1.7.0.75-2.5.4.2.0.1.el7_0.x   6/7
  Erasing    : javapackages-tools-3.4.1-6.el7_0.noarch                      7/7
  Verifying  : 1:java-1.7.0-openjdk-headless-1.7.0.75-2.5.4.2.0.1.el7_0.x   1/7
  Verifying  : icedtea-web-1.5.2-0.el7.x86_64                               2/7
  Verifying  : tagsoup-1.2.1-8.el7.noarch                                   3/7
  Verifying  : rhino-1.7R4-5.el7.noarch                                     4/7
  Verifying  : 1:java-1.7.0-openjdk-1.7.0.75-2.5.4.2.0.1.el7_0.x86_64       5/7
  Verifying  : jline-1.0-8.el7.noarch                                       6/7
  Verifying  : javapackages-tools-3.4.1-6.el7_0.noarch                      7/7

Removed:
  java-1.7.0-openjdk.x86_64 1:1.7.0.75-2.5.4.2.0.1.el7_0
  java-1.7.0-openjdk-headless.x86_64 1:1.7.0.75-2.5.4.2.0.1.el7_0
  javapackages-tools.noarch 0:3.4.1-6.el7_0

Dependency Removed:
  icedtea-web.x86_64 0:1.5.2-0.el7         jline.noarch 0:1.0-8.el7
  rhino.noarch 0:1.7R4-5.el7               tagsoup.noarch 0:1.2.1-8.el7

Complete!

3. 使用 rpm 指令安裝 jdk-8u45-linux-x64.rpm

[root@localhost tmp]# rpm -ivh jdk-8u45-linux-x64.rpm
正在準備…                       ################################# [100%]
Updating / installing...
   1:jdk1.8.0_45-2000:1.8.0_45-fcs    ################################# [100%]
Unpacking JAR files...
    rt.jar...
    jsse.jar...
    charsets.jar...
    tools.jar...
    localedata.jar...
    jfxrt.jar...
    plugin.jar...
    javaws.jar...
    deploy.jar...
[root@localhost tmp]# java -version
java version "1.8.0_45"
Java(TM) SE Runtime Environment (build 1.8.0_45-b14)
Java HotSpot(TM) 64-Bit Server VM (build 25.45-b02, mixed mode)
[root@localhost tmp]# javac -version
javac 1.8.0_45

利用 rpm 安裝完的 JDK,根目錄會在 /usr/java/jdk1.8.0_45
[root@localhost java]# pwd
/usr/java
[root@localhost java]# ls -l
總計 4
lrwxrwxrwx. 1 root root   16  8月 17 16:36 default -> /usr/java/latest
drwxr-xr-x. 9 root root 4096  8月 17 16:36 jdk1.8.0_45
lrwxrwxrwx. 1 root root   21  8月 17 16:36 latest -> /usr/java/jdk1.8.0_45

4. 編輯「/etc/profile」檔案

這個profile檔案裡寫的指令在系統開機時會自動執行。
 使用「export」指令來設定Java相關的系統環境變數。要設定的變數有「JAVA_HOME」、「JRE_HOME」、「PATH」、 「CLASSPATH」。「JAVA_HOME」為JDK的目錄,就是剛剛複製到「/usr/lib」目錄中的JDK目錄,「JRE_HOME」為 JRE(Java Runtime Environment)的目錄,JDK有包含JRE,位置就在JDK目錄下的「jre」目錄。「PATH」變數為系統尋找指令(檔案)的路徑,將 「JAVA_HOME」變數和「JRE_HOME」變數加進原先的「PATH」變數前。「CLASSPATH」變數為Java尋找Java程式所使用到的 Class路徑,路徑可以是目錄也可以是.jar檔案,將目前的目錄「.」和「$JAVA_HOME/lib」與「$JAVA_HOME/jre /lib」加進變數中吧!

範例如下:
export JAVA_HOME=/usr/java/jdk1.8.0_45
export JRE_HOME=/usr/java/jdk1.8.0_45/jre
export ANT_HOME=/opt/apache-ant-1.7.0
export JBOSS_HOME=/opt/jboss-eap-6.3

export PATH=$JAVA_HOME/bin:$JRE_HOME/bin:$PATH:$ANT_HOME/bin
export CLASSPATH=$CLASSPATH:.:$JAVA_HOME/lib:$JRE_HOME/lib
重新關機後,就可以生效。


(繼續閱讀...)

2010年7月29日 星期四

PHP 多檔案上傳範例 multiple file upload

From: Polin Wei

多檔上傳的程式,可以分成兩個部份來解釋:

  1. 在網頁 HTML 的呈現方面需要用 Ajax 來即時呈現即將上載的檔案有那些。

  2. 將這些上載的檔案記載在陣列 Array 中,並逐一的上載到伺服器。


  關於第一點,需要用到 Ajax 的技術,若對於 Ajax 不瞭解也沒有關係,我們可以使用一個免費的 JQuey 套件:Multiple File Upload Plugin (jQuery.MultiFile) ,套件可以從 http://www.fyneworks.com/jquery/multiple-file-upload 下載,或從或從 資訊空間 - 檔案下載 來取得。

  使用的方法很簡單,只要將兩個 javascript 檔: jquery.js 及 jquery.MultiFile.js 含入,在 form 中加入 <input type="file" name="my_files[]" class="multi" /> 即可。因為 jquery.MultiFile.js 會將要上載的檔案資料記錄在陣列中,所以要用 name="my_files[]"  來作資料的接收;而 class="multi" 是 jQuery 用來作多檔案上傳程式碼置換點的判斷,HTML 檔案的部份如下:


繼續詳細閱讀 Continue Reading...

2009年5月7日 星期四

[FCKeditor] 用 Java Taglib 使用 FCKeditor

From: Polin Wei

FCKeditor 是所見即所得(WYSIWYG)的線上編輯器, 支援多國語言, 多種瀏覽器支援, 可更換SKIN,還可以用JavaScript控制按鈕,功能十分多樣化,外掛的功能也是十分強大,支援瀏覽器管理檔案...等多樣化外掛。

支援語言: ASP.Net, ASP, ColdFusion, PHP, Java, Active-FoxPro, Lasso, Perl, Python
支援流覽器: IE, FireFox, Safari, Opera, Google Chrome, Camino
支援平台: MS Windows , MAC , Linux
版權: under the GPL, LGPL and MPL open source licenses

在 Java 的平台上有一個很好用的工具 Taglib , 可以讓你的 jsp 程式簡單化.配置如下

FCKeditor: FCKeditor_2.6.4.zip
FCKeditor.Java: fckeditor-java-2.4.1-bin.zip
FCKeditor.Java 文件參考: http://java.fckeditor.net/
SLF4j: slf4j-1.5.6.zip
Application Server: Tomcat 6.x.x

step01:
在 WebContent 目錄下建立一個目錄 fckeditor , 並將 FCKeditor_2.6.4.zip 解開的資料放在這個目錄下.

step02:
解開 fckeditor-java-2.4.1-bin.zip , 將 fckeditor-java-core-2.4.1.jar, 及 lib 目錄下的三個檔案 commons-fileupload-1.2.1.jar, commons-io-1.3.2.jar, slf4j-api-1.5.2.jar , 複製到 WEB-INF\lib

step03:
解開 slf4j-1.5.6.zip , 將slf4j-api-1.5.6.jar, slf4j-simple-1.5.6.jar 複製到 WEB-INF\lib

step04:
在 WEB-INF\web.xml 檔增加下列程式碼
<servlet>
 <servlet-name>Connector</servlet-name>
 <servlet-class>net.fckeditor.connector.ConnectorServlet</servlet-class>
 <load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Connector</servlet-name>
  <url-pattern> /fckeditor/editor/filemanager/connectors/*
  </url-pattern>
</servlet-mapping>


step05:
在 WEB-INF 目錄下增加一個檔案 FCKeditor.tld , 內容如下:
<?xml version="1.0" encoding="UTF-8"?>
<taglib 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-jsptaglibrary_2_0.xsd"
 version="2.0">
 <description>
  The FCKeditor Tag Library offers a very convenient way to create
  several FCKeditor instances with different configurations.
  Additionally, you can check for user-based capabilities.
 </description>
 <display-name>FCKeditor Tag Library</display-name>
 <tlib-version>2.4</tlib-version>
 <short-name>FCK</short-name>
 <uri>http://java.fckeditor.net</uri>
 <tag>
  <description>
   Creates a FCKeditor instance with the given parameters. Any
   parameter except instanceName which is empty or contains
   whitespaces only will be ignored.
  </description>
  <display-name>editor</display-name>
  <name>editor</name>
  <tag-class>net.fckeditor.tags.EditorTag</tag-class>
  <body-content>JSP</body-content>
  <attribute>
   <description>
    The unique instance name under which the editor can be
    retrieved through the API.
   </description>
   <name>instanceName</name>
   <required>true</required>
   <rtexprvalue>true</rtexprvalue>
   <type>java.lang.String</type>
  </attribute>
  <attribute>
   <description>
    Width of the FCKeditor instance in the browser window.
   </description>
   <name>width</name>
   <rtexprvalue>true</rtexprvalue>
   <type>java.lang.String</type>
  </attribute>
  <attribute>
   <description>
    Height of the FCKeditor instance in the browser window.
   </description>
   <name>height</name>
   <rtexprvalue>true</rtexprvalue>
   <type>java.lang.String</type>
  </attribute>
  <attribute>
   <description>
    The toolbar set which shall be displayed to the user.
   </description>
   <name>toolbarSet</name>
   <rtexprvalue>true</rtexprvalue>
   <type>java.lang.String</type>
  </attribute>
  <attribute>
   <description>
    The path/folder in which the editor is deployed under
    the given context. The context path will be attached
    automatically. (e.g. '/fckeditor')
   </description>
   <name>basePath</name>
   <rtexprvalue>true</rtexprvalue>
   <type>java.lang.String</type>
  </attribute>
  <attribute>
   <description>
    Passes any content to the FCKeditor document. Use the
    jsp:attribute tag for large inline content. \r, \n, and
    \t will be truncated.
   </description>
   <name>value</name>
   <rtexprvalue>true</rtexprvalue>
   <type>java.lang.String</type>
  </attribute>
  <example><![CDATA[
<FCK:editor instanceName="editorDefault" height="500px" />]]>
  </example>
 </tag>
 <tag>
  <description>
   Sets a config property of the editor to the supplied value.
   You may provide any attribute you want for the editor. Set
   at least one attribute per tag or several attributes with
   one tag. This tag can only be nested within an editor tag.
   For all configuration options click
   <![CDATA[<a href="http://docs.fckeditor.net/FCKeditor_2.x/Developers_Guide/Configuration/Configuration_Options">here</a>]]>.
  </description>
  <display-name>config</display-name>
  <name>config</name>
  <tag-class>net.fckeditor.tags.ConfigTag</tag-class>
  <body-content>empty</body-content>
  <dynamic-attributes>true</dynamic-attributes>
  <example>
   <![CDATA[
<FCK:config SkinPath="/skins/silver/" AutoDetectLanguage="true" />]]>
  </example>
 </tag>
 <tag>
  <description>
   Displays session-dependent and compatibility-related
   information. This tag is intended for developers only.
   Response messages cannot be localized, they are English
   only.
  </description>
  <display-name>check</display-name>
  <name>check</name>
  <tag-class>net.fckeditor.tags.CheckTag</tag-class>
  <body-content>empty</body-content>
  <attribute>
   <description>
    Provide the feature name you want to check. Valid
    features are [FileUpload, FileBrowsing,
    CompatibleBrowser]
   </description>
   <name>command</name>
   <required>true</required>
   <type>java.lang.String</type>
  </attribute>
  <example><![CDATA[
<FCK:check command="FileUpload" />
<FCK:check command="CompatibleBrowser" />]]>
  </example>
 </tag>
</taglib>


step06:
建立一個 fck.jsp 來測試, 程式碼如下:
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib uri="/WEB-INF/FCKeditor.tld" prefix="FCK"%>

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>

<form action="show.jsp" method="post" target="_blank">
<FCK:editor instanceName="fckEdit"  width="700" height="500"  toolbarSet="Default" />
<input type="submit" value="Submit">
</form>


</body>
</html>



成果如下圖:


fckeditor-java-2.4.1 的設定比較簡便, 就連上載檔案, 也只要在step04: 設定好 servlet : Connector 就可以了. 不需要太繁瑣. 不過若要上載檔案, 不要忘了要在 classpath 建立一個檔案 fckeditor.properties , 內容如下:
fckeditor.toolbarSet=Basic
connector.userActionImpl=net.fckeditor.requestcycle.impl.UserActionImpl
connector.userFilesPath=/userfiles
connector.resourceType.file.extensions.allowed=txt|doc
connector.resourceType.image.extensions.allowed=jpg|png


這樣才不會有問題. 參數說明:
connector.userFilesPath : 是伺服器上要存放檔案的地方.如 /userfiles
connector.resourceType.file.extensions.allowed : 可以限制上傳到/userfiles/file 目錄的附加檔名有那些
connector.resourceType.image.extensions.allowed: 可以限制上傳到/userfiles/image 目錄的附加檔名有那些

因為上載的檔案只能存在這個 application WEBcontent 的目錄內, 所以若將 java 打包成 war 檔在 JBoss 上使用, 則會有問題.

2009年4月2日 星期四

[JAVA] Tag Interface 參數及方法說明

From: Polin Wei

所有的標籤 Tag 處理類別均是執行 Tag, IterationTag 或 BodyTag 介面之一的 Java 類別 (class) . 因為 Java 並不支援多重繼承, 因此, 如果現有的類別 (class) 已繼承自某個基礎類別, 就無法使其繼承自必要的標籤 Tag 處理基礎類別了(好像有點饒舌). 但 JSP 提供另一個更好的解決方法, 它仍舊可以只繼承單一基礎類別, 不過這些類別可以執行多個選擇的介面.

執行此介面的類別可以在起始標籤 public int doStartTag() throws JspException 和結束標籤 public int doEndTag() throws JspException 中執行自訂作業, 但不能控制主體內容.

在 doStartTag() 所傳回的值有:
public final static int EVAL_BODY_INCLUDE : 通知伺服器將主體內容放在 out 的資料流中
public final static int SKIP_BODY : 通知伺服器不要處理任何的主體內容

在 doEndTag() 所傳回的值有:
public final static int EVAL_PAGE : 通知伺服器繼續評估網頁
public final static int SKIP_PAGE : 通知伺服器不要處理網頁的其餘部份

方法:
public int doStartTag() : 如果傳回 SKIP_BODY 則直接呼叫 doEndTag() ; 如果傳回 EVAL_BODY , 則將主體內容放在 out 資料流中.

public int doEndTag() : 之前已呼叫過 doStartTag() , 主體內容可能已經處理過, 也可能沒有處理過, 如果傳回 SKIP_PAGE , 此網頁就不再作任何評估, 就此結束; 如果傳回 EVAL_PAGE, 網頁就會繼續評估.

public abstract void setPageContext() : 設定目前的 PageContext , 並在伺服器呼叫 doStartTag() 之前.

public abstract javax.servlet.jsp.tagext.Tag getParent() : 取得最近的標籤處理常式, 並封裝此標籤處理常式, 如果找不到就傳回 null

public abstract void setParent() : 此方法設定父階標籤處理常式, 會由 getParent() 傳回, 在 doStartTag() 之前呼叫, 因此視需要存取父階的標籤處理常式

再次看 Tag 的程式運作的流程圖, 應該就比較瞭解了

2009年4月1日 星期三

[JAVA] Tag 自訂標籤第一支程式

From: Polin Wei

上一篇 [JAVA] Tag 自訂標籤簡介 大致介紹了 Tag 自訂標籤 的方便性, 及如何使用, 現在就來看如何撰寫 Tag 自訂標籤 及 如何在 JSP 網頁上, 使用自己撰寫的 Tag 標籤

Step1: 撰寫 Tag 的 Java 程式檔: jsDemoTag.java
package com.demos.tag;

import javax.servlet.jsp.JspException;
import javax.servlet.jsp.JspWriter;
import javax.servlet.jsp.tagext.BodyContent;
import javax.servlet.jsp.tagext.BodyTagSupport;

public class jsDemoTag extends BodyTagSupport {

    
    @Override
    public int doEndTag() throws JspException {
        // TODO Auto-generated method stub
        try {
            StringBuffer sb = new StringBuffer();
            // 利用 pageContext Object 取得 JSP 網頁輸出資料流 .getOut() , 才能將產生的 Java Script 寫到客戶端
            JspWriter out = pageContext.getOut();

            // 利用 BodyContent Objext 及 getBodyContent() 函式取得資料
            BodyContent bodyContent = getBodyContent();

            if( bodyContent!=null ){
                String bodyMessage = bodyContent.getString();
                sb.append("<script language=\"javascript\"> \n  \n");
                sb.append("alert('"+ bodyMessage.trim() +"');");
                sb.append("  \n</script> \n");
               
                // 將資料寫回客戶端
                out.write(sb.toString());              
            }
           
        } catch (Exception e) {
            // TODO: handle exception
            System.err.print(e);
        }
        return EVAL_PAGE;
    }   
}



Step2: 建立標籤程式庫描述元 demo.tld , 並放在 WEB-INF 目錄下
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE taglib PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.1//EN" "http://java.sun.com/dtd/web-jsptaglibrary_1_1.dtd" >
<taglib>
  <tlibversion>1.0</tlibversion>
  <jspversion>1.1</jspversion>
  <shortname>demo</shortname>  
  <info>Demo Customization Tag </info>
  <tag>
    <name>message</name>
    <tagclass>com.demos.tag.jsDemoTag</tagclass>
    <info>Display Alert Box</info>
  </tag>
</taglib>


tld檔中, 在<attribute> </attribute>中可設定 name, required, rtexprvalue 等三個屬性條件,<required>用來指定屬性是否一定要使用,若設定為true,則一定要使用指定的屬性,設定為false表示屬性為可選的(optional),<rtexprvalue>用來表示屬性指定時,是否可以使用表示式等動態屬性,例如 EL ${param.who}這樣的指定,如果設定為true表示可以,設定為false表示必須為靜態屬性。


Step3: 建立 JSP 網頁 HelloTag.jsp 來測試
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib prefix="uDemo"  uri="/WEB-INF/demo.tld"%>

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Demo Customization Tag Library</title>
</head>
<body>
<uDemo:message>Hello Tag !! This is first Tag Library</uDemo:message>
</body>
</html>

[JAVA] Tag 自訂標籤簡介

From: Polin Wei

自定標籤 Tag 的優點:
使用預先建立的 Tag 標籤可以減少 Java 程式碼在前端開發所需要的時間, 進而加速網站開發, 重覆使用自訂標籤是縮短時間的最大幕後功臣.

Tag 自定標籤只能經由 JSP 網頁來使用, Tag 標籤處理常式和 JSP 網頁是彼此緊密結合的, 因此, 您得以存取 PageContext 物件, 就可以存取目前包含在 JSP 網頁中的相同資料. 所以, Tag 標籤可以存取任何從 session 資料到 request 物件裡的變數. 不過, 從 PageContext 物件得到最重要的一件事是存取 JSP 網頁的 out 物件, 我們需要此物件才能將內容寫回 JSP 網頁的輸出資料流.

使用自定標籤 Tag 的方法

只要兩個簡單的步驟就能使用標籤程式庫

Step1: 匯入標籤程式庫
匯入標籤程式庫只需使用 taglib 指令, 如
<%@ taglib uri="/WEB-INF/struts-layout.tld" prefix="layout"%>
uri : 是識別標籤程式庫的唯一名稱, 用來指定標籤程式庫描述元(Tag Library Descriptor , TLD) 的位置. 標籤程式庫描述元(Tag Library Descriptor , TLD) 實際上是索引檔案, 告訴 JSP 容器 Context 每個標籤 Tag 處理常式所在位置與使用對象. 也就是說. TLD 是 JSP 應用程式裡定義標籤程式庫的地方.

Step2: 從標籤程式庫中呼叫自訂標籤
在 Step1 中定義請求呼叫此標籤程式庫的方法 prefix="layout" , 並從 layout 標籤程式庫中請求 html 自訂標籤的功能
<layout:html>

</layout:html>


撰寫 Tag 程式(class) 繼承 TagSupport 與 BodyTagSupport的區別:
撰寫 Tag 的程式( class ), 若選擇繼承TagSupport的類別,那您所能決定的,就是要不要顯示標籤之間的文字,但沒有辦法對這段文字作任何的處理,如果您要對本體文字作處理,可以繼承BodyTagSupport類別。

大體上, Tag 的程式運作的流程如下圖

2009年3月18日 星期三

[JAVA] Filtering 過濾器的使用

From: Polin Wei

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 中的 <filter> 定義中所指定的. 若無則回傳 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的參數
<filter>
    <filter-name>loggerFilter</filter-name>
    <filter-class>com.demos.filter.LoggerFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>loggerFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>


<filter-mapping> 的樣式可以對 URL 或 servlet 來作 Filter:

<url-pattern>/*</url-pattern>
<servlet-name>action</servlet-name>



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 也要相對的加入
<filter>
    <filter-name>Set Character Encoding</filter-name>
    <filter-class>
        com.gu.filters.SetCharacterEncodingFilter
    </filter-class>
    <init-param>
        <param-name>encoding</param-name>
        <param-value>utf-8</param-value>
    </init-param>
    <init-param>
        <param-name>ignore</param-name>
        <param-value>true</param-value>
    </init-param>
</filter>
<filter-mapping>
    <filter-name>Set Character Encoding</filter-name>
    <servlet-name>action</servlet-name>
</filter-mapping>

2009年3月6日 星期五

[Java] 建立由 LDAP AD 認證的機制

From: Polin Wei

環境:
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<String, String> env = new Hashtable<String, String>();
        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) {

                }
            }
        }
    }

2009年1月12日 星期一

[DataBase] PreparedStatement & Statement 的差異

From: Polin Wei

Java 程式語言在寫入資料庫有兩種方式 PreparedStatement 與 Statement , [Java] Date Type Write In DataBase 日期型態如何寫入資料庫 一文中有 PreparedStatement 的程式範例, 至於 Statement 的程式碼如下:

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

public void writeInDB(){
Connection conn = null;
String sql ;
Statement pstmt ;
ResultSet rs;
try {
    sql = "Select id,name FROM mydate where id='" + PolinWei + "'";
    stmt = conn.createStatement();
    rs = stmt.executeQuery(sql);
    if ( rs.next() ){
       name = rs.getString("NAME");
       System.out.println("name: " + name);           
    }
    rs.close();
    stmt.close();
} catch (Exception e) {
    System.err.println(e);
} finally {
    try {
    conn.close();
    } catch (Exception e) {
        e.printStackTrace();
    }
}

}


看似 Statement 比 PreparedStatement 的程式為簡單, 且程式碼較為精簡 , 但若這支程式的使用率很頻繁, 且 WHERE 條件中的值也每次都不一樣時, 建議應使用 PreparedStatement , 因為這會讓後端的資料庫在作 Parse 時, 負載會減輕很多.

附註: 若希望 ResultSet 可以上一筆, 下一筆的查詢. 則在宣告 Statement stmt 時要加入 ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY 這兩個參數, 如:

Statement stmt=conn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);

2009年1月8日 星期四

[Tomcat] apache-tomcat-6.x.zip 的起動方式

From: Polin Wei

Tomcat 在 Window 的平台可以不用安裝就可以起動執行. 從 http://tomcat.apache.org/index.html 下載 apache-tomcat-6.x.x.zip 的壓縮檔, 解開後執行 %CATALINA_HOME%\bin\startup.bat 卻沒啟動 ? 為何?

正確的步驟應如下:
1. 將 http://tomcat.apache.org/index.html 下載 apache-tomcat-6.x.x.zip 的壓縮檔解壓到 C:\AppServ\apache-tomcat-6.0.14
2. 在 %CATALINA_HOME%\bin 目錄新增一個檔案 project_start.bat 內容如下:

@echo off

set CATALINA_HOME=C:\AppServ\apache-tomcat-6.0.14
rem JAVA_HOME must point to a full JSDK, not just a JRE
set JAVA_HOME=D:\Progs\jdk1.6.0_07

rem Quite possibly gratuitous
set PATH=%JAVA_HOME%\jre\bin;%JAVA_HOME%\bin;%PATH%

rem Adjust the following heap settings as necessary
set JAVA_OPTS=-server -Xms256M -Xmx256M -Djava.awt.headless=true -Dwt.context.defaultLocalResourcesOnly=true


rem Enable local JMX connections in Java 5
set JAVA_OPTS=%JAVA_OPTS% -Dcom.sun.management.jmxremote

rem Un-rem next line to enable debugger attaching to this instance of Tomcat
rem set JAVA_OPTS=%JAVA_OPTS% -Xnoagent -Xdebug -Xrunjdwp:transport=dt_shmem,address=tomcat,server=y,suspend=n

"%CATALINA_HOME%\bin\startup.bat"


3. 編輯 %CATALINA_HOME%\conf\server.xml , 在設定檔區間要寫入您專案的名字
<Host appBase="webapps" autoDeploy="true" name="localhost" unpackWARs="true" xmlNamespaceAware="false" xmlValidation="false">
   [ JAVA 的專案名稱要放在這裡 ]
</Host>


如下:
<Host appBase="webapps" autoDeploy="true" name="localhost" unpackWARs="true" xmlNamespaceAware="false" xmlValidation="false">
    <Context docBase="D:/myProj" path="/myProj" reloadable="true" crossContext="true" source="org.eclipse.jst.j2ee.server:myProj"/>
</Host>


這樣就可以執行了

2009年1月7日 星期三

[Java] Date Type Write In DataBase 日期型態如何寫入資料庫

From: Polin Wei

完整的程式如下:

import java.util.Date;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.text.SimpleDateFormat;
import java.util.TimeZone;

public void DateWriteInDB(){
Connection conn = null;
String sql ;
PreparedStatement pstmt ;
ResultSet rs;
try {
java.util.Date now = new java.util.Date(); //取得現在時間
SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
sf.setTimeZone(TimeZone.getTimeZone("GMT")); // 設定時區為格林威治 GMT 時區
String sGMT = sf.format(now);
java.sql.Timestamp createDate = Timestamp.valueOf(sGMT); // 要轉換成 java.sql.Date 的物件才可以寫入資料庫

sql = "INSERT INTO mydate (id, create_date) VALUES (?,?)";
pstmt = conn.prepareStatement(sql);
pstmt.setString(1, "01");
pstmt.setTimestamp(2, createDate);
pstmt.execute();
} catch (Exception e) {
System.err.println(e);
} finally {
try {
conn.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}


PS: 日期型態要寫入資料庫, 需要用 java.sql.PreparedStatement 物件來寫入

2008年11月14日 星期五

[JNDI] Java + Tomcat + MySQL 的連結設定

From: Polin Wei

環境:
Web Server: apache-tomcat-6.0.14
DB Version: MySQL 5.0.45
DB : test
Table: users(username varchar(30),password varchar(30))
JDBC Driver: mysql-connector-java-5.1.7-bin.jar
JAVA: jdk1.6.0_07


在Web步驟如下:
Step 1: Copy MySQL Connector/J 的 JAR 檔
mysql-connector-java-5.1.7-bin.jar 複製到 $TOMCAT_HOME/lib

Step 2:在 $TOMCAT_HOME/conf/server.xml 的 <Context></Context> 中加入下列的參數
<Resource name="jdbc/MySQLDS01" auth="Container" type="javax.sql.DataSource" factory="org.apache.tomcat.dbcp.dbcp.BasicDataSourceFactory" driverClassName="com.mysql.jdbc.Driver" url="jdbc:mysql://localhost:3306/test" username="username" password="password" maxActive="20" maxIdle="10" maxWait="-1" />




Step 3: 撰寫一個網頁 MySQLConnTest.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@page import="com.mysql.*,java.util.*,javax.naming.*,java.sql.*,javax.sql.*" %>


<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<%    
    Context ctx = new InitialContext();     
    String strLookup = "java:comp/env/jdbc/MySQLDS01";
    DataSource ds =(DataSource) ctx.lookup(strLookup);
    Connection con = ds.getConnection();
    Statement smt = con.createStatement();
    String sql = "";
    ResultSet rs = null;   
     
    sql = "SELECT * FROM users";
    rs = smt.executeQuery(sql);
    while(rs.next())
    {
         out.println(rs.getString(1));
         out.println(rs.getString(2));        
    }


%>


</body>
</html>




這樣就可以利用 JNDI 的方式連到 MySQL , 並在網頁中顯示資料庫test中表格users裡的資料.

若是純以 Java Code 來執行連結MySQL , 則程式碼如下:

package com.demos;


import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;


public class MySQLConnTest {


 /**
  * @param args
  */
 public static void main(String[] args) {
  // TODO Auto-generated method stub
  Connection conn = null;
  String Server_IP = "127.0.0.1";


  try {
   Class.forName("com.mysql.jdbc.Driver");
   String sql = "";
   conn = DriverManager.getConnection("jdbc:mysql://" + Server_IP
     + ":3306/test", "username", "password");
   sql = "select * from users";
   // Statement stmt =
   // conn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,
   // ResultSet.CONCUR_READ_ONLY);
   Statement stmt = conn.createStatement();
   ResultSet rs = stmt.executeQuery(sql);
   if (rs.next()) {
    System.out.println(rs.getString("userName"));
    System.out.println(rs.getString("password"));
   } else {
    System.out.print("Cound not find data in test of MySQL");
   }
  } catch (Exception e) {
   // TODO: handle exception
   e.printStackTrace();
   try {
    conn.rollback();
   } catch (SQLException e1) {
    e1.printStackTrace();
   }
  } finally {
   try {
    if (conn != null && !conn.isClosed()) {
     conn.close();
    }
   } catch (Exception e) {
    e.printStackTrace();
   }
  }


 }


}



2008年11月4日 星期二

[Java] quartz 工作定時排程器

From: Polin Wei

  在一個應用系統中常要定時去執行某些程式, 例如: 同步異質平台的資料, 或是定時發信件; Java是一種跨平台(Window/Linux)的程式語言, 雖然在 Window 平台可以用 AT 指令來作排程, 在 Linux 可以用 crontab 來排程, 但總是無法與系統作密切的結合.

  quartz是個不錯的選擇, 它一樣可以跨異質平台作業, 而且與 Java 的結合也很密切, 只要在Java程式段有
public void execute(JobExecutionContext context)
throws JobExecutionException {....}
quartz作接口即可
, 下面我們來看一下如何實作它.總共有幾個步驟, 就可以讓它順利執行.

設定

1. 下載 quartz 所需的 JAR 檔

2. WEB-INF/web.xml 中加入quartz的 servlet
<servlet>
<servlet-name>QuartzInitializer</servlet-name>
<servlet-class>
org.quartz.ee.servlet.QuartzInitializerServlet
</servlet-class>
<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>
<init-param>
<param-name>start-scheduler-on-load</param-name>
<param-value>true</param-value>
</init-param>
<load-on-startup>0</load-on-startup>
</servlet>


3. 建立 quartz的設定檔
  在 Java Resource 的目錄建立二個檔案 quartz.properties 及 jobSchedule.xml(此檔的檔名可以自定), 檔案內容如下:

quartz.properties 檔
org.quartz.jobStore.class=org.quartz.simpl.RAMJobStore
org.quartz.jobStore.misfireThreshold=60000
org.quartz.plugin.jobInitializer.class=org.quartz.plugins.xml.JobInitializationPlugin
org.quartz.plugin.jobInitializer.failOnFileNotFound=true
org.quartz.plugin.jobInitializer.fileName=/jobSchedule.xml => 這個檔案是定義 JOB 的排程用
org.quartz.plugin.jobInitializer.overWriteExistingJobs=true
org.quartz.plugin.jobInitializer.validating=false
org.quartz.plugin.jobInitializer.validatingSchema=true
org.quartz.plugin.triggHistory.class=org.quartz.plugins.history.LoggingTriggerHistoryPlugin
org.quartz.plugin.triggHistory.triggerCompleteMessage=Trigger {1}.{0} completed firing job {6}.{5} at {4, date, HH\:mm\:ss MM/dd/yyyy} with resulting trigger instruction code\: {9}
org.quartz.plugin.triggHistory.triggerFiredMessage=Trigger {1}.{0} fired job {6}.{5} at\: {4, date, HH\:mm\:ss MM/dd/yyyy}
org.quartz.scheduler.instanceId=1
org.quartz.scheduler.instanceName=sched1
org.quartz.threadPool.class=org.quartz.simpl.SimpleThreadPool
org.quartz.threadPool.threadCount=100
org.quartz.threadPool.threadPriority=5


jobSchedule.xml 檔
<?xml version="1.0" encoding="UTF-8"?>
<quartz>
<job>
<job-detail>
<name>job_mail_demo</name> ==> 定義工作的名字: job_mail_demo
<group>DEFAULT</group>
<description>job_mail_demo</description>
<job-class>com.demos.job_mail_demo</job-class> ==> 定義排程器要執行那一個 Java 程式
<job-data-map allows-transient-data="true">
<entry>
<key>name</key>
<value>job_mail_demo</value>
</entry>
</job-data-map>
</job-detail>
<trigger>
<cron>
<name>Cron_job_mail</name> ==> 定義排程器的名字: Cron_job_mail
<group>DEFAULT</group>
<job-name>job_mail_demo</job-name> ==> 定義排程器[Cron_job_mail]內要執行的工作[job_mail_demo]
<job-group>DEFALUT</job-group>
<cron-expression>0 0/5 * * * ?</cron-expression> ==> 每5分鐘執行工作排程 job_mail_demo 一次
</cron>
</trigger>
</job>
</quartz>
<!-- Cron 的小小說明表示方式意義
"0 0 12 * * ?" Fire at 12pm (noon) every day
"0 15 10 ? * *" Fire at 10:15am every day
"0 15 10 * * ?" Fire at 10:15am every day
"0 15 10 * * ? *" Fire at 10:15am every day
"0 15 10 * * ? 2005" Fire at 10:15am every day during the year 2005
"0 * 14 * * ?" Fire every minute starting at 2pm and ending at 2:59pm, every day
"0 0/5 14 * * ?" Fire every 5 minutes starting at 2pm and ending at 2:55pm, every day
"0 0/5 14,18 * * ?" Fire every 5 minutes starting at 2pm and ending at 2:55pm, AND fire every 5 minutes starting at 6pm and ending at 6:55pm, every day
"0 0-5 14 * * ?" Fire every minute starting at 2pm and ending at 2:05pm, every day
"0 10,44 14 ? 3 WED" Fire at 2:10pm and at 2:44pm every Wednesday in the month of March.
"0 15 10 ? * MON-FRI" Fire at 10:15am every Monday, Tuesday, Wednesday, Thursday and Friday
"0 15 10 15 * ?" Fire at 10:15am on the 15th day of every month
"0 15 10 L * ?" Fire at 10:15am on the last day of every month
"0 15 10 ? * 6L" Fire at 10:15am on the last Friday of every month
"0 15 10 ? * 6L" Fire at 10:15am on the last Friday of every month
"0 15 10 ? * 6L 2002-2005" Fire at 10:15am on every last friday of every month during the years 2002, 2003, 2004 and 2005
"0 15 10 ? * 6#3" Fire at 10:15am on the third Friday of every month
-->


4. Java 程式段 job_mail_demo.java
package com.demos;

import java.sql.Connection;
import java.util.Date;
import org.apache.log4j.Logger;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import com.gu.utils.BA_TOOLS;

public class job_mail_demo implements Job{
static Logger loger = Logger.getLogger(job_mail_demo.class.getName());

public void execute(JobExecutionContext context)
throws JobExecutionException {
String name = context.getJobDetail().getJobDataMap().getString("name");

System.out.println("run " + name + " at " + new java.util.Date());
loger.warn("Executing job: executing at " + new Date());

try {
BA_TOOLS tools = BA_TOOLS.getInstance();
tools.sendmail("localhost", "polin.wei@mail.com", "polin.wei@mail.com", "Schedule Job Demo",
"Schedule Job Demo");

System.out.println("END " + name + " at " + new java.util.Date());
loger.warn("job END: END at " + new Date());
} catch (Exception e) {
e.printStackTrace();
}

}

}



  系統執行時, quartz 就會依照排程定時去發 mail , 因為在 Java 程式有設 log4j 來作偵測 quartz 是否有定時執行, 所以可以看到 Java Console 的顯示如下:

[ERROR] 04 十一月 06:10:05.456 下午 Thread-8 [com.gu.utils.MailThread-run]
polin.wei@xxx.com郵件送出失敗!

2008/11/4 下午 06:15:00 org.quartz.plugins.history.LoggingTriggerHistoryPlugin triggerComplete
資訊: Trigger DEFAULT.Cron_job_mail completed firing job DEFAULT.job_mail_demo at 18:15:00 11/04/2008 with resulting trigger instruction code: DO NOTHING
[DEBUG] 04 十一月 06:15:05.679 下午 Thread-8 [com.gu.utils.MailThread-run]
polin.wei@mail.com郵件已送出!


2008年10月23日 星期四

[Java] log4j 的說明及實作

From: Polin Wei

簡介 Introduction
  Log4j 是一套開放源碼的工具,方便編程人員在程式中加入 log 機制,並輸出到各種目標上。Log4j 能夠透過外部的設定檔(properites 或 XML)進行設定。Log4j 能夠將 log message 寫到 console, 檔案,串流,TCP 協定的伺服器, Unix Syslog daemon 等。詳細的說明可以參考官方網 log4j

組成 Log4j 的三大元件(Loggers, Appenders and Layouts) :
  • Logger - 由編程人員在程式中使用,進行 logging 的元件
  • Appender - 負責將 log message 輸出到各種裝置上
  • Layout - 決定 log message 的格式
Loggers:
  Logger 可以被指派等級。能夠指派給 Logger 的等級有 : DEBUG, INFO, WARN, ERROR, FATAL 5 種,定義在 org.apache.log4j.Level 類別中。這 5 種等級的高低順序為 FATAL > ERROR > WARN > DEBUG > INFO 。

  Logger 的等級決定它產生 log message 的數量 : Logger 只寫"出高於或等於本身等級"的 log message。例如某個 Logger 的等級被設定為 WARN,那麼它只會寫出等級為 WARN, ERROR, FATAL 的 log message,對於 DEBUG, INFO 的 log message 則不予理會。

  若是 Logger 的等級未被設定,則會自動使用 parent(上一層) 的等級。如果程式中所有的 Logger 都未設定等級,則由 root logger 決定。

  Logger 之間以名稱區分,所以在程式中任何地方,呼叫 Logger.getLogger(),並傳入同一個 Logger 名稱,則會得到同一個 Logger 的 reference。

  Logger 之間以名稱區分出階層。即使父階層在程式中出現的時機比子階層晚,例如 "com.foo" logger 比 "com.foo.bar" 被取得的時間來得晚,"com.foo" 仍然是 "com.foo.bar" 的父階層(會影響到子階層 logger 未被定義的屬性, log 等級, appender, layout )。

Appenders:
  透過 Appender, Logger 能夠將 log message 輸出到指定的裝置上。一個 Logger 能夠擁有多個 Appender,所以 Logger 能夠同時將 log message 輸出到多個個裝置上。

  Appender 的設定亦會反映在 Logger 的階層中。當 Logger 輸出一筆 log message 時,父階層的 Appender 和自己的 Appender(如果有的話)都會記錄到這筆 log message;

  例如 "com.foo" Logger 有一個 Appender 將 log message 輸出到 console,而 "com.foo.bar" 有一個 Appender 將 log message 輸出到檔案;當 "com.foo.bar" Logger 輸出一筆 log message 時, console 和檔案都會出現這筆 log message。

  而最簡單的例子,就是當 root logger 擁有一個輸出到 console 的 Appender 時,則程式中所有的 logger 所產生的 log message 都會輸出到 console。唯一個例外的情況,就是當某個 logger 將自己的 additivity 屬性設為 false(Logger.setAdditivity(false)),則此 logger 與隸屬於它的子 logger 都不會將 log message 寫到 console。

Layouts:
  可以透過 Layout 的配置,自由改變 Logger 寫出 log message 的格式。例如,為 Logger 加入一個 conversion pattern 為 "%r [%t] %-5p %c - %m%n" 的 PatternLayout,則輸出的 log message 就可能會像下列這樣:

176 [main] INFO org.foo.Bar - Located nearest gas station.

PatternLayout 的 格式字元列表如下:

# %c 輸出日誌訊息所屬的類別的全名
# %d 輸出日誌時間點的日期或時間,指定格式的方式:%d{yyy-MM-dd HH:mm:ss }。
# %l 輸出日誌事件的發生位置,即輸出日誌訊息的語句處於它所在的類別的第幾行。
# %m 輸出訊息,如log(message)中的message。
# %n 輸出一個列尾符號。
# %p 輸出優先階層,即DEBUG,INFO,WARN,ERROR,FATAL。如果是調用debug()輸出的,則為DEBUG,依此類推。
# %r 輸出自應用啟動到輸出該日誌訊息所耗費的毫秒數。
# %t 輸出產生該日誌事件的線程名。
# %r 輸出自應用啟動到輸出該日誌訊息所耗費的毫秒數。
# %f 輸出日誌訊息所屬的類別的類別名。

Layout 亦會反映在 Logger 的階層上。


實作:

1. 修改 log4j.xml 檔
  在JBOSS(version:4.0.3SP1) 上的 log4j.xml 實作,可以分兩個層次來看:
  • 一是修改 Server 端的 log4j.xml ,檔案在:$JBOSS_HOME/server/default/conf/log4j.xml
  • 一是修改每個Prjoject中的 $Java Resource/src 程式原始檔目錄下的 log4j.xml
這兩個檔案內容大致相同,差異只在 Project 端的 logger 參數在 Server 端要改成 category

Server 端的 log4j.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">

<!-- ============================================================ -->
<!--  Log4j Configuration -->
<!-- ============================================================ -->


<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/" debug="false">

   <!-- ======================== -->
   <!-- Preserve messages in a local file -->
   <!-- ======================== -->

   <!-- A time/date based rolling appender 定義 log message 輸出FILE檔案 -->
   <appender name="FILE" class="org.jboss.logging.appender.DailyRollingFileAppender">
      <errorHandler class="org.jboss.logging.util.OnlyOnceErrorHandler"/>
      <param name="File" value="${jboss.server.home.dir}/log/server.log"/>
      <param name="Append" value="false"/>

      <!-- Rollover at midnight each day -->
      <param name="DatePattern" value="'.'yyyy-MM-dd"/>

      <!-- 定義 log message 的格式 -->
      <layout class="org.apache.log4j.PatternLayout">
         <!-- The default pattern: Date Priority [Category] Message\n -->
         <param name="ConversionPattern" value="%d %-5p [%c] %m%n"/>

      </layout>
   </appender>


   <!-- ===================================================== -->
   <!-- Append messages to the console 定義 log message 輸出 Console -->
   <!-- ===================================================== -->

   <appender name="CONSOLE" class="org.apache.log4j.ConsoleAppender">
      <errorHandler class="org.jboss.logging.util.OnlyOnceErrorHandler"/>
      <param name="Target" value="System.out"/>
      <param name="Threshold" value="INFO"/>

      <!-- 定義 log message 的格式 -->
      <layout class="org.apache.log4j.PatternLayout">
         <!-- The default pattern: Date Priority [Category] Message\n -->
         <param name="ConversionPattern" value="%d{ABSOLUTE} %-5p [%c{1}] %m%n"/>
      </layout>
   </appender>

   
   <!-- ========================================= -->
   <!-- Limit categories 對 class: com.demos 作偵錯觀察 -->
   <!-- ========================================= -->
   <category name="com.demos">
      <priority value="DEBUG"/>
   </category>

   <!-- ============================ -->
   <!-- Setup the Root category 設定 log 要在那裡產生 -->
   <!-- ============================ -->

   <root>
      <appender-ref ref="CONSOLE"/>
      <appender-ref ref="FILE"/>
   </root>

</log4j:configuration>




Project 端的 log4j.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">

   <!-- ===================================================== -->
   <!-- Append messages to the console 定義 log message 輸出至 Console 及 log 內容格式 -->
   <!-- ===================================================== -->
    <appender name="default" class="org.apache.log4j.ConsoleAppender">
        <param name="target" value="System.out" />
        <layout class="org.apache.log4j.PatternLayout">
            <param name="ConversionPattern"
                value="[%p] %d{dd MMM hh:mm:ss.SSS aa} %t [%C-%M]%n%m%n%n" />
        </layout>
    </appender>

    <!-- 設定要偵錯的 calss: com.demos 及 log 要輸出到那一個裝置-->
    <logger name="com.demos">
        <level value="debug" />
        <appender-ref ref="default" />
    </logger>

</log4j:configuration>


2. 在 java 程式 com.demos.LookupFormF.java 中放入偵錯點

package com.demos;

import javax.servlet.http.HttpServletRequest;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionMapping;
import org.apache.log4j.Logger;

public class LookupFormF extends ActionForm{

    static Logger loger = Logger.getLogger(LookupFormF.class.getName());
    private String symbol = null;
   
    public String getSymbol() {
        return (symbol);
    }
   
    public void setSymbol(String symbol) {
        this.symbol = symbol;
        loger.debug(symbol);
    }
}



3. 成果如下

16:54:23,733 INFO  [STDOUT] [DEBUG] 24 十月 04:54:23.733 下午 http-0.0.0.0-8043-
1 [com.demos.LookupFormF-setSymbol]
polinwei


2008年8月5日 星期二

[文章] Java Script 建立物件的方法

From: Polin Wei

方法一是:

  • var MyObject = function(){
  • /*Your Code Here*/
  • };


方法二是:

  • var MyObject = function(){
  • return{
  • /*Your Code Here*/
  • }
  • }();

範例: 建立一個 MyObject

MyObject = function() {
// private variables : 私有屬性或稱為區域變數
// private functions : 私有方法或稱為區域方法
// public space
return {
// public properties, e.g. strings to translate : 公有屬性或稱為公開變數

// public methods : 公有方法或稱為公開方法
init: function() {
alert('Application successfully initialized');
}
};
}();
實例如下:

  • MyObject = function() {
  • var myFirstName='WEI'; //私有屬性或稱為區域變數
  • var myLastName='Polin' ;
  • function getFirstName(){
  • alert(myFirstName);
  • }
  • function getLastName(){
  • alert(myLastName);
  • }
  • return {
  • NickName1: 'Super WEI', // public properties 公有屬性或稱為公開變數
  • NickName2: 'Good Luck',
  • init: function() {
  • alert(this.NickName1); //在Public zone裡面的需要使用this.xxxx來存取變數
  • alert(myFirstName); //在Public zone裡面的直接使用 xxx來存取 private zone裡面的變數
  • }, // end of init
  • other : function(){
  • alert(this.NickName2); //在Public zone裡面的需要使用this.xxxx來存取變數
  • alert(myLastName); //在Public zone裡面的直接使用 xxx來存取 private zone裡面的變數
  • } //注意結尾的,需要去除不然龜毛的IE會拒絕執行 end of other
  • }; // end of return
  • }(); // end of MyObject


有幾點重點要注意


第一個是變數的宣告方式:
Private zone的變數使用分號(;)隔開舉例如下:

  • var 變數1;
  • var 變數2;
但是在Public zone裡面的變數要使用逗號(,)隔開(註:其實這是JSON寫法的變型)舉例如下:

  • 變數1:變數1的值,
  • 變數2:變數2的值 //注意結尾的逗點在IE無法通過檢查


第二個是function(或稱方法)的宣告方式:
Private zone的使用方法如下:

  • function fun1(){
  • /*Your code HERE*/
  • };
  • function fun2(){
  • /*Your code HERE*/
  • };

在但是在Public zone的使用方法如下,(註:還這是JSON寫法的變型):

  • fun1: function() {

  • /*Your code HERE*/
  • },
  • fun2: function() {

  • /*Your code HERE*/
  • }


2008年7月29日 星期二

[文章] 初談 jQuery

From: Polin Wei

  這幾天在流灠有關於 Blogger 的網站, 總是有人談到 jQuery ,雖然本身在工作上是使用 ExtJS 2.1作為企業內的開發,但底層仍是 jQuery , 那到底什麼是 jQuery 呢? 它有什麼媚力呢? 若你有到 jQuery 的網站看的話, 就可以知道, 它開宗明義就有說明:

jQuery The Write Less, Do More !! jQuery is a new type of JavaScript library.
  jQuery is a fast, concise, JavaScript Library that simplifies how you traverse HTML documents, handle events, perform animations, and add Ajax interactions to your web pages. jQuery is designed to change the way that you write JavaScript.

意思就是說:
jQuery 是一套 JavaScript 的 Library
  jQuery 主要是用在 HTML 上 DOM 文件的操作,它可以快速且簡單的「選取元素(Element)」並且在這 DOM 的元素上「做一些事情」,在快速選取元素上可以讓你一次選取單一或多個的元素,然後你可以將這些被選取的元素做一些改變,例如隱藏、顯示...等等。此外 jQuery 的核心程式還加強了非同步傳輸(AJAX)以及事件(Event)的功能,讓你更容易操作遠端文件及事件。

  以下是一個完整的HTML實例,您可以Copy/Paste去跑看看,讓您更能瞭解 jQuery 的威力,至於所需要的 jQuery 可以到 jQuery 去下載,目前最新版為 1.2.6 :


<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <title>jQuery 1.2.6 Demo</title>
        <script type="text/javascript" src='jQuery-1.2.6.js'>  => 載入 jQuery 的 Java Script Library
        </script>
        <style type="text/css">
            .changeStyle {
                background-color: blue;
                color: #FFFFFF;
            }
           
            .content1 {
                background-color: red;
            }
           
        </style>
        <script type="text/javascript">
            /**
             *  jQuery 基本函數練習
             */
   
           // 函數說明: $ 是 jQuery 的物件,使用 $("div") 就是用 jQuery 來選取元素,這個範例可以選取文件內所有的 <div> 元素,
           // 後面接著的 .addClass("changeStyle") 就是將所有的 div 都加上 changeStyle 的 Style 的 class

            function fDiv(){
                $("div").addClass("changeStyle");
            }
   
    // 函數說明: 選取 id 為 first 的元素都加上 changeStyle 的 Style 的 class      
            function fDivFirst(){
                $("div#first").addClass("changeStyle");
            }
           
   // 函數說明: 選取 body 的元素都加上 changeStyle 的 Style 的 class
            function fBody(){
                $("body").addClass("changeStyle");
            }
           
   // 函數說明: 選取 h2  的元素都加上 changeStyle 的 Style 的 class
            function fHeader(){
                $("h2").addClass("changeStyle");
            }
   
            // 函數說明: 選取 class 為 content1 的 <div> 所包住的所有下層的 <p>
            function fContent1P(){
                $("div.content1 p").addClass("changeStyle");
            }
           
   // 函數說明: 選取 body 的元素, 並移除  changeStyle 的 Style 的 class
            function fRemoveBodyClass(){
                $("body").removeClass("changeStyle");
            }
           
   // 函數說明: 選取所有 div 的元素, 並移除  changeStyle 的 Style 的 class
            function fRemoveDivClass(){
                $("div").removeClass("changeStyle");
            }
        </script>
    </head>
    <body>
     <!-- 以下 <button ...> </button...> 作為事件觸發時, 所要作的事項 -->
        <button onclick="fDiv()"> 選取所有  div 的 selector </button>
        <button onclick="fDivFirst()"> 選取 div id 為 first </button>
        <button onclick="fHeader()"> 選取 h2 的 Header </button>
        <button onclick="fContent1P()"> 選取content1 的 Paragraph </button>
        <button onclick="fBody()"> Change Body Background Color </button>
        <button onclick="fRemoveBodyClass()"> Remove Body Class </button>
        <button onclick="fRemoveDivClass()"> Remove Div Class </button> <br>
  
  <!-- 以下為 HTML 的本體  -->
        <h2>Header H2</h2> <br>
        <div id="first">
            Hello World !! Polin Wei 這是第一個 div id = first
            <div class="content1">
                <p>
                    jQuery 是一個 Java Script Liberary
                </p>
            </div>
        </div>
        <h3>Header H3</h3>
        <br>
        <div id="second">
            Why jQuery? 這是第二個 div id = second
        </div>
        <div id="content2">
            <p>
                jQuery 主要是用在 HTML 上 DOM 文件的操作,它可以快速且簡單的「選取元素(Element)」並且在這 DOM 的元素上「做一些事情」,在快速選取元素上可以讓你一次選取單一或多個的元素,然後你可以將這些被選取的元素做一些改變,例如隱藏、顯示...等等。此外 jQuery 的核心程式還加強了非同步傳輸(AJAX)以及事件(Event)的功能,讓你更容易操作遠端文件及事件。
            </p>
        </div>
    </body>
</html>




2008年7月17日 星期四

[教學] Eclipse 與 Apache Tomcat 的整合開環境

來源:Polin Wei



環境:

OS : WinXP-SP3

Apache Tomcat : Apache-Tomcat-6.0.14 下載: http://tomcat.apache.org/
解壓在 C:\AppServ\apache-tomcat-6.0.14

Eclipse IDE : Ganymede 下載: http://www.eclipse.org/downloads/index.php

Java : jdk1.5.0_12 下載: http://java.sun.com/



  基本的環境變數,請看 [教學]Eclipse 與 Subversion 的整合運作 這篇介紹,接下來我們來看看在 Eclipse IDE 環境要如何設定.


##CONTINUE##

  在 Eclipse -> Preferences 中選擇 Server -> Runtime Environments


  按下 Add 增加 Apache 伺服器中的 Apache Tomcat v6.0


  若你的環境變數有事先設好,那下面的值應該是自動帶出來的,若沒有則手動選擇 Tomcat 安裝的路徑

  按下 Finishe 後,下方的 Servers 頁次應該會有 "Apache Tomcat v6.0.14 at localhost" ,在右邊則會有多一個 Servers 的目錄,然後可以按下滑鼠右鍵,選 "Add and Remove Projects"


  將你要 Publish 的專案加入進來這個 Local 的 Apache Tomcat 伺服器內即可,這樣你的專案就可以從流灠器 ( IE, FireFox ) 中流灠了.



WordPress 架站必備外掛