2008年4月29日 星期二

TOMCAT + JSP 的中文問題

1、JSP頁面顯示的中文問題
Page的第一行改成:<%@ page contentType="text/html; charset=UTF-8" %>
Head里加:<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">

2、頁面Form 內容提交的中文問題
1) 只要把%TOMCAT安裝目錄%/ webapps\jsp-examples\WEB-INF\classes\filters\SetCharacterEncodingFilter.class 文件拷到你的webapp目錄下的filters下,如果沒有filters目錄,就創建一個。

2)在你的web.xml的</web-app>之前加入:
<filter>
<filter-name>Set Character Encoding</filter-name>
<filter-class>filters.SetCharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>Set Character Encoding</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

或者你不習慣用這個,可以在每個jsp頁面�使用request.setCharacterEncoding("UTF-8");我個人感覺是一樣的

3、get方式的解決辦法

1) 打開tomcat的server.xml文件,找到區塊,加入如下一行:URIEncoding="UTF-8"

完整的應如下:

<Connector port="8090" maxThreads="150" minSpareThreads="25"

maxSpareThreads="75"
enableLookups="false" redirectPort="8443" acceptCount="100"
debug="0" connectionTimeout="20000"
disableUploadTimeout="true"
URIEncoding="UTF-8"/>

2)重啓tomcat,一切OK。
當然還有最土的解決方案,雖然不太會用到,不過還是列出來,以備最無奈的時候使用:
String encodeStr=new String(fieldValue.getBytes("8859_1"), "UTF-8");

執行如下test.jsp頁面,測試是否成功
<%@ page contentType="text/html;charset=UTF-8"%>
<%@ page import="java.util.*"%>
<META http-equiv=Content-Type content="text/html;charset=UTF-8">
<%
String q=request.getParameter("q");
q = q == null?"沒有值":q;
%>
<HTML>
<HEAD>
<TITLE>新聞列表顯示</TITLE>
<body>你提交了:<%=q%><br>
<form action="test.jsp" method="post">
輸入中文:<input type="text" name="q"><input type="submit" value="確定"> <br>
<a href="test.jsp?q=中國">通過get方式提交</a>
</form>
</BODY>
</HTML>

4、mysql的中文問題
首先要修改mysql配置文件的encoding爲UTF-8,然後把jdbc connection改成如下:
jdbc:mysql://localhost:3306/bookuseUnicode=true;characterEncoding=UTF-8


電腦編碼的基本概念(轉貼)

電腦編碼的基本概念(轉貼)

編碼 (Encoding)
(作者: 謝東翰)
--------------------

A. 電腦編碼系統簡介:

電腦系統中資料儲存的最基本單位是「位元 (bit)」,而每個「位元」所
能代表的數值只有 0 與 1 而已。因此當我們要用電腦做資料的儲存與處理時,
我們通常會將連續幾個位元和起來看成一個單位,稱之為「位元組 (byte)」,
其所能代表的數值就不會只限於 0 與 1,而可以達到 2^n-1 (其中 n 為該位
元組中所包含的位元個數),如此我們就可以將我們想記錄在電腦系統的符號
一一編號,以位元組為單位儲存在電腦中,這就是編碼 (Encoding) 的基本觀念。

由於早期的電腦系統是發源於美國,因此最早的編碼系統也是發源於此。由於
他們的資料只需數字、26 個英文字母 (包括大小寫)、標點與其他特殊符號、
外加一些電腦系統的控制碼即可,因此當時一個位元組的大小只需 7 個位元
即可包含所有所需的資訊,總共可容納 128 個符號,這也就是大家所熟知的
ASCII 編碼。

然而對於歐洲語系而言,7 個位元的編碼空間不符合所需,因為除了 26 個英
文字母外,歐洲許多國家還需要拉丁字母、特殊字母的上下標與其他符號等,
才能完整表示他們的語言。因此原來的編碼系統必須再擴充,由 7 個位元變
為 8 個位元,以容納那些多出的符號,這就是 ISO8859 的編碼標準。而依地
區語系的不同, ISO8859 的編碼標準又分成幾個部分,例如 ISO8859-1 所包
含的符號可使用於英語、丹麥語、芬蘭語、德語 .... 等,而 ISO8859-2 則
可用於英語、德語、羅馬尼亞語、波蘭語 .... 等。每一個部分的 0-127 碼
的編碼方式與 ASCII 都是一樣的,只有在 128-255 碼才依地區不同而不同。
如此不同地區的人們可以選用不同部分的 ISO8859 編碼來處理他們的資料。

