Home

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月31日 星期五

麥當勞培根季<<田園培根雙牛堡>>美味推薦


From: Polin Wei

From: Polin Wei 麥當勞培根季 意想不到的美味推薦


  芭啦芭芭芭...I'm lovin' it ! 麥當勞推出新口味 "田園培根雙牛堡" 。今天一下班就帶著小崴崴往麥當勞跑...才一進門就看到它各式各樣大小的廣告。


 看來這一次麥當勞是下重本來推銷這款新口味"田園培根雙牛堡" ,今天沒來好好品嚐它一下,怎麼對得起我的胃呢? 因為太餓了,一下子就點了一堆的食物,滿滿的一盤子,真是令人食指大動...

  別急...別急...照相留記念後再享用嘛!!

 "田園培根雙牛堡" ...那兩片培根...爽口的大黃瓜...雙份的澳洲牛肉...再淋上特製的煙燻培根醬,煙燻的味道...微酸大黃瓜的口感...紮實的牛肉...濃郁的吉事片...這些 MIX 在一起,讓那味道變得完全不一樣,超讚!! 真是太超過了...真是太超值了啦!!



  瞧我們滿足的樣子...時間就應該浪費在美好的食物上...多了兩片...味道變得更美味,快來嚐嚐就知道它的威力了...再來給它個特寫當作 Ending...
更多都在 http://www.mcdonalds.com.tw/Campaign_2008_Bacon/index.html

[Hyperion] Interactive Reporting 資料分析與報表產生的利器

From: Polin Wei

  Hyperion Interactive Reporting 是 Oracle BI (Business Intelligence Suite Enterprise Edition Plus)系統中的模組之一,它可以輕鬆的幫你製作 Report, Pivot, Chart, Dashboard, 若只想單純查詢資料時, 也可只用它的 Query 產生的 Results就可以了. 不需要下任何的 SQL 語法.

  Hyperion Interactive Reporting 有 Server & Client 的版本,今天以 Client版本來作示範.所需要的安裝程式可以上 Oracle 的網站抓.

實作:
  新建立一個資料庫的連結 File->New ,並將此連結檔名存成 ODBCDemo.oce
  • 選擇 ODBC 連結

  • User Name :空白
  • Password: 空白
  • Host: Hyperion Client Sample


  再依下圖將所需要的 table (Periods Days, Sales Fact, Products, Regions, Stores)拉進來, 將要查的欄位放在 Request 裡.



再按 Process ,就可以自動產生 Results值了




對於製作報表也輕鬆易舉

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年10月22日 星期三

[文章]老婆小崴崴,是我信仰的原創


From: Polin Wei

老婆小崴崴,是我信仰的原創


  人生三大喜事: 他鄉遇故知、金榜題名時、洞房花燭夜。老婆「小崴崴」就佔了這三大喜事之一,為了記錄老婆「小崴崴」與我生活中,柴米油盬醬醋茶的甘苦,我們用部落格記下這一切平凡卻不單調的家庭生活...;等時光飛逝 ,雙鬢泛白時,這將成為珍貴的資產供我們回憶。



  家是永遠的避風港,因為有了老婆「小崴崴」後,她變的更溫馨了,她給我安全、舒適、完全放鬆且毫無拘束的自在,「老婆小崴崴,是我信仰的原創」這句話真是貼切的表達了一切。



  adidas 也提供您一個安全、舒適、完全放鬆且毫無拘束...穿的自在。

2008年10月16日 星期四

[Google Translate] 讓你的網頁可以翻譯成多國語言

From: Polin Wei

  您的網誌內容希望能翻成各國語言,讓每個國家的人都看得懂嗎?就像下面 "我與小崴崴工作日記" 日文版一樣。

  

  而且當你的滑鼠移到句子段落的上方時,它還能用浮動視窗將原來的本文顯示出來。 該如何作呢?其時很簡單,只要一個步驟就可以。

  連結到 Google Translated : http://translate.google.com/translate_tools 再將所需的 Java Script 放在您的網頁上就可以了。




Google Translated Java Script Code


<script src="http://www.gmodules.com/ig/ifr?url=http://www.google.com/ig/modules/translatemypage.xml&up_source_language=zh-TW&synd=open&w=160&h=60&title=&lang=en&country=ALL&border=%23ffffff%7C3px%2C1px+solid+%23999999&output=js"></script>



