如果與a,form對象,image對象,applet對象相對應的html標記中設定了name性質,它的值將被用作document對象的屬性名,用來引用相應的對象,其他的對象則不可以。
另外,input等如果作為form的子元素,則直接用inputName或者document.inputName來引用此對象就是錯誤的,必須使用formName.inputName引用,否則就可以使用inputName來引用.
另外應該注意到有很多平時用的元素都沒有name.
如果想引用一個有id的元素,只能用Id或者document.getElementById,document.all.id來引用
但是象這樣的元素,所以象<a href="......" name="linkname" id="linkid">......</a>這樣的
可以用
linkid.href;
linkname.href;
document.all.linkid.href;
document.all.linkname.href;
document.getElementById("linkid").href;
document.getElementsByName("linkname")[0].href來引用
all是一個集合,包含所有html對像的集合,寫一個程式,可以存取到所有的對像。像這樣:
<script language="javascript">
var obj="";
for(i=0;i<document.all.length;i++)
obj+=document.all[i].tagName+";";
alert(obj);
</script>
注意要把程式放到</html>之后哦。
一. 10句話
1.不要依賴register_global=ON的環境,從你剛懂得配置php運行環境甚至尚不明白register_global的ON/OFF會對自己有什么影響的那天起,就應該勇敢地把它設為OFF.
2.寫程序前看看怎么用error_reporting.
3.不懂就問本身沒錯,但你需要在那之前查查手冊。
4.當然,你需要懂得使用手冊。手冊上找不到答案的時候,應該考慮下網絡上的搜索引擎。
5.剛學會php+mysql之后,不要叫嚷著要寫論壇,要寫XXX。要明白,剛學會寫漢字并不表示你有能力寫詩。
6.在學web編程的時候,你應該先去認識html這個朋友。
7.有點能力后,試著回答新手的問題,不要看到自己懂的而別人不懂就沾沾自喜,扔下一名“簡單,那是基本的東西”就走更要不得。
8.思考是一個好習慣,不動手去寫就等于空想,什么也沒有。
9.寫好一段程序,如果覺得很滿意,一周后再看一遍,也許你會認為它應該有所改變
10.有空多看看別人的程序,找出他人的不足或優點,自己掂量。
二. 各取所需
1.善于使用“引用”,它能直接影響到程序的效率。
2.善于用三元運算子,可以讓程式較精簡有效率。
比如:
PHP代碼:
if ($data[$i]['nickname'])
{
????$nickname =??$data[$i]['nickname'];
}
else
{
????$nickname =??$data[$i]['ip'];
}
可以寫成:
PHP代碼:
$nickname =??$data[$i]['nickname'] ? $data[$i]['nickname'] : $data[$i]['ip'];
3.善于組織if...else...回圈
比如:
PHP代碼:
$ext_name = strtolower(str_replace(".", "", strrchr($upfilename, ".")));
if (!empty($type))
{
????if (!strpos($type, $ext_name))
????{
????????echo "Please upload the file of $type form.";
????????exit();
????}
}
上面的代碼你應該寫成這樣:
PHP代碼:
$ext_name = strtolower(str_replace(".", "", strrchr($upfilename, ".")));
if (!($type==='') && strpos($type, $ext_name)===false)
{
????echo "Please upload the file of $type form.";
????exit();
}
4.盡量讓你的代碼清淅些
如果寫成這樣,是比較讓人頭痛的:
PHP代碼:
$foo=$_post["foo"];
???$username=$_post["user"];
$group=$_POST["group"];
if ($group=="wheel"){
$username=$username."wheel";
}
同樣的代碼,這樣就比較讓人看得舒服了:
PHP代碼:
$foo??????= $_post["foo"];
$username = $_post["username"];
$group????= $_POST["group"];
if ($group=="wheel")
{
????$username = $username."wheel";
}
當然,有一定基礎后,你應該要寫成這樣:
PHP代碼:
$foo??????= &$_POST['foo'];
$username =??$_POST["group"]!='wheel' ? $_POST["username"] : $_POST["username"].'wheel';
5.編寫規范的mysql 語句。
字段和表名用"`"引起來,避免保留字的影響。
如果看到下面這樣的一個sql query,會讓人比較頭痛:
PHP代碼:
$query="select `flash_comment`.`content` , `flash_comment`.`nickname` , `flash_comment`.`date` , `flash_comment`.`ip` , `product`.`p_name` , `sgflash`.`fid` from `flash_comment` left join `product` on ( `flash_comment`.`p_no` = `product`.`p_no` ) left join `sgflash` on ( `product`.`p_name` = `sgflash`.`f_name` ) where `flash_comment`.`p_no` != '' order by `flash_comment`.`date`";
同樣的一個query,寫成這樣就令人看得明白得多了:
PHP代碼:
$query = "SELECT `flash_comment`.`content` , `flash_comment`.`nickname` , `flash_comment`.`date` , `flash_comment`.`ip` , `product`.`p_name` , `sgflash`.`fid`
??????????FROM `flash_comment`
??????????LEFT JOIN `product` ON ( `flash_comment`.`p_no` = `product`.`p_no` )
??????????LEFT JOIN `sgflash` ON ( `product`.`p_name` = `sgflash`.`f_name` )
??????????WHERE `flash_comment`.`p_no` != ''
??????????ORDER BY `flash_comment`.`date`";
1、中文問題的來源
????計算機最初的操作系統支持的編碼是單字節的字符編碼,于是,在計算機中一切處理程序最初都是以單字節編碼的英文為準進行處理。隨著計算機的發展,為了適應世界其它民族的語言(當然包括我們的漢字),人們提出了UNICODE編碼,它采用雙字節編碼,兼容英文字符和其它民族的雙字節字符編碼,所以,目前,大多數國際性的軟件內部均采用UNICODE編碼,在軟件運行時,它獲得本地支持系統(多數時間是操作系統)默認支持的編碼格式,然后再將軟件內部的UNICODE轉化為本地系統默認支持的格式顯示出來。Java的JDK和JVM即是如此,我這里說的JDK是指國際版的JDK,我們大多數程序員使用的是國際化的JDK版本,以下所有的JDK均指國際化的JDK版本。我們的漢字是雙字節編碼語言,為了能讓計算機處理中文,我們自己制定的gb2312、GBK、GBK2K等標準以適應計算機處理的需求。所以,大部分的操作系統為了適應我們處理中文的需求,均定制有中文操作系統,它們采用的是GBK,GB2312編碼格式以正確顯示我們的漢字。如:中文Win2K默認采用的是GBK編碼顯示,在中文WIN2k中保存文件時默認采用的保存文件的編碼格式也是GBK的,即,所有在中文WIN2K中保存的文件它的內部編碼默認均采用GBK編碼,注意:GBK是在GB2312基礎上擴充來的。
????由于Java語言內部采用UNICODE編碼,所以在JAVA程序運行時,就存在著一個從UNICODE編碼和對應的操作系統及瀏覽器支持的編碼格式轉換輸入、輸出的問題,這個轉換過程有著一系列的步驟,如果其中任何一步出錯,則顯示出來的漢字就會出是亂碼,這就是我們常見的JAVA中文問題。
????同時,Java是一個跨平臺的編程語言,也即我們編寫的程序不僅能在中文windows上運行,也能在中文Linux等系統上運行,同時也要求能在英文等系統上運行(我們經常看到有人把在中文win2k上編寫的JAVA程序,移植到英文Linux上運行)。這種移植操作也會帶來中文問題。
????還有,有人使用英文的操作系統和英文的IE等瀏覽器,來運行帶中文字符的程序和瀏覽中文網頁,它們本身就不支持中文,也會帶來中文問題。
????有,幾乎所有的瀏覽器默認在傳遞參數時都是以UTF-8編碼格式來傳遞,而不是按中文編碼傳遞,所以,傳遞中文參數時也會有問題,從而帶來亂碼現象。
????總之,以上幾個方面是JAVA中的中文問題的主要來源,我們把以上原因造成的程序不能正確運行而產生的問題稱作:JAVA中文問題。
2、JAVA編碼轉換的詳細過程
????我們常見的JAVA程序包括以下類別:
???? *直接在console上運行的類(包括可視化界面的類)
???? *JSP代碼類(注:JSP是Servlets類的變型)
???? *Servelets類
???? *EJB類
???? *其它不可以直接運行的支持類
????這些類文件中,都有可能含有中文字符串,并且我們常用前三類JAVA程序和用戶直接交互,用于輸出和輸入字符,如:我們在JSP和Servlet中得到客戶端送來的字符,這些字符也包括中文字符。無論這些JAVA類的作用如何,這些JAVA程序的生命周期都是這樣的:
????*編程人員在一定的操作系統上選擇一個合適的編輯軟件來實現源程序代碼并以.java擴展名保存在操作系統中,例如我們在中文win2k中用記事本編輯一個java源程序;
???? *編程人員用JDK中的javac.exe來編譯這些源代碼,形成.class類(JSP文件是由容器調用JDK來編譯的);
???? *直接運行這些類或將這些類布署到WEB容器中去運行,并輸出結果。
????那么,在這些過程中,JDK和JVM是如何將這些文件如何編碼和解碼并運行的呢?
????這里,我們以中文win2k操作系統為例說明JAVA類是如何來編碼和被解碼的。
????第一步,我們在中文win2k中用編輯軟件如記事本編寫一個Java源程序文件(包括以上五類JAVA程序),程序文件在保存時默認采用了操作系統默認支持GBK編碼格式(操作系統默認支持的格式為file.encoding格式)形成了一個.java文件,也即,java程序在被編譯前,我們的JAVA源程序文件是采用操作系統默認支持的file.encoding編碼格式保存的,java源程序中含有中文信息字符和英文程序代碼;要查看系統的file.encoding參數,可以用以下代碼:
public class ShowSystemDefaultEncoding {
public static void main(String[] args) {
String encoding = System.getProperty("file.encoding");
System.out.println(encoding);
}}
????第二步,我們用JDK的javac.exe文件編譯我們的Java源程序,由于JDK是國際版的,在編譯的時候,如果我們沒有用-encoding參數指定我們的JAVA源程序的編碼格式,則javac.exe首先獲得我們操作系統默認采用的編碼格式,也即在編譯java程序時,若我們不指定源程序文件的編碼格式,JDK首先獲得操作系統的file.encoding參數(它保存的就是操作系統默認的編碼格式,如WIN2k,它的值為GBK),然后JDK就把我們的java源程序從file.encoding編碼格式轉化為JAVA內部默認的UNICODE格式放入內存中。然后,javac把轉換后的unicode格式的文件進行編譯成.class類文件,此時.class文件是UNICODE編碼的,它暫放在內存中,緊接著,JDK將此以UNICODE編碼的編譯后的class文件保存到我們的操作系統中形成我們見到的.class文件。對我們來說,我們最終獲得的.class文件是內容以UNICODE編碼格式保存的類文件,它內部包含我們源程序中的中文字符串,只不過此時它己經由file.encoding格式轉化為UNICODE格式了。
????這一步中,對于JSP源程序文件是不同的,對于JSP,這個過程是這樣的:即WEB容器調用JSP編譯器,JSP編譯器先查看JSP文件中是否設置有文件編碼格式,如果JSP文件中沒有設置JSP文件的編碼格式,則JSP編譯器調用JDK先把JSP文件用JVM默認的字符編碼格式(也即WEB容器所在的操作系統的默認的file.encoding)轉化為臨時的Servlet類,然后再把它編譯成UNICODE格式的class類,并保存在臨時文件夾中。如:在中文win2k上,WEB容器就把JSP文件從GBK編碼格式轉化為UNICODE格式,然后編譯成臨時保存的Servlet類,以響應用戶的請求。
????第三步,運行第二步編譯出來的類,分為三種情況:
????A、 直接在console上運行的類
????B、 EJB類和不可以直接運行的支持類(如JavaBean類)
????C、 JSP代碼和Servlet類
????D、 JAVA程序和數據庫之間
????下面我們分這四種情況來看。
????A、直接在console上運行的類
????這種情況,運行該類首先需要JVM支持,即操作系統中必須安裝有JRE。運行過程是這樣的:首先java啟動JVM,此時JVM讀出操作系統中保存的class文件并把內容讀入內存中,此時內存中為UNICODE格式的class類,然后JVM運行它,如果此時此類需要接收用戶輸入,則類會默認用file.encoding編碼格式對用戶輸入的串進行編碼并轉化為unicode保存入內存(用戶可以設置輸入流的編碼格式)。程序運行后,產生的字符串(UNICODE編碼的)再回交給JVM,最后JRE把此字符串再轉化為file.encoding格式(用戶可以設置輸出流的編碼格式)傳遞給操作系統顯示接口并輸出到界面上。
????對于這種直接在console上運行的類,它的轉化過程可用圖1更加明確的表示出來:
圖1
????以上每一步的轉化都需要正確的編碼格式轉化,才能最終不出現亂碼現象。
????B、EJB類和不可以直接運行的支持類(如JavaBean類)
????由于EJB類和不可以直接運行的支持類,它們一般不與用戶直接交互輸入和輸出,它們常常與其它的類進行交互輸入和輸出,所以它們在第二步被編譯后,就形成了內容是UNICODE編碼的類保存在操作系統中了,以后只要它與其它的類之間的交互在參數傳遞過程中沒有丟失,則它就會正確的運行。
這種EJB類和不可以直接運行的支持類, 它的轉化過程可用圖2更加明確的表示出來:
圖2
????C、JSP代碼和Servlet類
????經過第二步后,JSP文件也被轉化為Servlets類文件,只不過它不像標準的Servlets一校存在于classes目錄中,它存在于WEB容器的臨時目錄中,故這一步中我們也把它做為Servlets來看。
????對于Servlets,客戶端請求它時,WEB容器調用它的JVM來運行Servlet,首先,JVM把Servlet的class類從系統中讀出并裝入內存中,內存中是以UNICODE編碼的Servlet類的代碼,然后JVM在內存中運行該Servlet類,如果Servlet在運行的過程中,需要接受從客戶端傳來的字符如:表單輸入的值和URL中傳入的值,此時如果程序中沒有設定接受參數時采用的編碼格式,則WEB容器會默認采用ISO-8859-1編碼格式來接受傳入的值并在JVM中轉化為UNICODE格式的保存在WEB容器的內存中。Servlet運行后生成輸出,輸出的字符串是UNICODE格式的,緊接著,容器將Servlet運行產生的UNICODE格式的串(如html語法,用戶輸出的串等)直接發送到客戶端瀏覽器上并輸出給用戶,如果此時指定了發送時輸出的編碼格式,則按指定的編碼格式輸出到瀏覽器上,如果沒有指定,則默認按ISO-8859-1編碼發送到客戶的瀏覽器上。這種JSP代碼和Servlet類,它的轉化過程可用圖3更加明確地表示出來:
圖3
????D、Java程序和數據庫之間
????對于幾乎所有數據庫的JDBC驅動程序,默認的在JAVA程序和數據庫之間傳遞數據都是以ISO-8859-1為默認編碼格式的,所以,我們的程序在向數據庫內存儲包含中文的數據時,JDBC首先是把程序內部的UNICODE編碼格式的數據轉化為ISO-8859-1的格式,然后傳遞到數據庫中,在數據庫保存數據時,它默認即以ISO-8859-1保存,所以,這是為什么我們常常在數據庫中讀出的中文數據是亂碼。
????對于JAVA程序和數據庫之間的數據傳遞,我們可以用圖4清晰地表示出來
圖4
????3、分析常見的JAVA中文問題幾個必須清楚的原則
????首先,經過上面的詳細分析,我們可以清晰地看到,任何JAVA程序的生命期中,其編碼轉換的關鍵過程是在于:最初編譯成class文件的轉碼和最終向用戶輸出的轉碼過程。
????其次,我們必須了解JAVA在編譯時支持的、常用的編碼格式有以下幾種:
????*ISO-8859-1,8-bit, 同8859_1,ISO-8859-1,ISO_8859_1等編碼
????*Cp1252,美國英語編碼,同ANSI標準編碼
????*UTF-8,同unicode編碼
????*GB2312,同gb2312-80,gb2312-1980等編碼
????*GBK , 同MS936,它是gb2312的擴充
????及其它的編碼,如韓文、日文、繁體中文等。同時,我們要注意這些編碼間的兼容關體系如下:
????unicode和UTF-8編碼是一一對應的關系。GB2312可以認為是GBK的子集,即GBK編碼是在gb2312上擴展來的。同時,GBK編碼包含了20902個漢字,編碼范圍為:0x8140-0xfefe,所有的字符可以一一對應到UNICODE2.0中來。
????再次,對于放在操作系統中的.java源程序文件,在編譯時,我們可以指定它內容的編碼格式,具體來說用-encoding來指定。注意:如果源程序中含有中文字符,而你用-encoding指定為其它的編碼字符,顯然是要出錯的。用-encoding指定源文件的編碼方式為GBK或gb2312,無論我們在什么系統上編譯含有中文字符的JAVA源程序都不會有問題,它都會正確地將中文轉化為UNICODE存儲在class文件中。
????
然后,我們必須清楚,幾乎所有的WEB容器在其內部默認的字符編碼格式都是以ISO-8859-1為默認值的,同時,幾乎所有的瀏覽器在傳遞參數時都是默認以UTF-8的方式來傳遞參數的。所以,雖然我們的Java源文件在出入口的地方指定了正確的編碼方式,但其在容器內部運行時還是以ISO-8859-1來處理的。
?
???4、中文問題的分類及其建議最優解決辦法
????了解以上JAVA處理文件的原理之后,我們就可以提出了一套建議最優的解決漢字問題的辦法。
????我們的目標是:我們在中文系統中編輯的含有中文字符串或進行中文處理的JAVA源程序經編譯后可以移值到任何其它的操作系統中正確運行,或拿到其它操作系統中編譯后能正確運行,能正確地傳遞中文和英文參數,能正確地和數據庫交流中英文字符串。
????我們的具體思路是:在JAVA程序轉碼的入口和出口及JAVA程序同用戶有輸入輸出轉換的地方限制編碼方法使之正確即可。
????具體解決辦法如下:
????1、 針對直接在console上運行的類
????對于這種情況,我們建議在程序編寫時,如果需要從用戶端接收用戶的可能含有中文的輸入或含有中文的輸出,程序中應該采用字符流來處理輸入和輸出,具體來說,應用以下面向字符型節點流類型:
????對文件:FileReader,FileWrieter
????????其字節型節點流類型為:FileInputStream,FileOutputStream
????對內存(數組):CharArrayReader,CharArrayWriter
????????其字節型節點流類型為:ByteArrayInputStream,ByteArrayOutputStream
????對內存(字符串):StringReader,StringWriter
????對管道:PipedReader,PipedWriter
????????其字節型節點流類型為:PipedInputStream,PipedOutputStream
????同時,應該用以下面向字符型處理流來處理輸入和輸出:
????BufferedWriter,BufferedReader
????????其字節型的處理流為:BufferedInputeStream,BufferedOutputStream
????InputStreamReader,OutputStreamWriter
????其字節型的處理流為:DataInputStream,DataOutputStream
????其中InputStreamReader和InputStreamWriter用于將字節流按照指定的字符編碼集轉換到字符流,如:
????InputStreamReader in = new InputStreamReader(System.in,"GB2312");
????OutputStreamWriter out = new OutputStreamWriter (System.out,"GB2312");
????例如:采用如下的示例JAVA編碼就達到了要求:
//Read.java
import java.io.*;
public class Read {
public static void main(String[] args) throws IOException {
String str = "\n中文測試,這是內部硬編碼的串"+"\ntest english character";
String strin= "";
BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in,"gb2312")); //設置輸入接口按中文編碼
BufferedWriter stdout = new BufferedWriter(new OutputStreamWriter(System.out,"gb2312")); //設置輸出接口按中文編碼
stdout.write("請輸入:");
stdout.flush();
strin = stdin.readLine();
stdout.write("這是從用戶輸入的串:"+strin);
stdout.write(str);
stdout.flush();
}}
????同時,在編譯程序時,我們用以下方式來進行:
????javac -encoding gb2312 Read.java
????其運行結果如圖5所示:
????圖5
????2、 針對EJB類和不可以直接運行的支持類(如JavaBean類)
????由于這種類它們本身被其它的類調用,不直接與用戶交互,故對這種類來說,我們的建議的處理方式是內部程序中應該采用字符流來處理程序內部的中文字符串(具體如上面一節中一樣),同時,在編譯類時用-encoding gb2312參數指示源文件是中文格式編碼的即可。
????3、 針對Servlet類
????針對Servlet,我們建議用以下方法:
????在編譯Servlet類的源程序時,用-encoding指定編碼為GBK或GB2312,且在向用戶輸出時的編碼部分用response對象的setContentType("text/html;charset=GBK");或gb2312來設置輸出編碼格式,同樣在接收用戶輸入時,我們用request.setCharacterEncoding("GB2312");這樣無論我們的servlet類移植到什么操作系統中,只有客戶端的瀏覽器支持中文顯示,就可以正確顯示。如下是一個正確的示例:
//HelloWorld.java
package hello;
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
public class HelloWorld extends HttpServlet
{
public void init() throws ServletException { }
public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
{
request.setCharacterEncoding("GB2312"); //設置輸入編碼格式
response.setContentType("text/html;charset=GB2312"); //設置輸出編碼格式
PrintWriter out = response.getWriter(); //建議使用PrintWriter輸出
out.println("< hr >");
out.println("Hello World! This is created by Servlet!測試中文!");
out.println("< hr >");
}
public void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
{
request.setCharacterEncoding("GB2312"); //設置輸入編碼格式
response.setContentType("text/html;charset=GB2312"); //設置輸出編碼格式
String name = request.getParameter("name");
String id = request.getParameter("id");
if(name==null) name="";
if(id==null) id="";
PrintWriter out = response.getWriter(); //建議使用PrintWriter輸出
out.println("< hr >");
out.println("你傳入的中文字串是:" + name);
out.println("< hr >你輸入的id是:" + id);
out.println("< hr >");
}
public void destroy() { }
}
??? 請用javac -encoding gb2312 HelloWorld.java來編譯此程序。
??? 測試此Servlet的程序如下所示:
< %@page contentType="text/html; charset=gb2312"% >
< %request.setCharacterEncoding("GB2312");% >
< html >< head >< title >< /title >
< Script language="JavaScript" >
function Submit() {
//通過URL傳遞中文字符串值給Servlet
document.base.action = "./HelloWorld?name=中文";
document.base.method = "POST";
document.base.submit();
}
< /Script >
< /head >
< body bgcolor="#FFFFFF" text="#000000" topmargin="5" >
< form name="base" method = "POST" target="_self" >
< input name="id" type="text" value="" size="30" >
< a href = "JavaScript:Submit()" >傳給Servlet< /a >
< /form >< /body >< /html >
??? 其運行結果如圖6所示:
????圖6
????4、 JAVA程序和數據庫之間
????為避免JAVA程序和數據庫之間數據傳遞出現亂碼現象,我們建議采用以下最優方法來處理:
????1、 對于JAVA程序的處理方法按我們指定的方法處理。
????2、 把數據庫默認支持的編碼格式改為GBK或GB2312的。
????如:在mysql中,我們可以在配置文件my.ini中加入以下語句實現:
????在[mysqld]區增加:
????default-character-set=gbk
????并增加:
????[client]
????default-character-set=gbk
????在SQL Server2K中,我們可以將數據庫默認的語言設置為Simplified Chinese來達到目的。
????5、 針對JSP代碼
????由于JSP是在運行時,由WEB容器進行動態編譯的,如果我們沒有指定JSP源文件的編碼格式,則JSP編譯器會獲得服務器操作系統的file.encoding值來對JSP文件編譯的,它在移植時最容易出問題,如在中文win2k中可以很好運行的jsp文件拿到英文linux中就不行,盡管客戶端都是一樣的,那是因為容器在編譯JSP文件時獲取的操作系統的編碼不同造成的(在中文wink中的file.encoding和在英文Linux中file.encoding是不同的,且英文Linux的file.encoding對中文不支持,所以編譯出來的JSP類就會有問題)。網絡上討論的大多數是此類問題,多是因為JSP文件移植平臺時不能正確顯示的問題,對于這類問題,我們了解了JAVA中程序編碼轉換的原理,解決起來就容易多了。我們建議的解決辦法如下:
????1、我們要保證JSP向客戶端輸出時是采用中文編碼方式輸出的,即無論如何我們首先在我們的JSP源代編中加入以下一行:
? < %@page contentType="text/html; charset=gb2312"% >
??? 2、為了讓JSP能正確獲得傳入的參數,我們在JSP源文件頭加入下面一句:
??? < %request.setCharacterEncoding("GB2312");% >
??? 3、為了讓JSP編譯器能正確地解碼我們的含有中文字符的JSP文件,我們需要在JSP源文件中指定我們的JSP源文件的編碼格式,具體來說,我們在JSP源文件頭上加入下面的一句即可:
??? < %@page pageEncoding="GB2312"% >或< %@page pageEncoding="GBK"% >
??? 這是JSP規范2.0新增加的指令。
??? 我們建議使用此方法來解JSP文件中的中文問題,下面的代碼是一個正確做法的JSP文件的測試程序:
//testchinese.jsp
< %@page pageEncoding="GB2312"% >
< %@page contentType="text/html; charset=gb2312"% >
< %request.setCharacterEncoding("GB2312");% >
< %
String action = request.getParameter("ACTION");
String name = "";
String str = "";
if(action!=null && action.equals("SENT"))
{
name = request.getParameter("name");
str = request.getParameter("str");
}
% >
< html >
< head >
< title >< /title >
< Script language="JavaScript" >
function Submit()
{
document.base.action = "?ACTION=SENT&str=傳入的中文";
document.base.method = "POST";
document.base.submit();
}
< /Script >
< /head >
< body bgcolor="#FFFFFF" text="#000000" topmargin="5" >
< form name="base" method = "POST" target="_self" >
< input type="text" name="name" value="" size="30" >
< a href = "JavaScript:Submit()" >提交< /a >
< /form >
< %
if(action!=null && action.equals("SENT"))
{
out.println("< br >你輸入的字符為:"+name);
out.println("< br >你通過URL傳入的字符為:"+str);
}
% >
< /body >
< /html >
??? 如圖7是此程序運行的結果示意圖:
????圖7
????5、總結
????在上面的詳細分析中,我們清晰地給出了JAVA在處理源程序過程中的詳細轉換過程,為我們正確解決JAVA編程中的中文問題提供了基礎。同時,我們給出了認為是最優的解決JAVA中文問題的辦法。
????6、參考資料
????1、段明輝.Java 編程技術中漢字問題的分析及解決.
????????http://www-900.ibm.com/developerWorks/cn/java/java_chinese/index.shtml
????2、 周競濤.關于Java中文問題的幾條分析原則
????????http://www-900.ibm.com/developerWorks/cn/java/l-javachinese/index.shtml
????7、作者介紹
????????作者:abnerchai,高級程序員,作者聯系方法:josserchai@yahoo.com
???
為了實現web層(struts)和持久層(Hibernate)之間的松散耦合,我們采用業務代表(Business Delegate)和DAO(Data Access Object)兩種模式。DAO模式為了減少業務邏輯和數據訪問邏輯之間的耦合,當一個持久曾框架被應用時,該模式將會減少業務對象和該框架之間的耦合,這樣我們可以不修改業務對象而選擇不同的持久層框架的實現。實際上在DAO模式中包含兩種結構模式:橋(Bridge)模式和適配器(Adaptor)模式。?
對表現層,我們使用
Struts
;業務層使用
Spring
;對于持久層我們使用的是
Hibernate
。你盡可以取代這里的某個框架而使用你喜歡的框架已達到同樣的效果。下圖顯示了框架被整合起來時,從最高層次看到的視圖。
應用層
??? 許多設計良好的web應用,可以被按職責分為四層。這些層次是表現層、持久層、業務層、和領域模型層。每一個層次都有其獨特的職責,不能把各自的功能與其它層次相混合。每一個應用層都應該和其它層隔離開來,但允許使用接口在層間進行通信。我們開始來看看每個層,并討論一下它們各自都應該提供什么和不應該提供什么。
表現層
??? 一個典型的web 應用的末端是表現層。許多Java 開發者都知道Struts提供了什么東西。然而,太多時候,耦合代碼比如業務邏輯被放進org.apache.struts.Action中。所以,我們先總結一下Struts之類的框架應該提供什么。下面就是Struts 的職責所在:
-
管理用戶的請求和響應
-
提供一個控制起來將調用委托到業務邏輯和其他上游處理
-
將來自于拋出例外的其他層的例外處理到Struts Action 中
-
組裝可以在視圖中表現的模型對象
-
執行UI 校驗
下面是一些經常可以使用Struts進行編碼但是不應該和表現層關聯的事情:
-
直接和數據庫交互,比如JDBC 調用
-
與應用相關的業務邏輯和校驗
-
事務管理
在表現層中引入這些類型的代碼將導致類型耦合和維護負擔。
持久層
??? 一個典型Web應用的另一端是持久層。這也是應用中最容易很快失控的地方。開發者通常低估了自己構建自己的持久層框架的挑戰。一個定制的,內部開發的持久層不僅需要大量的開發時間,并且通常缺乏功能和難以管理。目前有許多解決這些問題的開源對象關系映射 (ORM) 框架。特別地,Hibernate 框架就允許Java中的對象-關系的持久性和查詢服務。Hibernate 對已經熟悉了SQL 和JDBC API的Java開發者來或具有中度的學習曲線。Hibernate 的持久對象基于POJO和Java群集(collections)。此外,使用Hibernate 不和你的IDE接口。下面列出了你需要在持久性框架中編寫的代碼類型:
-
查詢關系信息到對象中。Hibernate是通過稱為HQL的OO查詢語言,或者使用更有表現能力的規則API,來完成這個工作的。除了使用對象而不是表,使用字段而不是列的方式,HQL非常類似于 SQL。也有一些新的特定的HQL 語言特征需要學習;但是,它們是很容易理解和良好編寫的。HQL是一種用于查詢對象的自然語言,而對象,只需要很少的學習曲線吧。.
-
存儲、更新和刪除存儲在數據庫中的信息
-
高級的對象關系映射框架比如Hibernate支持大部分主流SQL數據庫,它們支持父/子關系,事務,繼承和多態。
下面是應該在持久層避免的一些事情:
-
業務邏輯應該置于應用的更高層中。這里只允許數據訪問方法。
-
不應該使持久邏輯和表現邏輯耦合。避免表現組件如JSP或者基于servlet的類中的邏輯直接和數據訪問進行通信。通過將持久性邏輯隔離在其自己的層中,應用將具有更加靈活的修改性而不影響到其他層的代碼。例如, Hibernate可以使用其他持久框架和API代替,而不需要修改其它層中的代碼。
業務層應該負責下面的問題:
-
處理應用的業務邏輯和業務校驗
-
管理事務
-
允許與其他層進行交互的接口
-
管理業務級對象之間的依賴性
-
加入了表現和持久層之間的靈活性,以便它們不需要彼此進行直接通信
-
從表現層暴露上下文給業務層以獲得業務服務
-
管理從業務層到表現層的實現
POJO = pure old Java object POJO有一些private的參數作為對象的屬性。然后針對每個參數定義了get和set方法作為訪問的接口。例如: public class User {
private long id;
private String name;
public void setId(long id) {
this.id = id;
}
public void setName(String name) {
this.name=name;
}
public long getId() {
return id;
}
public String getName() {
return name;
}
}
POJO對象有時也被稱為Data對象,大量應用于表現現實中的對象。