然而到了亞洲地區,上述的 8 位元編碼又不夠用了。因為亞洲地區不再是拼
音文字,因此多出了成千上萬個符號,我們已無法仿照當初 ISO8859 的做法,
弄出屬於中文的部分,或屬於日文的部分。唯一的作法只有合併幾個位元來
共同表示一個符號,如此才有足夠的空間來容納一個地區所有的文字。例如
我們台灣地區最常見的 BIG5 編碼,就是將兩個位元組合起來看成一個字。
但當一份文件中同時要有中英文時,意味著我們要有一個規則可以區分這個
位元組應該視為 ASCII 碼,或者它與它的下一個位元組應合起來視為一個
BIG5 碼。為了定出這樣的規則,就表示說我們無法全部使用整個雙位元組
的所有空間 (共 65536 個值)。就如我們的 BIG5 碼,其所包含的字數就只
有 13000 多個。

以上就地區語文使用似乎已經足夠了,然而在某些場合下,我們仍需要在同
一份文件中記錄多國文字。以 BIG5 編碼為例,它可以確保中文字與 ASCII
碼可以同時存在,不至於混餚 (事實上對於其他語系而言,他們的編碼方式多
半都是如此: 可以讓該地區的文字與 ASCII 碼同時存在),但如果我們要同時
表示中文、日文、韓文的文字呢?這裡就真正牽涉到多國語文的編碼範籌了。
而編碼系統的擴充就有兩種形式:

1. 文法式 (Modal) 編碼系統:

這裡最有名的就是 ISO2022 編碼。它的特徵是讓一個字串有「狀態」的區
別,而不同「狀態」的改變則以幾個特殊位元組值來代表。例如當一個字串
中讀到了位元組值 a 與位元組值 b 時,就表示字串進入狀態一,若讀到位
元組值 a 與 c 時就表示字串進入狀態二 .... 等。然後我們可以定義狀態
一以後的字串應解釋為日文 JIS 編碼,狀態二以後應解釋為簡體中文的 GB
編碼 .... 等等。如此便可以有系統地將各國的編碼方式整合進來。

很明顯的,這樣的編碼方式有一個限制,就是可以整合進來的編碼系統不能
與狀態改變標記位元 (如上例的 ab, ac .... 等) 衝突,否則的話就無法
整合進來。我們的 BIG5 編碼就是因為衝突了,所以無法整合到 ISO2022 中。
而且,這樣的編碼方式很複雜,程式實作困難,因此近年來較少有人使用了。

2. 定長式編碼系統:

此編碼系統是仿照 ASCII、ISO8859 的概念,給定一個固定長度的位元數,
試圖將世界上所有的符號都包含進來,並依序給它們編號。此方式最著名的
就是 Unicode (或稱 UCS2) 與 UCS4。以 Unicode 為例,其每個「位元組」
的長度固定為 16 個位元,即拿兩個傳統 8 位元的位元組合併成一個新的位
元組,然後編號從 0 到 65535 全部拿來使用,其中 0 到 127 是與 ASCII
碼相容的。如此方式,大概可以包含世界上主要的語言與符號如歐美地區、
中日韓越、中亞地區 .... 等等。至於 UCS4 則是 Unicode 的再擴充,其每
個「位元組」有 32 個位元,其中 0 到 65535 是與 Unicode 相同的,其餘
則是用來編入世界其他少數語言與罕用文字。

此編碼方式很明顯的好處就是沒有了文法式編碼系統的限制,同時程式容易
實作,只要提供一個適當的轉碼表,我們就可以很容易地將地區常用編碼系
統轉換為 Unicode 或 UCS4。此轉碼表可能相當大,特別是在繁體中文的
情況,但對於目前電腦系統的能力 (記憶體容量與運算速度 .... 等) 而言
已不是問題。因此,此編碼方式也逐漸成為世界的主流。儘管在某些地區仍
然對此編碼方式有意見,但在可預見的未來它將會越來越普遍。

然而,定長式編碼系統並非完全沒有限制的。最明顯的一點就是目前的電腦
硬體與程式語言都是將一個「位元組」定義為 8 個位元長,而非 16 或 32
個位元長,而且考慮到相容性的問題,在可預見的未來恐怕不會有全面性的
改變。同時由於不同 CPU 對於「位元序」的解釋不同,使得同樣是 16 或 32
位元的一個數值,在不同的 CPU 下會呈現不同的值 (例如 32 位元下在 x86
CPU 所呈現的數值 1,若將同樣的位元資料移到其他 RISC CPU 下可能呈現
出 16777216)。因此定長式編碼多半只能用於正執行中的程式內部,以便
於資料處理。若程式需要做資料的輸出入時,最理想的方式是將它轉為適當
的「多位元組編碼」 (見後述) 然後才進行。

B. GNU/Linux 下的編碼與字集:

