tory320

            BlogJava :: 首頁 :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理 ::
            10 隨筆 :: 0 文章 :: 1 評(píng)論 :: 0 Trackbacks

          2006年12月25日 #

          Design Principle
          Identify the aspects of your application that vary and separate them from what stays the same.
          Here's another way to think about this principle: take the parts that vary and encapsulate them, so that later you can alter or extends the parts that vary without affecting those that don't.
          As simple as this concept is, it forms the basis for almost every design pattern. All patterns provide a way to let some part of a system vary independently of all other parts.

          Each set of class will hold all the implementations of their respective behavior. For instance, we might have one clss that implements quarking, another implements squaking, and another that implements silence.

          To separate thest behaviors from the Duck class, we'll pull both methods out of the duck class and create a new set of class to represent each behavior.

          This is in contrast to the way we were doing things before, where a behavior either came from a concrete implementation in the suprerclass Duck, or by providing a specialized implementation in the sub class itself. In both cases we were relying on an implementation. We were locked into using that specific implemetation and there was no room for changing out the behavior.

          And the same is true for the duck's flying behavior.

          Okay, now that we've done the deep dive on the duck simulator design, it's time to come back up for air and take a look at the big picture.

          Below is the entire reworked class structure. We have everything you'd expect: ducks extending Duck. fly behavior implementing FlyBehavior and quack behavior implementing QuackBehavior.

          Notice also that we've started to describe things a little differntly. Instead of thinking of the duck behaviors as a set of behaviors, we'll start thinking of them ad a family of algorithms. Think about it: in the SimUDuck design, the algorithms represent things a duck would do , but we could just as easily use the same techniques for a set of classes that implement the ways to compute state sales tax by different states.

          posted @ 2008-03-07 17:58 tory 閱讀(137) | 評(píng)論 (0)編輯 收藏

          /**
          ?* //FileOperate.java
          ?* 文件的各種操作
          ?* 楊彩 http://blog.sina.com.cn/m/yangcai
          ?* 文件操作 1.0
          ?*/
          ?
          //package common;
          ?
          import java.io.*;
          ?
          public class FileOperate
          {
          ?static boolean exitnow=false;
          ?static String aa,bb;
          ? public FileOperate() {
          ? }
          ?
          ? /**
          ?? * 新建目錄
          ?? */
          ? public void newFolder(String folderPath) {
          ??? try
          ??? {
          ????? String filePath = folderPath;
          ????? filePath = filePath.toString();
          ????? File myFilePath = new File(filePath);
          ????? if(!myFilePath.exists())
          ????? {
          ??????? myFilePath.mkdir();
          ????? }
          ????? System.out.println("新建目錄操作 成功執(zhí)行");
          ??? }
          ??? catch(Exception e)
          ??? {
          ????? System.out.println("新建目錄操作出錯(cuò)");
          ????? e.printStackTrace();
          ??? }
          ? }
          ?
          ? /**
          ?? * 新建文件
          ?? */
          ? public void newFile(String filePathAndName, String fileContent)
          ? {
          ?
          ??? try
          ??? {
          ????? String filePath = filePathAndName;
          ????? filePath = filePath.toString();
          ????? File myFilePath = new File(filePath);
          ????? if (!myFilePath.exists())
          ????? {
          ??????? myFilePath.createNewFile();
          ????? }
          ????? FileWriter resultFile = new FileWriter(myFilePath);
          ????? PrintWriter myFile = new PrintWriter(resultFile);
          ????? String strContent = fileContent;
          ????? myFile.println(strContent);
          ????? resultFile.close();
          ????? System.out.println("新建文件操作 成功執(zhí)行");
          ??? }
          ??? catch (Exception e) {
          ????? System.out.println("新建目錄操作出錯(cuò)");
          ????? e.printStackTrace();
          ?
          ??? }
          ?
          ? }
          ?
          ? /**
          ?? * 刪除文件
          ?? */
          ? public void delFile(String filePathAndName) {
          ??? try {
          ????? String filePath = filePathAndName;
          ????? filePath = filePath.toString();
          ????? File myDelFile = new File(filePath);
          ????? myDelFile.delete();
          ????? System.out.println("刪除文件操作 成功執(zhí)行");
          ??? }
          ??? catch (Exception e) {
          ????? System.out.println("刪除文件操作出錯(cuò)");
          ????? e.printStackTrace();
          ?
          ??? }
          ?
          ? }
          ?
          ? /**
          ?? * 刪除文件夾
          ?? */
          ? public void delFolder(String folderPath)
          ? {
          ??? try
          ??? {
          ????? delAllFile(folderPath); //刪除完里面所有內(nèi)容
          ????? String filePath = folderPath;
          ????? filePath = filePath.toString();
          ????? File myFilePath = new File(filePath);
          ????? myFilePath.delete(); //刪除空文件夾
          ????? System.out.println("刪除文件夾操作 成功執(zhí)行");
          ??? }
          ??? catch (Exception e)
          ??? {
          ????? System.out.println("刪除文件夾操作出錯(cuò)");
          ????? e.printStackTrace();
          ?
          ??? }
          ?
          ? }
          ?
          ? /**
          ?? * 刪除文件夾里面的所有文件
          ?? * @param path String 文件夾路徑 如 c:/fqf
          ?? */
          ? public void delAllFile(String path)
          ? {
          ??? File file = new File(path);
          ??? if(!file.exists())
          ??? {
          ????? return;
          ??? }
          ??? if(!file.isDirectory())
          ??? {
          ????? return;
          ??? }
          ??? String[] tempList = file.list();
          ??? File temp = null;
          ??? for (int i = 0; i < tempList.length; i++)
          ??? {
          ????? if(path.endsWith(File.separator))
          ????? {
          ??????? temp = new File(path + tempList[i]);
          ????? }
          ????? else
          ????? {
          ??????? temp = new File(path + File.separator + tempList[i]);
          ????? }
          ????? if (temp.isFile())
          ????? {
          ??????? temp.delete();
          ????? }
          ????? if (temp.isDirectory())
          ????? {
          ??????? delAllFile(path+"/"+ tempList[i]);//先刪除文件夾里面的文件
          ??????? delFolder(path+"/"+ tempList[i]);//再刪除空文件夾
          ????? }
          ??? }
          ????????? System.out.println("刪除文件操作 成功執(zhí)行");?
          ? }
          ?
          ? /**
          ?? * 復(fù)制單個(gè)文件
          ?? * @param oldPath String 原文件路徑 如:c:/fqf.txt
          ?? * @param newPath String 復(fù)制后路徑 如:f:/fqf.txt
          ?? */
          ? public void copyFile(String oldPath, String newPath) {
          ??? try {
          ????? int bytesum = 0;
          ????? int byteread = 0;
          ????? File oldfile = new File(oldPath);
          ????? if (oldfile.exists())
          ????? { //文件存在時(shí)
          ??????? InputStream inStream = new FileInputStream(oldPath); //讀入原文件
          ??????? FileOutputStream fs = new FileOutputStream(newPath);
          ??????? byte[] buffer = new byte[1444];
          ??????? int length;
          ??????? while ( (byteread = inStream.read(buffer)) != -1) {
          ????????? bytesum += byteread; //字節(jié)數(shù) 文件大小
          ????????? System.out.println(bytesum);
          ????????? fs.write(buffer, 0, byteread);
          ??????? }
          ??????? inStream.close();
          ????? }
          ??????????? System.out.println("刪除文件夾操作 成功執(zhí)行");?
          ??? }
          ??? catch (Exception e) {
          ????? System.out.println("復(fù)制單個(gè)文件操作出錯(cuò)");
          ????? e.printStackTrace();
          ?
          ??? }
          ?
          ? }
          ?
          ? /**
          ?? * 復(fù)制整個(gè)文件夾內(nèi)容
          ?? * @param oldPath String 原文件路徑 如:c:/fqf
          ?? * @param newPath String 復(fù)制后路徑 如:f:/fqf/ff
          ?? */
          ? public void copyFolder(String oldPath, String newPath) {
          ?
          ??? try
          ??? {
          ????? (new File(newPath)).mkdirs(); //如果文件夾不存在 則建立新文件夾
          ????? File a=new File(oldPath);
          ????? String[] file=a.list();
          ????? File temp=null;
          ????? for (int i = 0; i < file.length; i++)
          ????? {
          ??????? if(oldPath.endsWith(File.separator))
          ??????? {
          ????????? temp=new File(oldPath+file[i]);
          ??????? }
          ??????? else{
          ????????? temp=new File(oldPath+File.separator+file[i]);
          ??????? }
          ?
          ??????? if(temp.isFile())
          ??????? {
          ????????? FileInputStream input = new FileInputStream(temp);
          ????????? FileOutputStream output = new FileOutputStream(newPath + "/" +
          ????????????? (temp.getName()).toString());
          ????????? byte[] b = new byte[1024 * 5];
          ????????? int len;
          ????????? while ( (len = input.read(b)) != -1)
          ????????? {
          ??????????? output.write(b, 0, len);
          ????????? }
          ????????? output.flush();
          ????????? output.close();
          ????????? input.close();
          ??????? }
          ??????? if(temp.isDirectory())
          ??????? {//如果是子文件夾
          ????????? copyFolder(oldPath+"/"+file[i],newPath+"/"+file[i]);
          ??????? }
          ????? }
          ??????????? System.out.println("復(fù)制文件夾操作 成功執(zhí)行");?
          ??? }
          ??? catch (Exception e) {
          ????? System.out.println("復(fù)制整個(gè)文件夾內(nèi)容操作出錯(cuò)");
          ????? e.printStackTrace();
          ?
          ??? }
          ?
          ? }
          ?
          ? /**
          ?? * 移動(dòng)文件到指定目錄
          ?? * @param oldPath String 如:c:/fqf.txt
          ?? * @param newPath String 如:d:/fqf.txt
          ?? */
          ? public void moveFile(String oldPath, String newPath) {
          ??? copyFile(oldPath, newPath);
          ??? delFile(oldPath);
          ?
          ? }
          ?
          ? /**
          ?? * 移動(dòng)文件到指定目錄
          ?? * @param oldPath String 如:c:/fqf.txt
          ?? * @param newPath String 如:d:/fqf.txt
          ?? */
          ? public void moveFolder(String oldPath, String newPath) {
          ??? copyFolder(oldPath, newPath);
          ??? delFolder(oldPath);
          ?
          ? }
          ?
          ? public static void main(String args[])
          ? {
          ? ?System.out.println("使用此功能請(qǐng)按[1]? 功能一:新建目錄");
          ? ?System.out.println("使用此功能請(qǐng)按[2]? 功能二:新建文件");
          ? ?System.out.println("使用此功能請(qǐng)按[3]? 功能三:刪除文件");
          ? ?System.out.println("使用此功能請(qǐng)按[4]? 功能四:刪除文件夾");
          ? ?System.out.println("使用此功能請(qǐng)按[5]? 功能五:刪除文件夾里面的所有文件");
          ? ?System.out.println("使用此功能請(qǐng)按[6]? 功能六:復(fù)制文件");
          ? ?System.out.println("使用此功能請(qǐng)按[7]? 功能七:復(fù)制文件夾的所有內(nèi)容");
          ? ?System.out.println("使用此功能請(qǐng)按[8]? 功能八:移動(dòng)文件到指定目錄");
          ? ?System.out.println("使用此功能請(qǐng)按[9]? 功能九:移動(dòng)文件夾到指定目錄");
          ? ?System.out.println("使用此功能請(qǐng)按[10] 退出程序");
          ? ?
          ?while(!exitnow)
          ?{
          ? ??FileOperate fo=new FileOperate();
          ? ??try
          ? ??{
          ? ??BufferedReader Bin=new BufferedReader(new InputStreamReader(System.in));
          ? ??String a=Bin.readLine();
          ? ??int b=Integer.parseInt(a);
          ? ??
          ? ??switch(b)
          ? ??{
          ? ???case 1:System.out.println("你選擇了功能一? 請(qǐng)輸入目錄名");??
          ? ????? aa=Bin.readLine();
          ? ????? fo.newFolder(aa);
          ? ????? break;
          ? ???case 2:System.out.println("你選擇了功能二? 請(qǐng)輸入文件名");??
          ? ????? aa=Bin.readLine();
          ? ????? System.out.println("請(qǐng)輸入在"+aa+"中的內(nèi)容");
          ? ????? bb=Bin.readLine();
          ? ????? fo.newFile(aa,bb);
          ? ????? break;
          ? ???case 3:System.out.println("你選擇了功能三? 請(qǐng)輸入文件名");??
          ? ????? aa=Bin.readLine();
          ? ????? fo.delFile(aa);
          ? ????? break;
          ? ???case 4:System.out.println("你選擇了功能四? 請(qǐng)輸入文件名");??
          ? ????? aa=Bin.readLine();
          ? ????? fo.delFolder(aa);
          ? ????? break;
          ? ???case 5:System.out.println("你選擇了功能五? 請(qǐng)輸入文件名");??
          ? ????? aa=Bin.readLine();
          ? ????? fo.delAllFile(aa);
          ? ????? break;??
          ? ???case 6:System.out.println("你選擇了功能六? 請(qǐng)輸入文件名");??
          ? ????? aa=Bin.readLine();
          ? ????? System.out.println("請(qǐng)輸入目標(biāo)文件名");?
          ? ????? bb=Bin.readLine();
          ? ????? fo.copyFile(aa,bb);
          ? ????? break;
          ? ???case 7:System.out.println("你選擇了功能七? 請(qǐng)輸入源文件名");??
          ? ????? aa=Bin.readLine();
          ? ????? System.out.println("請(qǐng)輸入目標(biāo)文件名");?
          ? ????? bb=Bin.readLine();
          ? ????? fo.copyFolder(aa,bb);
          ? ????? break;? ?????
          ? ???case 8:System.out.println("你選擇了功能八? 請(qǐng)輸入源文件名");??
          ? ????? aa=Bin.readLine();
          ? ????? System.out.println("請(qǐng)輸入目標(biāo)文件名");?
          ? ????? bb=Bin.readLine();
          ? ????? fo.moveFile(aa,bb);
          ? ????? break;
          ? ??? ?case 9:System.out.println("你選擇了功能九? 請(qǐng)輸入源文件名");??
          ? ????? aa=Bin.readLine();
          ? ????? System.out.println("請(qǐng)輸入目標(biāo)文件名");?
          ? ????? bb=Bin.readLine();
          ? ????? fo.moveFolder(aa,bb);
          ? ????? break;? ?????
          ? ???case 10:exitnow=true;
          ? ?????? System.out.println("程序結(jié)束,請(qǐng)退出");
          ? ????? break;
          ? ???default:System.out.println("輸入錯(cuò)誤.請(qǐng)輸入1-10之間的數(shù)");?? ???? ????? ?
          ? ?? }
          ? ??
          ? ??
          ? ??System.out.println("請(qǐng)重新選擇功能");
          ? ??
          ? ??
          ? ??}
          ? ??catch(Exception e)
          ? ??{
          ? ??System.out.println("輸入錯(cuò)誤字符或程序出錯(cuò)");
          ? ??}
          ? ??
          ?}? ?
          ?}
          }
          posted @ 2007-01-30 13:03 tory 閱讀(188) | 評(píng)論 (0)編輯 收藏

          本文是在參閱了http://ivanl.javaeye.com/blog/24739基礎(chǔ)上完成的
          在看JPetStore的代碼時(shí),發(fā)現(xiàn)它的分頁處理主要是通過返回PaginatedList對(duì)象來完成的。如:在CatalogService類中
          public?PaginatedList?getProductListByCategory(String?categoryId)?{?
          ????
          return?productDao.getProductListByCategory(categoryId);?
          ??}
          ?

          分頁是操作數(shù)據(jù)庫型系統(tǒng)常遇到的問題。分頁實(shí)現(xiàn)方法很多,但效率的差異就很大了。iBatis是通過什么方式來實(shí)現(xiàn)這個(gè)分頁的了。查看它的實(shí)現(xiàn)部分:
          ?
          返回的PaginatedList實(shí)際上是個(gè)接口,實(shí)現(xiàn)這個(gè)接口的是PaginatedDataList類的對(duì)象,查看PaginatedDataList類發(fā)現(xiàn),每次翻頁的時(shí)候最后都會(huì)調(diào)用下面這段函數(shù)
          private?List?getList(int?idx,?int?localPageSize)?throws?SQLException?{?
          ????
          return?sqlMapExecutor.queryForList(statementName,?parameterObject,?(idx)?*?pageSize,?localPageSize);?
          ??}
          ?
          由于
          public?interface?SqlMapClient?extends?SqlMapExecutor,?SqlMapTransactionManager?{……}?

          所以實(shí)際的調(diào)用次序如下:
          SqlMapClientImpl.queryForPaginatedList->SqlMapSessionImpl.queryForPaginatedList?
          ->SqlMapExecutorDelegate.queryForPaginatedList->GeneralStatement.executeQueryForList?
          ->GeneralStatment.executeQueryWithCallback->GeneralStatment.executeQueryWithCallback?
          ->SqlExecutor.executeQuery->SqlExecutor.handleMultipleResults()->SqlExecutor.executeQuery->?handleResults?
          分頁處理的函數(shù)如下
          private?void?handleResults(RequestScope?request,?ResultSet?rs,?int?skipResults,?int?maxResults,?RowHandlerCallback?callback)?throws?SQLException?{?
          ????
          try?{?
          ??????request.setResultSet(rs);?
          ??????ResultMap?resultMap?
          =?request.getResultMap();?
          ??????
          if?(resultMap?!=?null)?{?
          ????????
          //?Skip?Results?
          ????????if?(rs.getType()?!=?ResultSet.TYPE_FORWARD_ONLY)?{?
          ??????????
          if?(skipResults?>?0)?{?
          ????????????rs.absolute(skipResults);?
          ??????????}
          ?
          ????????}
          ?else?{?
          ??????????
          for?(int?i?=?0;?i?<?skipResults;?i++)?{?
          ????????????
          if?(!rs.next())?{?
          ??????????????
          return;?
          ????????????}
          ?
          ??????????}
          ?
          ????????}
          ?
          ??
          ????????
          //?Get?Results?
          ????????int?resultsFetched?=?0;?
          ????????
          while?((maxResults?==?SqlExecutor.NO_MAXIMUM_RESULTS?||?resultsFetched?<?maxResults)?&&?rs.next())?{?
          ??????????Object[]?columnValues?
          =?resultMap.resolveSubMap(request,?rs).getResults(request,?rs);?
          ??????????callback.handleResultObject(request,?columnValues,?rs);?
          ??????????resultsFetched
          ++;?
          ????????}
          ?
          ??????}
          ?
          ????}
          ?finally?{?
          ??????request.setResultSet(
          null);?
          ????}
          ?
          ??}
          ?

          由此可見,iBatis的分頁主要依賴于jdbcdriver的如何實(shí)現(xiàn)以及是否支持rs.absolute(skipResults)。它并不是一個(gè)好的分頁方式。它先要取出所有的符合條件的記錄存入ResultSet對(duì)象,然后用absolute方法進(jìn)行定位,來實(shí)現(xiàn)分頁。當(dāng)記錄數(shù)較大(比如十萬條)時(shí),整體的查詢速度將會(huì)變得很慢。
          所以分頁還是要考慮采用直接操作sql語句來完成。當(dāng)然小批量的可以采用iBatis的分頁模式。一般分頁的sql語句與數(shù)據(jù)庫的具體實(shí)現(xiàn)有關(guān)
          mysql:?
          select?*?from?A?limit?startRow,endRow?
          oracle:?
          select?b.*?from?(select?a.*,rownum?as?linenum?from?(select?*?from?A)?a?where?rownum?<=?endRow)?b?where?linenum?>=?startRow?

          Hibernate的Oracle分頁采用的就是是拼湊RowNum的Sql語句來完成的。參考代碼如下:?
          ?
          ????????public?String?createOraclePagingSql(String?sql,?int?pageIndex,?int?pageSize){?
          ????????????
          int?m?=?pageIndex?*?pageSize;?
          ????????????
          int?n?=?m?+?pageSize;?
          ????????????
          return?"select?*?from?(?select?row_.*,?rownum?rownum_?from?(?"?+?sql?
          ????????????????????
          +?"?)?row_?where?rownum?<=?"?+?n??
          ????????????????????
          +?")?where?rownum_?>?"?+?m;?
          ????????}
          ?
          綜上,小批量(<2w)可以采用ibatis自帶的分頁類,大批量的還是直接操縱sql,當(dāng)然也可以將這些sql自己進(jìn)行封裝,或在包中封裝都可以。包封裝的示例代碼如下:
          一個(gè)封裝了分頁功能的Oracle Package
          create?or?replace?package?body?FMW_FY_HELPER?is
          PROCEDURE?GET_DATA(pi_sql?in?varchar,pi_whichpage?in?integer,pi_rownum?in?integer,
          po_cur_data?out?cur_DATA,po_allrownum?out?
          integer,pio_succeed?in?out?integer)
          as?
          v_cur_data?cur_DATA;
          v_cur_temp?cur_TEMP;
          v_temp?
          integer;
          v_sql?
          varchar(5000);
          v_temp1?
          integer;
          v_temp2?
          integer;
          begin
          pio_succeed?:
          =?1;
          v_sql?:
          =?'select?count(''a'')?from?(?'?||?pi_sql?||?')';
          execute?immediate?v_sql?into?v_temp;

          po_allrownum:
          =ceil(v_temp/pi_rownum);

          v_sql?:
          =?'';
          v_temp?:
          =pi_whichpage*pi_rownum?+?1;
          v_temp1:
          =(pi_whichpage-1)*pi_rownum?+?1;
          v_temp2:
          =pi_whichpage*pi_rownum;
          v_sql:
          =?'select?*?from?(select?rownum?as?rn,t.*?from?('?||?pi_sql?||')?t?where?rownum<'?||?to_char(v_temp)?||?')??where?rn?between?'?||?to_char(v_temp1)?||?'?and?'?||?to_char(v_temp2);
          open?v_cur_data?for?v_sql;
          if?v_cur_data?%notfound
          then
          pio_succeed:
          =-1;
          return;
          end?if;
          po_cur_DATA?:
          =?v_cur_data;
          end;
          posted @ 2007-01-19 13:02 tory 閱讀(832) | 評(píng)論 (0)編輯 收藏

          使用JFreeChart生成熱點(diǎn)圖表
          2006-12-14 11:54
          <一>前言:

            JFreeChart是開放源代碼站點(diǎn)SourceForge.net上的一個(gè)JAVA項(xiàng)目。它的功能十分強(qiáng)大,能創(chuàng)建餅圖、柱狀圖(普通柱狀圖以及堆棧柱狀圖)、線圖、區(qū)域圖、分布圖、混合圖、甘特圖以及一些儀表盤等等,并可生成PNG或JPG圖片格式文件。
            本人在學(xué)習(xí)過程中發(fā)現(xiàn),網(wǎng)上很多文章都是講一些JFreeChart的基本應(yīng)用,而對(duì)JFreeChart生成熱點(diǎn)圖表這樣常用的功能雖有所提及卻沒有一個(gè)完整的例子,所以我就寫一個(gè)簡單示例供大家參考,希望對(duì)大家的學(xué)習(xí)有所幫助。?

            <二>示例說明:

            假設(shè)有一個(gè)關(guān)于程序員北京,上海,廣洲三地程序員學(xué)歷,開發(fā)語言,薪金情況的調(diào)查。首先要以餅圖顯示程序員學(xué)歷的分布情況(index.jsp)。點(diǎn)擊餅圖的每一部分會(huì)以柱狀圖顯示該層次程序員所用開發(fā)語言和薪金的情況(barview.jsp)。重點(diǎn)演示怎樣在餅圖上添加鏈接。?

            <三>準(zhǔn)備工作:

            1.下載最新版本的JFreeChart,當(dāng)前為jfreechart-1.0.0-rc1
          下載地址:http://www.jfree.org/jfreechart/index.html

            2.解壓文件,將jfreechart-1.0.0-rc1/lib下的jcommon-1.0.0-rc1.jar,jfreechart-1.0.0-rc1.jar復(fù)制到WEB應(yīng)用的lib目錄下。

            3.在web.xml文件中增加以下內(nèi)容:

          <servlet>?
          <servlet-name>DisplayChart</servlet-name>?
          <servlet-class>org.jfree.chart.servlet.DisplayChart</servlet-class>?
          </servlet>?
          <servlet-mapping>?
          <servlet-name>DisplayChart</servlet-name>?
          <url-pattern>/servletDisplayChart</url-pattern>?
          </servlet-mapping>?

            <四>餅圖頁面代碼(index.jsp)?


          <%@?page?contentType="text/html;charset=GBK"%>?
          <%@?page?import="org.jfree.data.general.DefaultPieDataset"%>?
          <%@?page?import="org.jfree.chart.*"%>?
          <%@?page?import="org.jfree.chart.plot.*"%>?
          <%@?page?import="org.jfree.chart.servlet.ServletUtilities"%>?
          <%@?page?import="org.jfree.chart.labels.StandardPieItemLabelGenerator"%>?
          <%@?page?import="org.jfree.chart.urls.StandardPieURLGenerator"%>?
          <%@?page?import="org.jfree.chart.entity.StandardEntityCollection"%>?
          <%@?page?import="java.io.*"%>?
          <HTML>?
          <HEAD>?
          <META?http-equiv=Content-Type?content="text/html;?charset=GBK">?
          <TITLE>nacl_zhuang@hotmail.com</TITLE>?
          </HEAD>?
          <BODY>?
          <%?

          DefaultPieDataset?data?=?new?DefaultPieDataset();?
          data.setValue("高中以下",370);?
          data.setValue("高中",1530);?
          data.setValue("大專",5700);?
          data.setValue("本科",8280);?
          data.setValue("碩士",4420);?
          data.setValue("博士",80);?

          PiePlot3D?plot?=?new?PiePlot3D(data);//3D餅圖?
          plot.setURLGenerator(new?StandardPieURLGenerator("barview.jsp"));//設(shè)定鏈接?
          JFreeChart?chart?=?new?JFreeChart("",JFreeChart.DEFAULT_TITLE_FONT,?plot,?true);?
          chart.setBackgroundPaint(java.awt.Color.white);//可選,設(shè)置圖片背景色?
          chart.setTitle("程序員學(xué)歷情況調(diào)查表");//可選,設(shè)置圖片標(biāo)題?
          plot.setToolTipGenerator(new?StandardPieItemLabelGenerator());?
          StandardEntityCollection?sec?=?new?StandardEntityCollection();?
          ChartRenderingInfo?info?=?new?ChartRenderingInfo(sec);?
          PrintWriter?w?=?new?PrintWriter(out);//輸出MAP信息?
          //500是圖片長度,300是圖片高度?
          String?filename?=?ServletUtilities.saveChartAsPNG(chart,?500,?300,?info,?session);?
          ChartUtilities.writeImageMap(w,?"map0",?info,?false);?

          String?graphURL?=?request.getContextPath()?+?"/servlet/DisplayChart?filename="?+?filename;?

          %>?

          <P?ALIGN="CENTER">?
          <img?src="<%=?graphURL?%>"?width=500?height=300?border=0?usemap="#map0">?
          </P>?
          </BODY>?
          </HTML>?

            生成的圖片如下


            在瀏覽器中點(diǎn)右鍵->查看源文件會(huì)發(fā)現(xiàn)有以下一段HTML代碼:?

          <map?id="map0"?name="map0">?
          <area?shape="poly"?coords="247,61,250,61,250,123,250,123"?title="博士?=?80"?alt=""?href="barview.jsp?category=博士&pieIndex=0"/>?
          <area?shape="poly"?coords="148,112,153,102,160,92,170,83,182,76,196,70,212,65,229,62,247,61,250,123,250,123"?title="碩士?=?4,420"?alt=""?href="barview.jsp?category=碩士&pieIndex=0"/>?
          <area?shape="poly"?coords="324,167,311,173,297,179,282,182,266,185,250,186,234,185,217,183,202,179,188,173,175,167,
           ?165,159,157,151,151,142,147,132,146,122,148,112,250,123,250,123"?title="本科?=?8,280"?alt=""?
           href="barview.jsp?category=本科&pieIndex=0"/>?
          <area?shape="poly"?coords="307,72,324,80,338,91,347,103,352,117,352,131,347,144,338,156,324,167,250,123,250,123"?title="大專?=?5,700"?alt=""?href="barview.jsp?category=大專&pieIndex=0"/>?
          <area?shape="poly"?coords="261,62,285,65,307,72,250,123,250,123"?title="高中?
           =?1,530"?alt=""?href="barview.jsp?category=高中&pieIndex=0"/>?
          <area?shape="poly"?coords="250,61,261,62,250,123,250,123"?title="高中以下?=?370"?alt=""?href="barview.jsp?category=高中以下&pieIndex=0"/>?
          </map>?


            這就是MAP信息,我們?cè)贗MG標(biāo)簽中加入usemap="#map0"就可以為餅圖的每一部分加入鏈接。

            <五>柱狀圖頁面代碼:(barview.jsp)

          <HTML>?
          <HEAD>?
          <META?http-equiv=Content-Type?content="text/html;?charset=GBK">?
          <TITLE>nacl_zhuang@hotmail.com</TITLE>?
          </HEAD>?

          <body>?

          <%@?page?contentType="text/html;charset=GBK"%>?
          <%@?page?import="org.jfree.chart.ChartFactory,?
          org.jfree.chart.JFreeChart,?
          org.jfree.chart.plot.PlotOrientation,?
          org.jfree.chart.servlet.ServletUtilities,?
          org.jfree.data.category.*"%>?
          <%?
          CategoryDataset?dataset;?
          String?category=request.getParameter("category");?
          category=?new?String(category.getBytes("ISO8859_1"),?"GBK");?
          if(category.equals("本科")||category.equals("高中")||category.equals("大專"))?
          {?
           dataset=getDataSet();?
          }?
          else?if(category.equals("碩士")||category.equals("博士"))?
          {?
           dataset=getDataSet2();?
          }else?
          {?
           dataset=getDataSet3();?
          }?
          String?title=category+"程序員在各城市薪金情況統(tǒng)計(jì)";?
          JFreeChart?chart?=?ChartFactory.createBarChart3D(title,?
          "城市",?
          "薪金",?
          dataset,?
          PlotOrientation.VERTICAL,?
          true,?
          false,?
          false);?

          String?filename?=?ServletUtilities.saveChartAsPNG(chart,?500,?300,?null,?session);?
          String?graphURL?=?request.getContextPath()?+?"/servlet/DisplayChart?filename="?+?filename;?
          %>?
          <P?ALIGN="CENTER">?
          <img?src="<%=?graphURL?%>"?width=500?height=300?border=0?usemap="#<%=?filename?%>">?
          </P>?
          <%!?
          private?static?CategoryDataset?getDataSet()?{?
           DefaultCategoryDataset?dataset?=?new?DefaultCategoryDataset();?
           dataset.addValue(2000,?"北京",?"VB");?
           dataset.addValue(1800,?"上海",?"VB");?
           dataset.addValue(2200,?"廣州",?"VB");?
           dataset.addValue(3200,?"北京",?"JAVA");?
           dataset.addValue(3500,?"上海",?"JAVA");?
           dataset.addValue(3600,?"廣州",?"JAVA");?
           dataset.addValue(3300,?"北京",?"DOT?NET");?
           dataset.addValue(3400,?"上海",?"DOT?NET");?
           dataset.addValue(3700,?"廣州",?"DOT?NET");?
           dataset.addValue(2500,?"北京",?"DELPHI");?
           dataset.addValue(2800,?"上海",?"DELPHI");?
           dataset.addValue(3200,?"廣州",?"DELPHI");?
           dataset.addValue(5000,?"北京",?"VC");?
           dataset.addValue(3500,?"上海",?"VC");?
           dataset.addValue(4600,?"廣州",?"VC");?
           return?dataset;?
          }?
          private?static?CategoryDataset?getDataSet2()?{?
           DefaultCategoryDataset?dataset?=?new?DefaultCategoryDataset();?
           dataset.addValue(2000,?"上海",?"VB");?
           dataset.addValue(3000,?"北京",?"JAVA");?
           dataset.addValue(3330,?"上海",?"JAVA");?
           dataset.addValue(3500,?"廣州",?"JAVA");?
           dataset.addValue(3500,?"北京",?"DOT?NET");?
           dataset.addValue(4000,?"上海",?"DOT?NET");?
           dataset.addValue(4800,?"廣州",?"DOT?NET");?
           dataset.addValue(2600,?"北京",?"DELPHI");?
           dataset.addValue(2200,?"上海",?"DELPHI");?
           dataset.addValue(4000,?"北京",?"VC");?
           dataset.addValue(4000,?"上海",?"VC");?
           dataset.addValue(4200,?"廣州",?"VC");?
           return?dataset;?
          }?
          private?static?CategoryDataset?getDataSet3()?{?
           DefaultCategoryDataset?dataset?=?new?DefaultCategoryDataset();?
           dataset.addValue(2100,?"北京",?"VB");?
           dataset.addValue(2200,?"上海",?"VB");?
           dataset.addValue(2100,?"廣州",?"VB");?
           dataset.addValue(3000,?"北京",?"JAVA");?
           dataset.addValue(3200,?"上海",?"JAVA");?
           dataset.addValue(3600,?"廣州",?"JAVA");?
           dataset.addValue(4100,?"北京",?"DOT?NET");?
           dataset.addValue(4200,?"上海",?"DOT?NET");?
           dataset.addValue(4160,?"廣州",?"DOT?NET");?
           dataset.addValue(2400,?"北京",?"DELPHI");?
           dataset.addValue(2600,?"上海",?"DELPHI");?
           dataset.addValue(2500,?"廣州",?"DELPHI");?
           dataset.addValue(5400,?"北京",?"VC");?
           dataset.addValue(5000,?"上海",?"VC");?
           dataset.addValue(5500,?"廣州",?"VC");?
           return?dataset;?
          }?
          %>?
          </body>?
          </html>?

            生成圖片如下:?


          posted @ 2006-12-29 23:36 tory 閱讀(389) | 評(píng)論 (0)編輯 收藏

          ?
          在用 AJAX 開發(fā)的過程中, 不可避免的會(huì)遇到中文問題. 很多原來可以通過表單進(jìn)行 POST 提交的字符, 到了用 AJAX 實(shí)現(xiàn)的時(shí)候, 就會(huì)出現(xiàn)煩人的亂碼和丟特殊字符的現(xiàn)象. 另外服務(wù)器端返回值如何解析, 也是一個(gè)很煩人的問題. 本文將就個(gè)人的一點(diǎn)實(shí)踐經(jīng)驗(yàn)作出總結(jié), 并給出一個(gè)盡量簡單可行, 復(fù)用性高的方案. 目的不是替代你喜歡的 AJAX 框架, 而是希望幫助您理解和處理可能遇到的問題.

          開始之前: 首先一個(gè)問題就是通常 XMLHttpRequest 默認(rèn)的編碼都是UTF-8的, 所以我們建議所有頁面, 客戶端和服務(wù)器端都使用 UTF-8 作為編碼.

          1. base64 encode 和 decode
          ??? 這個(gè)方案依賴于 JavaScript 實(shí)現(xiàn)的 base64 編碼/解碼方法, 在客戶端發(fā)送參數(shù)的時(shí)候用 base64 進(jìn)行編碼, 服務(wù)器端通過 base64 進(jìn)行解碼后還原出原來的字符, 這個(gè)解決方案可以滿足需要, 但是有個(gè)問題就是一是增加了客戶端代碼量, 還有個(gè)大問題就是編碼后的內(nèi)容比原始內(nèi)容會(huì)大很多, 另外如果找到的 base64 JS 算法不夠標(biāo)準(zhǔn)的話, 服務(wù)器端就無法還原原來的值了. 現(xiàn)在網(wǎng)上有很多種 base64 的 JS 實(shí)現(xiàn)代碼, 例如如下的一個(gè)算法實(shí)現(xiàn):

          <HTML>
          <HEAD>
          <TITLE>Base64</TITLE>
          <script language=javascript>
          var base64EncodeChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
          var base64DecodeChars = new Array(
            -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
            -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
            -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63,
            52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1,
            -1,  0, 1, 2, 3,? 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
            15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1,
            -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
            41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1);
          function base64encode(str) {
            var out, i, len;
            var c1, c2, c3;
            len = str.length;
            i = 0;
            out = "";
            while (i < len) {
          ?c1 = str.charCodeAt(i++) & 0xff;
          ?if(i == len)
          ?{
             out += base64EncodeChars.charAt(c1 >> 2);
             out += base64EncodeChars.charAt((c1 & 0x3) << 4);
             out += "==";
             break;
          ?}
          ?c2 = str.charCodeAt(i++);
          ?if(i == len)
          ?{
             out += base64EncodeChars.charAt(c1 >> 2);
             out += base64EncodeChars.charAt(((c1 & 0x3)<< 4) | ((c2 & 0xF0) >> 4));
             out += base64EncodeChars.charAt((c2 & 0xF) << 2);
             out += "=";
             break;
          ?}
          ?c3 = str.charCodeAt(i++);
          ?out += base64EncodeChars.charAt(c1 >> 2);
          ?out += base64EncodeChars.charAt(((c1 & 0x3)<< 4) | ((c2 & 0xF0) >> 4));
          ?out += base64EncodeChars.charAt(((c2 & 0xF) << 2) | ((c3 & 0xC0) >>6));
          ?out += base64EncodeChars.charAt(c3 & 0x3F);
            }
             return out;
          }
          function base64decode(str) {
            var c1, c2, c3, c4;
            var i, len, out;
            len = str.length;
            i = 0;
            out = "";
            while (i < len) {
          ?/* c1 */
          ?do {
             c1 = base64DecodeChars[str.charCodeAt(i++) & 0xff];
          ?} while(i < len && c1 == -1);
          ?if(c1 == -1)
             break;
          ?/* c2 */
          ?do {
             c2 = base64DecodeChars[str.charCodeAt(i++) & 0xff];
          ?} while(i < len && c2 == -1);
          ?if(c2 == -1)
             break;
          ?out += String.fromCharCode((c1 << 2) | ((c2 & 0x30) >> 4));
          ?/* c3 */
          ?do {
             c3 = str.charCodeAt(i++) & 0xff;
             if(c3 == 61)
           return out;
             c3 = base64DecodeChars[c3];
          ?} while(i < len && c3 == -1);
          ?if(c3 == -1)
             break;
          ?out += String.fromCharCode(((c2 & 0XF) << 4) | ((c3 & 0x3C) >> 2));
          ?/* c4 */
          ?do {
             c4 = str.charCodeAt(i++) & 0xff;
             if(c4 == 61)
           return out;
             c4 = base64DecodeChars[c4];
          ?} while(i < len && c4 == -1);
          ?if(c4 == -1)
             break;
          ?out += String.fromCharCode(((c3 & 0x03) << 6) | c4);
            }
             return out;
          }
          function utf16to8(str) {
            var out, i, len, c;
            out = "";
            len = str.length;
            for(i = 0; i < len; i++) {
          ?c = str.charCodeAt(i);
          ?if ((c >= 0x0001) && (c <= 0x007F)) {
             out += str.charAt(i);
          ?} else if (c > 0x07FF) {
             out += String.fromCharCode(0xE0 | ((c >> 12) & 0x0F));
             out += String.fromCharCode(0x80 | ((c >> 6) & 0x3F));
             out += String.fromCharCode(0x80 | ((c >> 0) & 0x3F));
          ?} else {
             out += String.fromCharCode(0xC0 | ((c >> 6) & 0x1F));
             out += String.fromCharCode(0x80 | ((c >> 0) & 0x3F));
          ?}
            }
             return out;
          }
          function utf8to16(str) {
            var out, i, len, c;
            var char2, char3;
            out = "";
            len = str.length;
            i = 0;
            while (i < len) {
          ?c = str.charCodeAt(i++);
          ?switch(c >> 4)
          ?{
            case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7:
             // 0xxxxxxx
             out += str.charAt(i-1);
             break;
            case 12: case 13:
             // 110x xxxx  10xx xxxx
             char2 = str.charCodeAt(i++);
             out += String.fromCharCode(((c & 0x1F) << 6) | (char2 & 0x3F));
             break;
            case 14:
             // 1110 xxxx 10xx xxxx 10xx xxxx
             char2 = str.charCodeAt(i++);
             char3 = str.charCodeAt(i++);
             out += String.fromCharCode(((c & 0x0F) << 12) |
               ((char2 & 0x3F) << 6) |
               ((char3 & 0x3F) << 0));
             break;
          ?}
            }
             return out;
          }

          function doit() {
            var f = document.f
             f.output.value = base64encode(utf16to8(f.source.value))
             f.decode.value = utf8to16(base64decode(f.output.value))
          }
          </script>
          </HEAD>
          <BODY>
          <H1>Base64</H1>
          <FORM NAME="f">
          原碼& lt;BR>
          <TEXTAREA NAME="source" ROWS=4 COLS=60 WRAP="soft"></TEXTAREA><BR><BR>
          Base64 encode<BR>
          <TEXTAREA NAME="output" ROWS=4 COLS=60 WRAP="soft"></TEXTAREA><BR><BR>
          Base64 decode<BR>
          <TEXTAREA NAME="decode" ROWS=4 COLS=60 WRAP="soft"></TEXTAREA><BR><BR>
          <INPUT TYPE=BUTTON VALUE="轉(zhuǎn)換" ONCLICK="doit()">
          </FORM>
          </BODY>

          在每個(gè)表單值被提交之前調(diào)用 base64encode, 然后在服務(wù)器端調(diào)用 base64 解碼器即可.
          在 JSP 中可以通過這樣做來實(shí)現(xiàn):
          ??? ??? sun.misc.BASE64Decoder base64decoder = new sun.misc.BASE64Decoder();
          ??? ??? byte[] data =?base64decoder.decodeBuffer(request.getParameter("input"));
          ??? ??? String result = new String(data, "UTF-8");// 注意建議這里制定字符集來歡迎到原來的字符串

          在這種情況下服務(wù)器端返回的字符也可以通過先 base64 編碼的方式傳遞到客戶端, 客戶端之后調(diào)用 JS 形式的解碼器即可還原到原來的字符串. 服務(wù)器端可以使用 sun.misc.BASE64Encoder (不要用 java.netURLEncoder).

          2.使用 JS 自帶的 escape() & encodeURI() & encodeURIComponent()

          escape() & encodeURI() & encodeURIComponent()這三個(gè)函數(shù)都可以用來對(duì)URI進(jìn)行encode或過濾特殊字符(#/$&+=?/等)。我的經(jīng)驗(yàn)是最好用encodeURIComponent()(需要IE 5.5以上,F(xiàn)ireFox當(dāng)然沒問題),因?yàn)閷?duì)UTF-8支持比較好,不會(huì)遇到中文亂碼問題,否則還需要進(jìn)行編碼轉(zhuǎn)換,很麻煩的。使用其它兩個(gè)函數(shù)都會(huì)發(fā)生丟失特殊字符的問題,例如空格變+號(hào)或者空格,引號(hào),&=?等丟失的問題, 至少使用 JSP 作為服務(wù)器端的話會(huì)發(fā)生這種情況, 有興趣的朋友可以將本文最后的例子代碼中的編碼部分修改后做個(gè)測(cè)試.

          下面是MSDN上對(duì)這三個(gè)函數(shù)的解釋:

          escape(charString)

          The escape method returns a string value (in Unicode format) that contains the contents of charstring. All spaces, punctuation, accented characters, and any other non-ASCII characters are replaced with %xx encoding, where xx is equivalent to the hexadecimal number representing the character. For example, a space is returned as "%20."

          Characters with a value greater than 255 are stored using the %uxxxx format.

          Note?? The escape method should not be used to encode Uniform Resource Identifiers (URI). Use encodeURI and encodeURIComponent methods instead.

          http://msdn.microsoft.com/library/en-us/script56/html/js56jsmthescape.asp

          ?encodeURI(URIString)

          The encodeURI method returns an encoded URI. If you pass the result to decodeURI, the original string is returned. The encodeURI method does not encode the following characters: ":", "/", ";", and "?". Use encodeURIComponent to encode these characters.

          http://msdn.microsoft.com/library/en-us/script56/html/js56jsmthfencodeuri.asp

          encodeURIComponent(encodedURIString)

          The encodeURIComponent method returns an encoded URI. If you pass the result to decodeURIComponent, the original string is returned. Because the encodeURIComponent method encodes all characters, be careful if the string represents a path such as /folder1/folder2/default.html. The slash characters will be encoded and will not be valid if sent as a request to a web server. Use the encodeURI method if the string contains more than a single URI component.

          http://msdn.microsoft.com/library/en-us/script56/html/js56jsmthencodeuricomponent.asp

          3. 使用一個(gè)簡便的客戶端數(shù)據(jù)解析方案

          最偷懶的辦法就是返回一段 HTML 顯示出來了. 至于如果是想帶一些數(shù)據(jù), 解析處理的話, 方案很多, 利用 XML 啊, JSON 啊什么的不一而足. 我這里呢就給出一個(gè)相當(dāng)簡便的方案: 使用 JS 內(nèi)置的 eval 方法來解析. 這個(gè)方案是在幫助一個(gè)同事想最快的已最短的代碼解析返回的對(duì)象的多個(gè)變量的時(shí)候提出的.

          服務(wù)器端返回一個(gè)字符串:
          var _dataObject = {
          ?? username : "beansoft",
          ??????? age : 24
          };

          客戶端在得到這個(gè)字符串后可以通過下面一段代碼搞定:
          var responseText = xmlhttp.responseText;
          eval(responseText);
          alert("_dataObject.username=" + _dataObject.username);

          好了, 解析出來了!
          如果要傳遞多個(gè)變量呢, 就用 var _dataObject1, var _dataObject2...這樣就可以了, 客戶端就依次是 _dataObject1.username, _dataObject2.username...

          等等: 我的變量里寫了特殊字符怎么辦? 例如我用的字符串是 'abc"'', 這時(shí)候我不得不拋出殺手锏了, 這就是用 Java 實(shí)現(xiàn)的 escape(), unescape() 方法, 其實(shí)本例中只需要 escape() 的 Java 版本就可以了(這個(gè)方案也幫助另一個(gè)同事解決了從JSP端傳遞的變量含有'號(hào)結(jié)果導(dǎo)致客戶端沒法顯示的問題):

          ??? public static String escape(String src) {
          ??? ??? int i;
          ??? ??? char j;
          ??? ??? StringBuffer tmp = new StringBuffer();
          ??? ??? tmp.ensureCapacity(src.length() * 6);
          ??? ??? for (i = 0; i < src.length(); i++) {
          ??? ??? ??? j = src.charAt(i);
          ??? ??? ??? if (Character.isDigit(j) || Character.isLowerCase(j)
          ??? ??? ??? ??? ??? || Character.isUpperCase(j))
          ??? ??? ??? ??? tmp.append(j);
          ??? ??? ??? else if (j < 256) {
          ??? ??? ??? ??? tmp.append("%");
          ??? ??? ??? ??? if (j < 16)
          ??? ??? ??? ??? ??? tmp.append("0");
          ??? ??? ??? ??? tmp.append(Integer.toString(j, 16));
          ??? ??? ??? } else {
          ??? ??? ??? ??? tmp.append("%u");
          ??? ??? ??? ??? tmp.append(Integer.toString(j, 16));
          ??? ??? ??? }
          ??? ??? }
          ??? ??? return tmp.toString();
          ??? }

          ??? public static String unescape(String src) {
          ??? ??? StringBuffer tmp = new StringBuffer();
          ??? ??? tmp.ensureCapacity(src.length());
          ??? ??? int lastPos = 0, pos = 0;
          ??? ??? char ch;
          ??? ??? while (lastPos < src.length()) {
          ??? ??? ??? pos = src.indexOf("%", lastPos);
          ??? ??? ??? if (pos == lastPos) {
          ??? ??? ??? ??? if (src.charAt(pos + 1) == 'u') {
          ??? ??? ??? ??? ??? ch = (char) Integer.parseInt(src
          ??? ??? ??? ??? ??? ??? ??? .substring(pos + 2, pos + 6), 16);
          ??? ??? ??? ??? ??? tmp.append(ch);
          ??? ??? ??? ??? ??? lastPos = pos + 6;
          ??? ??? ??? ??? } else {
          ??? ??? ??? ??? ??? ch = (char) Integer.parseInt(src
          ??? ??? ??? ??? ??? ??? ??? .substring(pos + 1, pos + 3), 16);
          ??? ??? ??? ??? ??? tmp.append(ch);
          ??? ??? ??? ??? ??? lastPos = pos + 3;
          ??? ??? ??? ??? }
          ??? ??? ??? } else {
          ??? ??? ??? ??? if (pos == -1) {
          ??? ??? ??? ??? ??? tmp.append(src.substring(lastPos));
          ??? ??? ??? ??? ??? lastPos = src.length();
          ??? ??? ??? ??? } else {
          ??? ??? ??? ??? ??? tmp.append(src.substring(lastPos, pos));
          ??? ??? ??? ??? ??? lastPos = pos;
          ??? ??? ??? ??? }
          ??? ??? ??? }
          ??? ??? }
          ??? ??? return tmp.toString();
          ??? }

          這樣, 在服務(wù)器端的時(shí)候可以變成:
          <%
          String username = "'abc\"''";// 其實(shí)這個(gè)普通子串轉(zhuǎn)換成 Java 語言中的字符串也有工具可以用的, 例如本人開發(fā)的 Native2JavaString, 改日再講.
          %>
          var _dataObject = {
          ?? username : "<%=escape(username)%>",
          ??????? age : 24
          };
          客戶端呢, 就可以簡單的來JS自帶的 unescape() 函數(shù)來取出原來的字符串:
          var responseText = xmlhttp.responseText;
          eval(responseText);
          alert("_dataObject.username=" + unescape(_dataObject.username));
          就是服務(wù)器端用 Java 寫的 escape(), 客戶端呢就用 JS 自帶的 unescape().

          4.?實(shí)例代碼
          好了, 說了這么多, 就推出個(gè)人的解決方案吧. 簡單的講就是我寫了一個(gè)腳本對(duì)象 AjaxFormer, 使用的是 escape來自動(dòng)的將原來的 POST/GET 方式的提交代碼自動(dòng)的轉(zhuǎn)換成 AJAX 的方式.

          /**
          ?* @constructor
          ?* This is a ajax form helper class.
          ?*
          ?* @param form - the document form
          ?* @param resultDivId - the result div id
          ?*/
          function AjaxFormer (form, resultDivId);

          構(gòu)造器的第一個(gè)參數(shù)是個(gè) form 對(duì)象, 第二個(gè)是個(gè)可選的結(jié)果 DIV 對(duì)象, 也就是說你可以指定服務(wù)器端返回的 HTML 代碼顯示的地方, 如果保持為空的話, 那么返回的 HTML?會(huì)被附加到文檔的末尾. 本對(duì)象有一個(gè)名字為 ajaxSubmitForm() 的方法來自動(dòng)的遍歷所有表單元素, 然后將結(jié)果拼成一個(gè)字符串, 最后根據(jù)原來的表單的提交方式(get/post)來自動(dòng)再客戶端用 AJAX 模擬提交這個(gè)表單到原來的表單的 action 屬性所指定的頁面中去.

          用法示例:
          <html>

          <head>
          <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
          <title>AJAX Form Submit Test</title>
          <script src='ajax_common.js'></script>

          </head>

          <body>
          <h3>AJAX Form Submit Test</h3>
          Fill the form and then click submit
          <form method="POST" id="form1" name="form1"
          action="form_action.jsp"
          onSubmit="former.ajaxSubmitForm();return false;">
          ??? <p><input type="hidden" name="hidden1" value="hiddenValue">
          ??? text:<input type="text" name="textf&1" size="20" value="text1">
          ??? checkbox:<input type="checkbox" name="checkbox1" value="ON" checked>
          ??? radio:<input type="radio" value="V1" checked name="radio1">
          ??? select:<select size="1" name="select1">
          ??? <option selected value="option1">D1</option>
          ??? </select>
          ??? <br>
          ??? <br>
          ??? <input type="submit" name="B1" value="submit">
          ??? <input type="reset" name="B2" value="reset">
          ??? </p>
          </form>

          <script type="text/javascript">
          var former = new AjaxFormer($('form1'));
          </script>
          </body>

          </html>

          紅色的字體就是您從一個(gè)非 AJAX 的表單提交改變成一個(gè) AJAX 的表單提交所需要做的工作, 看上去夠簡單吧?

          運(yùn)行時(shí)的效果如圖所示:
          http://www.aygfsteel.com/images/blogjava_net/beansoft/18680/o_ajaxFormer.png

          下載本文的源碼:?

          AJAXFormer.zip4KB

          將源碼解壓縮到JSP服務(wù)器的任意目錄下即可, 例如 $TOMCAT_HOME\webapps\ROOT 下, 然后在瀏覽器里鍵入:
          http://localhost:8080/ajax_form_submit.htm

          作者: beansoft@126.com?2006.12.25

          posted @ 2006-12-25 21:01 tory 閱讀(765) | 評(píng)論 (1)編輯 收藏

          主站蜘蛛池模板: 永川市| 广州市| 友谊县| 万荣县| 万年县| 佛山市| 井研县| 贺兰县| 大化| 栾城县| 石家庄市| 博野县| 任丘市| 县级市| 江津市| 朝阳县| 平山县| 宜阳县| 宁安市| 桃园县| 新津县| 阿坝| 佛山市| 永清县| 阜阳市| 麻栗坡县| 平泉县| 台州市| 南充市| 永仁县| 宾川县| 麻栗坡县| 城固县| 攀枝花市| 永胜县| 来凤县| 雷州市| 奈曼旗| 武山县| 达州市| 磴口县|