韓國版



日本版
  

2008年10月14日 星期二

巴布(Buboo) 心情隨手貼

From: Polin Wei

  寫網誌...文筆沒有那麼豐富, 也沒有那麼多時間; 有時只是想隨手寫寫當時的心情, 有什麼工具可以留下當時那一點點思緒的發洩呢?

  不妨可以安裝 巴布(Buboo) , 註冊好帳號後, 登入巴布(Buboo) ->巴布工具 -> 留言版型,將程式碼複制到你的網站內,就可以了.



  成果就像下圖一樣

2008年10月6日 星期一

[DOM] W3C DOM 文件物件模型(Document Object Model,DOM)

From: Polin Wei

文件物件模型(Document Object Model,DOM)是給 HTML 與 XML 文件使用的一組 API。它提供了文件的結構表述(representation),讓你可以更動其中的內容及可見物。其本質是建立網頁與 Script 或程式語言溝通的橋樑。

[全球資訊網協會](World Wide Web Consortium,W3C)建立了 [DOM] 的標準,稱之為「W3C DOM」。在當今主要瀏覽器都已正確實作的情況下,W3C DOM 使強大、跨瀏覽器的應用程式成真。


  現在舉個 HTML檔案 實例來說明 DOM(Document Object Model,DOM)文件物件模型,這樣比較能瞭解。


W3CDOM.html

<html>
<head>
<script type='text/javascript'>
function showTd(){
   var nodes = document.getElementsByTagName("td");
   for(var i = 0; i < nodes.length; i++) {
      var node = nodes[i];
      alert(node.childNodes[0].nodeValue);
    }
}
function showTitle(){
   document.getElementById("myTitle").innerHTML ="<h2>我與小崴崴</h2>";
}
</script>
</head>
<body>
<input value="showTitle" onclick="showTitle();" type="button"><br>
<input value="showTDValues" onclick="showTd();" type="button"><br>


<div id="myTitle"></div>
<table>
  <tbody>
    <tr>
      <td>EmpID</td>
      <td>UserID</td>
      <td>UserName</td>
    </tr>
    <tr>
      <td>E0001</td>
      <td>Polin</td>
      <td>我</td>
    </tr>   
  </tbody>
</table>
</body>
</html>



  DOM 對 W3CDOM.html 檔案視為一個標籤文件,每個標籤視作一個節點,這些節點從<html>
標籤開始作為根標籤,上面的 W3CDOM.html 可以用下圖來表示(下圖中標示出相對於橘色tr節點的屬性):

PS:可以使用hasChildNodes()來測試目前的DOM節點物件是否有子節點。

  在JavaScript中可以使用document物件取得HTML文件中節點的值,如標籤上的id屬性id="myTitle",可以使用getElementById()並指定id名稱來取得節點的DOM物件,例如:

function showTitle(){
   document.getElementById("myTitle").innerHTML ="<h2>我與小崴崴</h2>";
}


  您也可以操作getElementsByTagName()並指定標籤名稱來取得節點,例如可使用以下的程式片段,顯示上例的表格文字內容:

function showTd(){
   var nodes = document.getElementsByTagName("td");
   for(var i = 0; i < nodes.length; i++) {
      var node = nodes[i];
      alert(node.childNodes[0].nodeValue);
    }
}


您可以使用DOM節點的innerHTML屬性來設定節點中的HTML內容,不過innerHTML並不是W3C DOM規範中的標準屬性,只是目前剛好大部份的瀏覽器都有支援,標準的作法是要懂得各種DOM上建立、設定節點的方法,可以深入瞭解這 innerHTML屬性。

2008年10月5日 星期日

[AJax] AJax 基本觀念與實作

From: Polin Wei

  AJax 技術是目前網頁流行的趨勢,在工作上也時常運用此技術.那什麼是 AJax 呢?節錄一段 WIKI 上的 AJax 文章如下:

AJAX全稱為「Asynchronous JavaScript and XML」(非同步JavaScriptXML),是一種創建互動式網頁應用的網頁開發技術。根據Ajax提出者Jesse James Garrett建議[1],它:

  • 使用XHTML+CSS來表示資訊;
  • 使用JavaScript操作DOM(Document Object Model)進行動態顯示及互動;
  • 使用XMLXSLT進行資料交換及相關操作;
  • 使用XMLHttpRequest物件與Web伺服器進行非同步資料交換;
  • 使用JavaScript將所有的東西繫結在一起。
  • 使用SOAPXML的格式來傳送方法名和方法參數。
對架構有興趣的網友再自行細讀.接下來我們要以實作來瞭解AJax的運作,在實作之前再說明一下, JavaScript要放在網頁中的兩種模式:

第一種:JavaScript 嵌入 HTML 中的作法,有下列兩種模式


A: <script type="text/javascript"> .code </script>
B: <script type="text/javascript" src="url"></script>


建議使用 B 為宜,因為這樣程式碼分離,閱讀及 Debug 都較為方便.

第二種:搭配 XHTML,若是搭配嚴謹的XHTML格式則必須使用 cdata 將 JavaScript 用註解格式封裝

<script type="“text/javascript”">
<![CDATA[//>
<!— Javascript Code here … //-->
<!]]>
</script>

AJAX 處理的順序大致可以分成下列五個步驟
1.Create the object : XMLHttpRequest
2.Set the readystatechange event trigger
3.Open the Request
4.Send the Request
5.Check the readyState property

整個架構圖如下:


  下面就舉實例來說明 AJax 這五個步驟,在這個實例中需要兩個檔案 AJax.html & HelloAjax.txt,透過 AJax.html 是來取得網站內 HelloAjax.txt 檔案裡的資料。

AJax.html 檔案

<html>
<head>
<script type='text/javascript'>
var myXmlHttp;
function createXmlHttpObj(){
if(window.XMLHttpRequest) {
myXmlHttp = new XMLHttpRequest();
} else if(window.ActiveXObject) {
myXmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
}
}

function handleStateChange(){
var txtresp;
var xmlresp;
if(myXmlHttp.readyState == 4) {
if(myXmlHttp.status == 200) {
//以純文字方式取回伺服器回傳資料
txtresp = myXmlHttp.responseText;
//以 XML 方式取回伺服器回傳資料
xmlresp = myXmlHttp.responseXML;

//5.Check the readyState property
if (txtresp) {
document.getElementById("myTxtResp").innerHTML = txtresp;
}
}
}
}

function sendRequest(){
// 1.Create the object : XMLHttpRequest
createXmlHttpObj();
if(myXmlHttp) {
// 2.Set the readystatechange event trigger
myXmlHttp.onreadystatechange = handleStateChange;

// 3.Open the Request
myXmlHttp.open('get', 'HelloAjax.txt');

// 4.Send the Request
myXmlHttp.send(null);

}else {
alert("您的瀏覽器不支援這個Ajax程式的功能");
}
}
</script>
</head>

<body>
<input value="click me(介紹 AJax 的功能)" onclick="sendRequest();" type="button"><br>
<a href="#" onClick="sendRequest();" >click me(介紹 AJax 的功能)</a>
<div id="myTxtResp"></div>
</body>
</html>


HelloAjax.txt 檔案

Hello AJax
這是由 AJax 技術取得伺服器後端 HelloAjax.txt 的檔案資料

參考:

AJax 基本觀念與實作

2008年10月4日 星期六

[AJax] XMLHttpRequest 物件的一些基本方法

From: Polin Wei

  標準 XMLHttpRequest 的操作方法如下 :
  • abort()
    停止當前請求
  • getAllResponseHeaders()
    把 HTTP 請求的所有回應標頭作為鍵/值對傳回
  • getResponseHeader("header")
    傳回指定標頭的字串值
  • open("method", "url")
    建立對伺服器的呼叫。method 參數可以是 GET、POST 或 PUT。url 參數可以是相對 URL 或絕對 URL。這個方法還包括 3 個可選的參數
  • send(content)
    向伺服器發送請求
  • setRequestHeader("header", "value")把指定標頭設定為所提供的值。在設定任何標頭之前必須先呼叫 open