在很多情況下,我們經常將「編碼 (Encoding)」與「字集 (Character Set)」
混為一談,但實際上它們各自有明確的定義的。所謂的「字集」是一組符號
(或文字) 的集合,而「編碼」則是將這一組符號 (或文字) 以適當的方式編
入位元組中,以便電腦能夠表示與儲存。在許多情況下,由於一個編碼方式所
能容納的字數是有限的,也因此就限定了它所能使用的「字集」,故有時我們
會將「編碼」與「字集」視為同一個東西。

在使用 glibc-2.2.X 系列的 GNU/Linux 系統中,由於已完整支援了 I18N 架
構,使得世界各地的語系資料庫都已完整地建立在系統底層的函式庫 (libc)
中,這其中也包含了各語系所用的字集與其相對應的編碼系統。以我們中文為
例,兩岸三地可能會常用到的編碼系統包括:

1. BIG5: 台灣地區最常見的編碼方式。目前 glibc 中的 BIG5 是以微軟公司
所定義的 CP950 為基礎,外加文鼎公司所採用的倚天外字集與 Unicode
轉換表而成。

2. EUC-TW: 此編碼即等價於教育部所編定的 ISO10646 國家標準編碼,目前
已內含了所有與 UCS4 可以互轉的中文字,其他尚未定義與 UCS4 可互
轉的中文字則要等定義完成後才會納入。

3. BIG5HKSCS: 此為香港地區所使用的 Big5 與香港政府增補字集。它與 BIG5
編碼是相容的,並加以擴充以容納其他罕用字。

4. GB2312: 此為大陸地區最通行的編碼方式,可容納常用的簡體字集。

5. GBK: 此為 GB2312 的擴充,除了容納原本 GB2312 中的簡體字以外,同時
還包含了繁體字與其他罕用字。

6. GB18030: 此為最近新定義出的字集編碼,與 GB2312 相容。

7. Unicode 與 UCS4: 其中 UCS4 在 GNU/Linux 系統中被用作轉碼系統的「基
底字集」(見後述)。

8. UTF-8: 此為 Unicode 的多位元編碼形式,可用於 Unicode 編碼的輸出。

以上的編碼系統在 GNU/Linux 中都有完整的支援,至於教育部新定的 Big5+
目前則不在支援之列。

C. GNU/Linux 的轉碼系統:

在具備完整的 I18N 環境支援的 UNIX 系統中 (包括 GNU/Linux 系統),其編
碼系統的轉換有兩種方式:

1. 一般轉換介面: 此即為 libc 中的 iconv() 編碼轉換介面,它可以做到各
種編碼的轉換。然而,在一般的 UNIX 系統中,並不見得系統同時支援編碼
系統 A 與編碼系統 B, 就一定能做到 A 與 B 之間的互轉,即使 A 與 B
內含相同的 (子) 字集。但在 GNU/Linux 底下,只要 A 與 B 內含相同的
(子) 字集,則可以直接透過 iconv() 做轉換。例如將 BIG5 轉成 BIG5HKSCS
或反過來,或者 GB2312 與 GBK 與 GB18030 之間的互轉。當然,各字集與
UCS4 之間的互轉都不是問題,原因就是 glibc 是以 UCS4 做為轉碼系統的
「基底字集」。

所謂的「基底字集」意指各地區的語文符號在系統內部的表式方式,而且它
還是各地區所有語文符號的集合。根據此定義,表示我們可以將世界各地所
有的編碼方式轉換成「基底字集」來統一處理 (理論上)。而 glibc 所採用
的「基底字集」的編碼方式就是 UCS4, 它是定長編碼系統,採用 32 位元
的位元組來編碼,它是目前已定義最大的一個字集的編碼方式,而且它仍持
續擴編世界各地的文字與符號。

在 GNU/Linux 下如果要透過 iconv() 進行轉碼工作時,它實際上是先將該
編碼轉成基底字集,然後再轉成目的編碼,如此便二確保只要編碼中有共同
的 (子) 字集時,轉換可以順利進行。

便對於沒有共同子字集的情況呢?例如 BIG5 與 GB2312 之間的互轉,在
GNU/Linux 下也提供額外的 iconv() 模組來進行,而這些都統一在 iconv()
介面之下,故在實際使用上不會感到任何差別。然而這類的額外模組目前
並未包含所有可能的轉換情況,但仍持續在建構中。例如 BIG5 與 GB2312
的互轉模組已於日前完成,目前尚在實驗版的 glibc-2.3 測試中,預計不
久的未來等 glibc-2.3 正式發表,並且大部分的 GNU/Linux 系統都換裝
glibc-2.3 之後,中文繁簡轉換的部分將不是問題。

2. 區域資料庫編碼轉換介面: 此轉換介面是與系統區域化資料庫 (locale) 相
關的,也是絕大部分的 I18N 程式會使用的介面。由於不同的區域化資料庫
所採用的編碼系統是固定的,例如我們台灣地區的區域化資料庫名稱為
zh_TW (或 zh_TW.Big5), 其採用的編碼系統即為 BIG5。而區域化資料庫主
要的任務只有在讓同一份程式碼可以處理各地區的語言,因而可以適用於各
地區,而不需要額外修改程式本身,故它的任何不在於處理多國語文的問題。
因此,這個轉碼介面只負責該資料庫所採用的編碼,與系統基底字集所採用的
編碼系統互轉而已。它不包含如上述 iconv() 轉碼介面那樣,可以做到任意
編碼系統間的互轉。

此轉碼介面最大的用途在於方便程式做文字處理。因為地區原本的編碼系統
多半是採用「多位元組」編碼方式,例如 BIG5 就是將兩個 8 位元的位元組
組合起來使用,故稱「多位元組編碼」。但當我們要在字串中區分中文字與
英文字母時就會遇到麻煩,因為前者是以兩個位元組來代表,後者確是以單
一一個位元組來代表,故我們要在程式中額外寫入 BIG5 碼的編碼規則才行,
而這樣的程式就不能適用與其他的編碼方式了。因此,當我們用此轉換介面
將它轉成定長編碼方式時,由於每個字 (不論中英文) 都是故定的長度 (即
位元組數),我們稱之為「寬字元 (wide character)」,這使得我們可以很
方便做字串處理。同時,我們的程式中也不必加入 BIG5 的編碼規則,因為
這些都在此轉碼介面中處理掉了,因此,這樣寫出來的程式就是一個支援 I18N
的程式,可以在不需要修改程式碼本身的情況下適用於各語系與編碼系統。

然而,我們在前面也提過,定長編碼方式 (即寬字元) 只能用於運作中的程式內部,
如果在做資料輸出入時可能因 CPU 的位元序不同與各硬體系統的限制而出錯。因此,
當我們要做資料交換時,最好的方式是將它轉回多位元組編碼,才能確保不會有問
題。這在第 2 點的轉換介面是不成問題的,因為基底字集與其多位元組編碼之間
的對應是定義在區域化資料庫中的;但在第 1 點的轉換介面中,特別是 Unicode
或 UCS4,而且包含了如中日韓等多國語文資料的情況又如何呢?對於 Unicode
而言,其所對應的多位元組編碼為 UTF-8, 它可以將所有 Unicode 碼轉換成不定
長度的位元組,視其 Unicode 碼值而定,而且轉出來的多位元組與 ASCII 編碼相
容,故可以適用於所有的 UNIX 應用程式。至於 UCS4 所對應的多位原組編碼則為
UTF-16, 它是將兩個 UTF-8 字元組合而成的。

參考資料:

1. CJKV: Information Processing, by Ken Lunde,
Publish: O'Reilly, ISBN: 1-56592-224-7

2. Documents of glibc-2.2: man pages and info pages.

利用JavaMail.收發Gmail郵件(SSL)

運用 Java Bean 連結資料庫 - 以 MySQL 為例