接下來,再來針對各別的方法 ( Method ) 作比較仔細的說明:


  • void abort()
    顧名思義,這個方法就是要停止請求。
  • string getAllResponseHeaders()
    這個方法的核心功能對 Web 應用程式開發人員應該很熟悉了,它傳回一個字串,其中包含 HTTP 請求的所有回應標頭,標頭包括 ContentLength、Date 和 URI。
  • string getResponseHeader(string header)
    這個方法與 getAllRes-ponseHeaders() 是對應的,不過它有一個參數表示你希望得到的指定標頭值,並把這個值作為字串傳回。
  • void open(string method, string url, boolean asynch, string username,string password)
    這個方法會建立對伺服器的呼叫。這是初始化一個請求的純腳本方法。它有兩個必要的參數,還有 3 個可選參數。
  1. 要提供呼叫的特定方法(GET、POST 或 PUT)
  2. 還要提供所呼叫資源的 URL。
  3. 另外還可以傳遞一個 Boolean 值,指示這個呼叫是非同步的還是同步的。預設值為 true,表示請求本質上是非同步的。如果這個參數為 false,處理就會等待,直到從伺服器傳回回應為止。由於非同步呼叫是使用 Ajax 的主要優勢之一,所以倘若將這個參數設定為 false,從某種程度上講與使用XMLHttpRequest 物件的初衷不太相符。不過,前面已經說過,在某些情況下這個參數設定為 false 也是有用的,比如在持久儲存頁面之前可以先驗證使用者的輸入。
  4. 最後兩個參數不說自明,允許你指定一個特定的使用者名稱和密碼。
  • void send(content)
    這個方法實際向伺服器發出請求。如果請求聲明為非同步的,這個方法就會立即傳回,否則它會等待直到接收到回應為止。可選參數可以是 DOM 物件的實例、輸入串流,或者字串。傳入這個方法的內容會作為請求本體的一部分發送。
  • void setRequestHeader(string header, string value)
    這個方法為 HTTP請求中一個給定的標頭設定值。它有兩個參數,第一個字串表示要設定的標頭,第二個字串表示要在標頭中放置的值。需要說明,這個方法必須在呼叫 open() 之後才能呼叫。


  在所有這些方法中,最有可能用到的就是 open() 和 send()。XMLHttp-Request 物件還有許多屬性,在設計 Ajax 互動時這些屬性非常有用。

參考:

Ajax - XMLHttpRequest 重要的屬性

2008年10月3日 星期五

[CSS] pre 的運用

From: Polin Wei

  在網頁撰寫時,顯示整齊的程式碼可以讓人好檢視(如下圖)。


  但有時空格常會被吃掉,要怎麼作才能顯示出那些空格呢? 可以在 css 中定義一個 class 如下:

.code {
display: block; /* fixes a strange ie margin bug */
border: 1px solid black;
padding: 12px;
font-family: Courier New,Courier,monospace;
overflow:scroll;
letter-spacing: 0em;
white-space: pre ; // 要加入這一行
background: #F4F4F4 url('http://polin.wei.googlepages.com/codebg.png') left top repeat-y;
}


  然後在網頁中只要如下撰寫,就可以正常顯示了。


<div class="code">
if(window.XMLHttpRequest) {
  myXmlHttp = new XMLHttpRequest();
} else if(window.ActiveXObject) {
  myXmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
}
</div>

2008年9月22日 星期一

[AJax] XMLHttpRequest 重要的屬性

From: Polin Wei

  XMLHttpRequest 重要的屬性: onreadystatechange,readyState,status, statusText ,responseXML ,responseText。

  • onreadystatechange
    參考至callback函式,readyState每次改變時,都會呼叫onreadystatechange所參考的函式。
  • responseText
    伺服器傳來的請求回應文字,會設定給這個屬性。
  • responseXML
    伺服器傳來的請求回應如果是XML,會成為DOM設定給這個屬性。
  • statusText
    返回當前 XMLHttpRequest 請求的回應行狀態,回傳值: string status
  • readyState
    回應 XMLHttpRequest 的當前狀態,會有0到4的數值,共有5個狀態

0 = UNINITIALIZED; opennot yet called
(未初始化) Object已建立,但是尚未初始化(尚未使用open方法)

1 = Open; send for request not yet called
(初始化) Object已建立,尚未使用send方法

2 = Sent; send called, headers and status are available
(送出數據) send方法已使用,但是當前的狀態及http檔頭頭未知