因市面上 JSP 的教學書籍在講到 JavaBeans 時大都僅只於其特性介紹,版工日前在某本書上看到實際運用的範例 [1],挑選其中較實用的一則做了適當修改後,提供給網友作為參考。其功能為將資料庫連結的動作寫於一共用元件中,以達到保密性(避免資料庫連結帳號、密碼直接寫在頁面中)、程式碼方便修改的彈性,以及程式碼共用,避免同樣的程式碼重複出現在各個頁面中。在微軟 ASP.NET 中也早在 1.0 版即有相同功能,稱為程式碼後置(Code-Behind),可將資料庫的連結和控制項的處理寫在裡面,其由 IIS(嚴格說起來是.NET Framework)在執行時作處理。而其元件的副檔名為 .vb(VB.net) 或 .cs(C#)。

 將資料庫連結寫在 Java Bean 中還有一項好處,即為可達成一位使用者連線時,只會建立一組資料庫的連結。比較能夠避免因不當的程式撰寫觀念,而導致在各種情況下(分頁功能、使用者重新整理頁面)都不斷重新建立資料庫連結,而嚴重影響網站運作效能、浪費伺服器資源與頻寬。下方分別為 Java Bean 與其被引用 JSP 的程式碼。

DBconn.java


package tw.idv.stephen;

import javax.servlet.http.*;
import java.sql.*;

// HttpSessionBindingListener 用來聆聽 Bean 物件何時會被加入或被移出一個 Session (該介面的實作,以本例而言並非必要)
public class DBconn implements HttpSessionBindingListener {
  private Connection conn = null;
  String stConn = "jdbc:mysql://localhost:3306/資料庫名稱?user=資料庫帳號&password=資料庫密碼&" +
           "useUnicode=true&characterEncoding=MS950";

  public DBconn() {
    //buildConn();  // 亦可在建構子中完成資料庫連結
  }

  private void buildConn() {
    try {
      Class.forName("com.mysql.jdbc.Driver");
      conn = DriverManager.getConnection(stConn);
    } catch(Exception e) {
      System.out.println(e.getMessage());  
// 錯誤訊息顯示在 Web Container 的控制台中
    }
  }

  public Connection
getConn() {  // 傳回型別為Connection
    if (conn == null)
      buildConn();

    return this.conn;
  }

  public void
closeConn() {
    try {
      conn.close();  
// 關閉連結
      conn = null;   // 註記以等待資源回收
    } catch(SQLException ex) {
      System.out.println(ex.getMessage());  
// 亦可用 ex.toString() 顯示更完整訊息
    }
  }

  // 當 Java Bean 物件加入 Session 物件時,將自動執行此內建函數
  public void valueBound(HttpSessionBindingEvent event) {}

  // 當 Java Bean 物件從 Session 中移除時,或 Session 物件消滅時,將自動執行此內建函數
  public void valueUnbound(HttpSessionBindingEvent event) {
    if (conn != null)
      closeConn();
  }
}

 上方 Java Bean 的程式中實作了 HttpSessionBindingListener 介面,該介面定義了 Session 範圍內的物件其生命週期。該聆聽器的主要用途,包括當你的屬性物件本身想知道它被加入一個 Session 範圍的時間點,以便它能同時去讀出後端資料庫的最新資料;還有當 Session 將它移除時,它就可趁機去更改資料庫中的資料 [2]。但在本例中引用該介面,僅用於提示其可應用時機,並未如上述般使用。

 程式員亦應養成好習慣,之後若 Session 內的物件不再使用時,應呼叫 Session 的 removeAttribute() 移除該屬性;而當 Session 本身不再使用時,亦可由程式員主動呼叫 Session 的 invalidate() 終結掉 Container 中的 Session。如此可節省伺服器的記憶體使用,並有助於運作效能。

DBconn.jsp


<%@ page contentType="text/html;charset=MS950" import="java.sql.*" %>
<HTML>
<BODY>
<CENTER>
利用 Java Bean 建立 MySql 資料庫連結。<br>
每一位使用者連線,只會建立一個資料庫連結。<hr>

<!-- JSP 2.0 以後,Java Bean 至少要放在 Web Container 根目錄的再下面一層目錄內 -->
<jsp:useBean id="ConDbBean" scope="session" class="tw.idv.stephen.DBconn"/>

<%
Connection conn = ConDbBean.
getConn();   // 呼叫 Bean 物件的 getConn() 方法,取得已建立完成的資料庫連結
Statement stmt = conn.createStatement();  // 可依需求改為 PreparedStatement
ResultSet rs = stmt.executeQuery("SELECT Title, Price, Page FROM StoreDB");
%>

<TABLE bgcolor=#FFCC66>
<TR bgcolor=#FF9933>
<TD>書 名</TD><TD>價 格</TD><TD>頁 數</TD>
</TR>
<%
while (rs.next()) {
  out.print("<TR bgcolor=LightYellow>");
  out.print("<TD>" + rs.getString(1) + "</TD>");           
// 可用欄位索引值(1,2,3,...)撈取資料,
  out.print("<TD align=right>" + rs.getString("Price") + "</TD>");    // 亦可用欄位名稱撈取。
  out.print("<TD align=right>" + rs.getInt("Page") + "</TD>");    // 此欄位在資料庫中是以整數型別儲存
  out.print("</TR>");
}

rs.close();
stmt.close();
ConDbBean.
closeConn();  // 呼叫 Java Bean 的 closeConn() 方法,關閉資料庫連結
%>

</TABLE>
</CENTER>
</BODY>
</HTML>

 在 Bean 之中通常不會一併完成 Statement 物件的建立,是因為 Statement 物件會對應到一組 SQL 敘述。因此,若用 Bean 物件提供 Statement,則一個連線僅會有一個 Statement 物件。有可能當某個連線正在開啟某 SQL 敘述所產生的 ResultSet 物件時,又有網頁執行另一個 SQL 敘述,如此將導致原來開啟的 ResultSet 物件關閉,因而造成不可預期的錯誤。

 

參考文件 :
[1] 位元文化,2003,「JSP動態網頁入門實務」,文魁出版社,第 12 章。
[2] Bryan Basham、Kathy Sierra、Bert Bates,2005,「Head First Servlets & JSP」,O'Reilly 出版社,第 254 頁。

最近看的書--寫給SA的UML/MDA實務手冊


不錯的書..頁數不多.但內容精要.方便帶在身邊看
<<1198122227215.jpg>>

FW: 利用JavaMail.收發Gmail郵件(SSL)


    利用JavaMail收/發Gmail郵件(SSL)
    Gmail目前已經啓用了POP3和SMTP服務
    與其他郵箱不同的是Gmail提供的POP3和SMTP是使用安全套接字層SSL的,因此常規的JavaMail程式是無法收發郵件的,下面是使用JavaMail如何收取Gmail郵件以及發送郵件的代碼:

    1. 郵件收取
    package lius.javamail.ssl;
    import java.io.UnsupportedEncodingException;
    import java.security.*;
    import java.util.Properties;
    import javax.mail.*;
    import javax.mail.internet.InternetAddress;
    import javax.mail.internet.MimeUtility;

    /**
    *
    用於收取Gmail郵件
    * @author Winter Lau
    */
    public class GmailFetch {

    public static void main(String argv[]) throws Exception {

    Security.addProvider(new com.sun.net.ssl.internal.ssl.Provider());
    final String SSL_FACTORY = "javax.net.ssl.SSLSocketFactory";

    // Get a Properties object
    Properties props = System.getProperties();
    props.setProperty("mail.pop3.socketFactory.class", SSL_FACTORY);
    props.setProperty("mail.pop3.socketFactory.fallback", "false");
    props.setProperty("mail.pop3.port", "995");
    props.setProperty("mail.pop3.socketFactory.port", "995");

    //以下步驟跟一般的JavaMail操作相同
    Session session = Session.getDefaultInstance(props,null);

    //請將紅色部分對應替換成你的郵箱帳號和密碼
    URLName urln = new URLName("pop3","pop.gmail.com",995,null,
    "
    [郵箱帳號]", "[郵箱密碼]");
    Store store = session.getStore(urln);
    Folder inbox = null;
    try {
    store.connect();
    inbox = store.getFolder("INBOX");
    inbox.open(Folder.READ_ONLY);
    FetchProfile profile = new FetchProfile();
    profile.add(FetchProfile.Item.ENVELOPE);
    Message[] messages = inbox.getMessages();
    inbox.fetch(messages, profile);
    System.out.println("
    收件箱的郵件數:" + messages.length);
    for (int i = 0; i < messages.length; i++) {
    //
    郵件發送者
    String from = decodeText(messages[i].getFrom()[0].toString());
    InternetAddress ia = new InternetAddress(from);
    System.out.println("FROM:" + ia.getPersonal()+'('+ia.getAddress()+')');
    //
    郵件標題
    System.out.println("TITLE:" + messages[i].getSubject());
    //
    郵件大小
    System.out.println("SIZE:" + messages[i].getSize());
    //
    郵件發送時間
    System.out.println("DATE:" + messages[i].getSentDate());
    }
    } finally {
    try {
    inbox.close(false);
    } catch (Exception e) {}
    try {
    store.close();
    } catch (Exception e) {}
    }
    }

    protected static String decodeText(String text)
    throws UnsupportedEncodingException {
    if (text == null)
    return null;
    if (text.startsWith("=?GB") || text.startsWith("=?gb"))
    text = MimeUtility.decodeText(text);
    else
    text = new String(text.getBytes("ISO8859_1"));
    return text;
    }

    }
    2. 發送郵件
    package lius.javamail.ssl;
    import java.security.Security;
    import java.util.Date;
    import java.util.Properties;

    import javax.mail.Authenticator;
    import javax.mail.Message;
    import javax.mail.MessagingException;
    import javax.mail.PasswordAuthentication;
    import javax.mail.Session;
    import javax.mail.Transport;
    import javax.mail.internet.AddressException;
    import javax.mail.internet.InternetAddress;
    import javax.mail.internet.MimeMessage;

    /**
    *
    使用Gmail發送郵件
    * @author Winter Lau
    */
    public class GmailSender {

    public static void main(String[] args) throws AddressException, MessagingException {
    Security.addProvider(new com.sun.net.ssl.internal.ssl.Provider());
    final String SSL_FACTORY = "javax.net.ssl.SSLSocketFactory";
    // Get a Properties object
    Properties props = System.getProperties();
    props.setProperty("mail.smtp.host", "smtp.gmail.com");
    props.setProperty("mail.smtp.socketFactory.class", SSL_FACTORY);
    props.setProperty("mail.smtp.socketFactory.fallback", "false");
    props.setProperty("mail.smtp.port", "465");
    props.setProperty("mail.smtp.socketFactory.port", "465");
    props.put("mail.smtp.auth", "true");
    final String username = "
    [郵箱帳號]";
    final String password = "
    [郵箱密碼]";
    Session session = Session.getDefaultInstance(props, new Authenticator(){
    protected PasswordAuthentication getPasswordAuthentication() {
    return new PasswordAuthentication(username, password);
    }});

    // -- Create a new message --
    Message msg = new MimeMessage(session);

    // -- Set the FROM and TO fields --
    msg.setFrom(new InternetAddress(username + "@mo168.com"));
    msg.setRecipients(Message.RecipientType.TO,
    InternetAddress.parse("
    [收件人地址]",false));
    msg.setSubject("Hello");
    msg.setText("How are you");
    msg.setSentDate(new Date());
    Transport.send(msg);

    System.out.println("Message sent.");
    }
    }

初學者必看--如何學習jsp

初學者必看--如何學習jsp

轉貼==

 初學者必看:如何學習jsp

在網上看到很多問題是關于如何學習jsp的,正好網上看到一篇關于學習jsp的文章,就摘了一部分翻譯過來,希望能對大家學習jsp有點指
導。
一個普通的錯誤是把JSP當作簡化的 Java。它不是,(事實上, JSP 是簡化的 servlets 。)程序員通常試著沒有學習要求的支持技巧而
直接學習 JSP 。JSP 是一個餃接技術,並且成功地連接你需要理解的另外的技術。如果你已經知道 Java , HTML 和 Javascript,這意味著
JSP 將確實是簡單的。
需要成為一個成功的 JSP 程序員可以參考這個時間表。請注意下列︰
*忽略你已經熟悉的步驟。
*訓練的時間只是代表學習好足夠的基礎時間,這樣才能轉移到下一步。
1、建立並且理解你的Web Server。
因為Apache 是免費的並且在大多數平台上工作,為訓練目的推薦 Apache。
安裝時間︰2 天。

2、 保證你理解 HTML / XHTML 。
你將需要了解html基礎, 特別是 HTML 布局中的table的使用。XHTML 不久將代替 HTML ,學習 XHTML 的基礎是一個好主意。許多程序員
通過 HTML IDE 學習 HTML ( 集成開發環境 ) 。因為大多數 HTML IDE產生混亂的HTMl語法,所以花時間學習手工寫作html是很有必要的。因
為你將會使用 JSP 和 HTML 混合編程,精通HTML語法是重要的。所以,你必須能流利地寫 HTML 。
訓練時間︰2 ∼ 4 個星期。

3、開始學習 Java 。
開始學習 Java 1.3 理解 Java 基礎是很重要的。不用擔心學習Swing或 Java 的圖形方面,因為在JSP 中你不會使用這些特征。集中精力
在 Java 工作的細節,學習 Java 的邏輯,也在 Java Bean上花時間。學習Applet是好的, 但是就象Swing, JSP 的大多數應用將不使用小程
序。
訓練時間︰3 ∼ 6 個星期。

3、學習 JavaScript
學習怎麼將 JavaScript在HTML中驗證輸入的Form元素。也學習 JavaScript怎麼能在一 HTML 頁以內修改Form的元素。最後要求你能從一
HTML 頁內的事件中觸發 JavaScript Function。
訓練時間︰一∼ 2 個星期。

4、學習並且理解你的Web Server的更好的細節。
熟悉Web Server的特征,這是很重要的。
訓練時間︰2 天。

5、建立你的 JSP Server
我推薦以Tomcat開始。它可以很好地運行JSP程序。當你不能在生產使用Tomcat時,學習盡可能多的知識以便于更好的運行程序。另外, 許
多 JSP 程序員使用Tomcat。因此當你遇到一個問題時,你將容易發現幫助。
安裝時間︰一∼ 2 天。

6、開始學習 JSP 。
基本的 JSP 學習通過的步驟 1到步驟6可以完成, 然後使用 JSP 對象和腳本寫 JSP 程序來聯系。學習 JSP 的另外一個方面可以學習怎麼創
建一個分布式的應用程序。
訓練時間︰4 ∼ 6 個星期。

7、學習更多的 JSP server。
沒有關于更多的 JSP Server當然也可以運行jsp程序。然而, 許多 JSP server都由自己特殊的特征,可以讓你更好的理解你的JSP 工程。
學習更多的Jsp server如何處理jsp程序是有必要的。同樣也可以優化你的 JSP 應用程序,並且使之運行得更快而不出任何問題。
訓練時間︰2 ∼ 7 天。

8、 學習 JDBC 。
JSP 大多數應用將使用數據庫,JDBC 被用于數據庫連接。經常忽略的一個事實就是,每個 JDBC Driver 所支持的東西是相當不同的。了
解並熟悉在jsp工程上被使用的 JDBC driver的細節是很重要的。
(有時這部分的學習被包含在前面 Java 或JSP的學習中了 。)
訓練時間︰1∼ 2 個星期。
到現在,你已經成為了熟練的 JSP 程序員。仍然有很多需要學習,你可以考慮擴展你的知識比如 DHTML , XML ,java證書, JSP Tag
Libraries 或 Servlets , 看你想要造什麼類型的網站而決定了。
這些訓練是JSP 的核心。你不必都學習上面所有的, 取決于你在工程中分配到什麼任務和你已經有什麼知識。但是這是我成功地訓練程序員
的時間表。關鍵的單元是時間。平均的說, 5 個月時間確實能夠訓練一個人 ( 從開始到完成 ) 成為一個對jsp熟悉程序員。5 個月時間似乎很
長,但要成為一個資深的WEB程序員所學的東西遠遠不止這一些。
也許你認為這樣學習一種語言花費的時間太長了,因為學 ASP 會更快、時間會更短。 但是學習 ASP 不需要學習java的。

如何使用JAVA API中的Collection 來儲存值

轉貼自

通常Vector裡的都是物件的reference,而不是實際的物件

存放在Vector裡的都是物件,所以才會有String和int...等等的資料型態的差異,

例如:String在JAVA裡事物件的型態,可是int...等等,都是數值,而不是物件

把一些物件塞入Vector, 例如:

&nbsp;Vector v = new Vector();

Vector w = new Vector();

String[] firstnames = { "Spencer" , "Benx" , "Jaseph" , "Isao" , "Sidekick" };

String[] lastnames = { "is handsome boy" , "is our manager" , "is sale's father" , "is

tobacco's man" , "is our MIS"};



for( int i =0 ; i < firstnames.length ; i++ )

v.add(firstnames[i]);

for( int k =0 ; k < lastnames.length ; k++)

w.add(lastnames[k]);

for( int j = 0 ; j < v.size() ; j++)

System.out.println(" Odject.co's the best teammates = " + v.get(j) +" "+ w.get(j));

NEW起來一個Vector,然後跑一個for迴圈,把值塞入.

get出來時候,也是以同樣的方式

或者用Iterator來一一取得集合裡的值

Iterator it = v.iterator();

Iterator lit = w.iterator();



while(it.hasNext()){

System.out.println(" Odject.co's the best teammates(Iterators) = " + it.next()+" "+ lit.next());

}

以上面的結果,出來的值:

Odject.co's the best teammates = Spencer is handsome boy

Odject.co's the best teammates = Benx is our manager

Odject.co's the best teammates = Jaseph is sale's father

Odject.co's the best teammates = Isao is tobacco's man

Odject.co's the best teammates = Sidekick is our MIS

Odject.co's the best teammates(Iterators) = Spencer is handsome boy

Odject.co's the best teammates(Iterators) = Benx is our manager

Odject.co's the best teammates(Iterators) = Jaseph is sale's father

Odject.co's the best teammates(Iterators) = Isao is tobacco's man

Odject.co's the best teammates(Iterators) = Sidekick is our MIS

如果是一個陣列其元素是數值(只有字串是物件,塞入集合中只能塞入物件)時:

Vector a = new Vector();
int[] h = { 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 };
for( int g = 0 ; g < h.length ; g++ )
a.add( new Integer ( h[g] ));
Iterator lv = a.iterator();
while(lv.hasNext()){
System.out.println( " LV的(iterator) "+ lv.next());
}

雜湊表的用法學習:

//雜湊表的塞值和取值

HashMap aMap = new HashMap();

String myKey1 = "key1";

String myKey2 = "key2";

Integer theObject1 = new Integer(12345);

String theObject2 = "塞入的第二個值 theObject2";

aMap.put( myKey1 , theObject1);

aMap.put( myKey2 , theObject2);

if(aMap.put( myKey1 , theObject1) != null ){

System.out.println(" Oh Ya Baby ~~~~ I put an object to HashMap ");

}

System.out.println(aMap.get(myKey1));

System.out.println(aMap.get("key1"));

System.out.println(aMap.get("key2"));


雜湊表中用Iterator的塞key取值法:

Set keys = aMap.keySet();

Iterator keyIter = keys.iterator();

//Iterator keyIter = aMap.keySet().iterator();

while(keyIter.hasNext()){

System.out.println("aMap.Iterator(value) = " + keyIter.next());

}