3 = Receiving; downloading response, responseText only partially set
(數據傳送中) 已接收部分數據,因為回應及http檔頭不全,這時通過 responseBody 和responseText 獲取部分數據會出現錯誤

4 = COMPLETED; finished downloading
(完成)數據接數完畢,此時可以通過 responseBody 和 responseText 獲取完整的回應數據

status: 回應 XMLHttpRequest 請求的 http 狀態碼 ,回傳值:integer status code

100:Continue
101:Switching protocols
200:OK
201:Created
202:Accepted
203:Non-Authoritative Information
204:No Content
205:Reset Content
206:Partial Content
300:Multiple Choices
301:Moved Permanently
302:Found
303:See Other
304:Not Modified
305:Use Proxy
307:Temporary Redirect
400:Bad Request
401:Unauthorized
402:Payment Required
403:Forbidden
404:Not Found
405:Method Not Allowed
406:Not Acceptable
407:Proxy Authentication Required
408:Request Timeout
409:Conflict
410:Gone
411:Length Required
412:Precondition Failed
413:Request Entity Too Large
414:Request-URI Too Long
415:Unsupported Media Type
416:Requested Range Not Suitable
417:Expectation Failed
500:Internal Server Error
501:Not Implemented
502:Bad Gateway
503:Service Unavailable
504:Gateway Timeout
505:HTTP Version Not Supported

PS:此屬性 status 是唯讀,返回當前 XMLHttpRequest 請求的 http 狀態碼 ,此屬性僅當數據送出並完整接收完畢後才可以獲取。

程式範例如下:


if(myXmlHttp.readyState == 4) {
if(myXmlHttp.status == 200) {
//以純文字方式取回伺服器回傳資料
txtresp = myXmlHttp.responseText;
//以 XML 方式取回伺服器回傳資料
xmlresp = myXmlHttp.responseXML;
if (txtresp) {
alert(txtresp);
document.getElementById("myTxtResp").innerHTML = txtresp;
}
}
}



[AJax] Create The Object : XMLHttpRequest

From: Polin Wei

  XMLHttpRequest 的物件在 IE7以前版本 及 FireFox 各有不同,幸好在 IE7 時也支援 XMLHttpRequest Object:

  • Create XMLHttpRequest Object
  因為建立 XMLHttpRequest Object 在 IE7 以前版本及在 FireFox 是不一樣的,為了能相容,可以用下列方法來建立:

if(window.XMLHttpRequest) {
myXmlHttp = new XMLHttpRequest();
} else if(window.ActiveXObject) {
myXmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
}


在建立XMLHttpRequest之後,則可以使用以下的幾種方法:
  • void open(string method, string url, boolean asynch, string username, string password)
    開啟對伺服端的連結;method為請求方式(GET、POST);url為伺服端位址,如果是GET的話,可加上請求參數與值;asynch為非同步設定,預設是true,表示使用非同步方式。
  • void send(content)
    對伺服端傳送請求,content這以放XML、輸入串流、字串、JSON格式的內容,放進去會放在POST本體中發送。
  • void setRequestHeader(string header, string value)
    為HTTP請求設定一個給定的 header 設定值。
  • void abort()
    用來中斷請求。
  • string getAllResponseHeaders()
    傳回一個字串,其中包含HTTP請求的所有回應標頭。
  • string getResponseHeader(string header)
    傳回一個字串,其中包含指定的回應標頭值。

2008年9月10日 星期三

[AdSense] Feed Burner 部落格中 AdSense 的廣告

From: Polin Wei

  在[AdSense] AdSense 輕鬆的 Feed Burner 部落格中有介紹如何利用 Google AdSense 來 Burner你的部落格,可是卻一直沒有看到它的廣告.今天有試了一下,才發現它是要用類似 Google 閱讀器的 RSS 閱讀器才可以看得到.就像下圖:

我與小崴崴的工作日記: RSS: http://feedproxy.google.com/weipolin




我與小崴崴的電影日記:RSS: http://feedproxy.google.com/PolinJamie



我與小崴崴的生活日誌:RSS: http://feedproxy.google.com/jamieliao




這樣一來,你的廣告就有很多可以輪撥了,很不錯吧.大家一起來加入

我與小崴崴的工作日記: RSS: http://feedproxy.google.com/weipolin

我與小崴崴的電影日記:RSS: http://feedproxy.google.com/PolinJamie

我與小崴崴的生活日誌:RSS: http://feedproxy.google.com/jamieliao

捧個人場吧...

2008年9月3日 星期三

Google AdSense 在臺灣開通西聯匯款

真是個好消息, Google AdSense 終於在台灣有銀行可以匯款了。以下是 Google AdSense 發的信件內容,可惜的是,我沒還有足夠的廣告奬金可以匯啦!!
--------- Google AdSense 的信件原文-----------
親愛的發佈商:
我們有一個好消息要通知您 ─ 期待已久的西聯匯款 (Western Union Quick Cash) 已經正式向台灣 AdSense 發佈商開放!
使用西聯匯款有下列好處:

-款項在付款日隔天即可提領-提款不用任何手續費-任何一家提供西聯匯款服務的銀行均可提款
在登錄 AdSense 帳戶申請使用西聯匯款之前,請注意以下幾點:

-西聯匯款僅適用於個人帳戶,公司帳戶恕無法使用-提取西聯匯款時,必須攜帶身份證或護照,您的 AdSense 帳戶名字必須與您的身份證或護照名字相同。

另外,請注意,您的 AdSense 帳戶名字必須為拼音名字,因爲我們使用西聯匯款服務時,只能根據您的拼音名字匯款。

若您的 AdSense 帳戶名字為中文名字,請務必變更為對應的拼音名字。只要您的身份證或護照名字,按照臺灣通用拼音規則,與您的 AdSense帳戶名字一致,即可提款。

若您需要變更 AdSense 帳戶收款人姓名,請造訪https://www.google.com/adsense/support/bin/request.py?contact=change_payee
-您的款項必須在付款後 35 天内提出,否則將會過期,所有過期款項將返回您的 AdSense帳戶。我們會自動在您的帳戶中設定付款保留,如需解除此保留,請聯絡 Google AdSense 小組。
- 我們會透過美金匯款,不過,根據當地代理西聯業務的銀行政策,您可能以台幣提款。
若要開始使用西聯匯款,請參考我們的部落格文章http://zht-adsense.blogspot.com/2008/08/blog-post_15.html 或 AdSense 支援中心文章https://www.google.com/adsense/support/bin/answer.py?answer=62330

此外,我們在 AdSense 部落格發佈了一系列有關西聯匯款的文章,您可以造訪 http://zht-adsense.blogspot.com/,或造訪 AdSense 支援中心https://www.google.com/adsense/support/bin/topic.py?topic=10830 閲讀更多支援文章。

同時,歡迎您前往我們的 AdSense 支援論壇 http://www.google.com/adsensegroups-zht與更多人分享您使用西聯匯款的心得和體驗。

Google AdSense 中文小組敬上
Google Inc.1600 Amphitheatre ParkwayMountain View, CA 94043USA

2008年8月28日 星期四

[我是大明星] 我與小崴崴 上雜誌頭版了

From: Polin Wei

  電視明星看多了不稀奇。我與小崴崴也上了電子雜誌的頭版了耶。是 頭版 耶!!



  各大雜誌爭相報導喔!!


搞什麼啊,原來只要上 電子雜誌-我是大明星,每個人都可以是頭版嘛 !!

[DataBase] Oracle 的資料由 Linux 跨平台移轉到 Windows 平台

From: Polin Wei

Oracle DataBase 中的資料要跨平台移轉, 可以使用 exp/imp 的模式來作. 本範例示範由 Linux 平台移至 Windows 平台, 共有六個步驟:

先在 Windows 平台作好準備
step 1: create tablespace (建立與 Linux 平台一樣的 Tablespace 名字及檔案)

CREATE TABLESPACE "USERS_DATA"
LOGGING
DATAFILE 'C:\oraclexe\oradata\XE\USERS_DATA01.DBF' SIZE 50M
DEFAULT STORAGE ( MAXEXTENTS UNLIMITED);


step 2: Drop Users (帳號存在時, 才要作此步驟)

drop user JAPPS cascade;


step 3. Create Users(建立使用者)

create user JAPPS identified by JAPPS default tablespace USERS_DATA temporary tablespace temp;


step 4. Grant Permission (給予 create session 及 resource權限)

grant create session,resource to JAPPS;


step 5. export datas from original server (從 Linux 平台上匯出資料)

exp system/tiger@xp owner=\(JAPPS\) file=/tmp/exp_linux_data.dmp log=/tmp/exp_linux_data.log statistics=none grants=yes


step 6. import datas from dump file( import 到 Windows 平台)

imp system/oraclexe@xe grants=yes full=y ignore =y file="exp_linux_data.dmp" log="exp_linux_data.log"


以上就完成資料庫跨平台的移轉了

2008年8月27日 星期三

[教學] CBox 線上留言有 洋蔥頭 圖示囉

From: Polin Wei

  厭倦 CBox 一成不變的小圖示了嗎? 現在只要登入 CBox 後,在 Options->Smilies 就可以自己定義你想要的圖示。線上的圖示可以使用 即時通小圖網





step01: 在 即時通小圖網 滑鼠移到您想要的圖上, 按右鍵, 選擇內容


step02: 將網址貼在 CBox -> Options->Smilies 的 URL 內


step03: 完成後,成果如下:

【發現部落格新版圖!BlogAD夏日換新衣】

From: Polin Wei


  今天到 BlogAD 看了一下,發現它的網站已經換然一新了。以前的功能很少,而且網頁的配置真的不吸引人,但今天一看,哇!!立即吸引我的目光。現在它增加了以下的功能:

  以前 BlogAD 在計算奬金方面比較呆板,在此 BlogAD 的廣告獎金計算方式分為曝光式獎金及點閱式獎金兩種,您可以於每月的五號更換獎金計算方式,以下為兩種方式的說明:

  曝光式獎金主要是依照您每日的部落格流量、點閱數、廣告置放位置及您的下線數量來做加權分數計算,並且根據您的加權分數佔會員總分數的比例來計算獎金,一般而言,若您的部落格每日廣告遞送數超過5000以上,建議您採用這種方式。

  點閱式獎金為只要有網友點擊您部落格上的廣告,BlogAD就會從廣告主購買廣告的金額提撥固定比例的廣告獎金給您,每次的點擊會依照您昨日的廣告曝光數來決定獎金比例的多寡,也就是說只要您每日的廣告曝光數愈大,您得到的點閱獎金就愈多。

  BlogAD 為了讓會員能每日回BlogAD看看,它提供了另一項功能,賺BU幣! 嗯! 很棒喔,它除了可以賺錢、拿好康、體驗新產品、搶先看電影之外,還有一個令部落格主熱血沸騰的目標!!

  什麼是 「BU幣」?
「BU幣」是暢遊BlogAD所使用的虛擬貨幣。所有的服務皆可以用BU幣來購買。累計廣告獎金的同時,只要你有放BlogAD的廣告在自己的部落格裡,每天有一個 曝光數以上,每日就可以賺取 5BU,很簡單吧! 放廣告除了可以賺現金,還可以無形累積BU幣幫你購買其他好玩的服務。  

心動了嗎?馬上加入
BlogAD 吧!!

2008年8月25日 星期一

[DataBase] 如何在 OracleXE 建立自己的 Tablespace

From: Polin Wei

  在 OracleXE 資料庫中, 預設儲存的 Tablespace 是 USERS , 而 Temporary Tablespace 是 TEMP ,但若想要建立自己的帳號及預設的 Tablespace 該如何作呢?

先下SQL :
SELECT * FROM V$TABLESPACE;
查詢現有的 TABLESPACE






第一步驟:
  先建立一個 Tablespace 及該實體檔案的位置

CREATE TABLESPACE "sc"
LOGGING
DATAFILE ' C:\oraclexe\oradata\XE\ SC01.DBF' SIZE 10M;




第二步驟:
  建立使用者, 並指定要使用的 TABLESPACE and TEMPORARY TABLESPACE

CREATE USER sc <== 使用者名字
IDENTIFIED BY xxx <== 密碼
DEFAULT TABLESPACE sc <== 預設要使用的TABLESPACE
TEMPORARY TABLESPACE temp <== 預設要使用的 TEMPORARY



第三步驟:
 最後要給這個帳號權限

GRANT CREATE SESSION, RESOURCE TO SC;