??xml version="1.0" encoding="utf-8" standalone="yes"?>亚洲国产精品一区第二页,亚洲理论在线观看,亚洲成av人片天堂网http://www.tkk7.com/tory320/zh-cnFri, 09 May 2025 18:35:35 GMTFri, 09 May 2025 18:35:35 GMT600307http://www.tkk7.com/tory320/archive/2008/03/07/184570.htmltorytoryFri, 07 Mar 2008 09:58:00 GMThttp://www.tkk7.com/tory320/archive/2008/03/07/184570.htmlhttp://www.tkk7.com/tory320/comments/184570.htmlhttp://www.tkk7.com/tory320/archive/2008/03/07/184570.html#Feedback0http://www.tkk7.com/tory320/comments/commentRss/184570.htmlhttp://www.tkk7.com/tory320/services/trackbacks/184570.htmlDesign 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.



tory 2008-03-07 17:58 发表评论
]]>
文g的所有操?http://www.tkk7.com/tory320/archive/2007/01/30/96697.htmltorytoryTue, 30 Jan 2007 05:03:00 GMThttp://www.tkk7.com/tory320/archive/2007/01/30/96697.htmlhttp://www.tkk7.com/tory320/comments/96697.htmlhttp://www.tkk7.com/tory320/archive/2007/01/30/96697.html#Feedback0http://www.tkk7.com/tory320/comments/commentRss/96697.htmlhttp://www.tkk7.com/tory320/services/trackbacks/96697.html 文g的所有操?/font> /**
 * //FileOperate.java
 * 文g的各U操?br /> * 杨彩 http://blog.sina.com.cn/m/yangcai
 * 文g操作 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("新徏目录操作 成功执行");
    }
    catch(Exception e)
    {
      System.out.println("新徏目录操作出错");
      e.printStackTrace();
    }
  }
 
  /**
   * 新徏文g
   */
  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("新徏文g操作 成功执行");
    }
    catch (Exception e) {
      System.out.println("新徏目录操作出错");
      e.printStackTrace();
 
    }
 
  }
 
  /**
   * 删除文g
   */
  public void delFile(String filePathAndName) {
    try {
      String filePath = filePathAndName;
      filePath = filePath.toString();
      File myDelFile = new File(filePath);
      myDelFile.delete();
      System.out.println("删除文g操作 成功执行");
    }
    catch (Exception e) {
      System.out.println("删除文g操作出错");
      e.printStackTrace();
 
    }
 
  }
 
  /**
   * 删除文g?
   */
  public void delFolder(String folderPath)
  {
    try
    {
      delAllFile(folderPath); //删除完里面所有内?
      String filePath = folderPath;
      filePath = filePath.toString();
      File myFilePath = new File(filePath);
      myFilePath.delete(); //删除I文件夹
      System.out.println("删除文gҎ?成功执行");
    }
    catch (Exception e)
    {
      System.out.println("删除文gҎ作出?);
      e.printStackTrace();
 
    }
 
  }
 
  /**
   * 删除文g多w面的所有文?
   * @param path String 文g夹\??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]);//再删除空文g?
      }
    }
          System.out.println("删除文g操作 成功执行"); 
  }
 
  /**
   * 复制单个文g
   * @param oldPath String 原文件\?如:c:/fqf.txt
   * @param newPath String 复制后\?如: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())
      { //文g存在?
        InputStream inStream = new FileInputStream(oldPath); //d原文?
        FileOutputStream fs = new FileOutputStream(newPath);
        byte[] buffer = new byte[1444];
        int length;
        while ( (byteread = inStream.read(buffer)) != -1) {
          bytesum += byteread; //字节?文g大小
          System.out.println(bytesum);
          fs.write(buffer, 0, byteread);
        }
        inStream.close();
      }
            System.out.println("删除文gҎ?成功执行"); 
    }
    catch (Exception e) {
      System.out.println("复制单个文g操作出错");
      e.printStackTrace();
 
    }
 
  }
 
  /**
   * 复制整个文g夹内?
   * @param oldPath String 原文件\?如:c:/fqf
   * @param newPath String 复制后\?如:f:/fqf/ff
   */
  public void copyFolder(String oldPath, String newPath) {
 
    try
    {
      (new File(newPath)).mkdirs(); //如果文g夹不存在 则徏立新文g?
      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())
        {//如果是子文g?
          copyFolder(oldPath+"/"+file[i],newPath+"/"+file[i]);
        }
      }
            System.out.println("复制文gҎ?成功执行"); 
    }
    catch (Exception e) {
      System.out.println("复制整个文g夹内Ҏ作出?);
      e.printStackTrace();
 
    }
 
  }
 
  /**
   * Ud文g到指定目?
   * @param oldPath String 如:c:/fqf.txt
   * @param newPath String 如:d:/fqf.txt
   */
  public void moveFile(String oldPath, String newPath) {
    copyFile(oldPath, newPath);
    delFile(oldPath);
 
  }
 
  /**
   * Ud文g到指定目?
   * @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("使用此功能请按[1]  功能一Q新建目?);
   System.out.println("使用此功能请按[2]  功能二:新徏文g");
   System.out.println("使用此功能请按[3]  功能三:删除文g");
   System.out.println("使用此功能请按[4]  功能四:删除文g?);
   System.out.println("使用此功能请按[5]  功能五:删除文g多w面的所有文?);
   System.out.println("使用此功能请按[6]  功能六:复制文g");
   System.out.println("使用此功能请按[7]  功能七:复制文g夹的所有内?);
   System.out.println("使用此功能请按[8]  功能八:Ud文g到指定目?);
   System.out.println("使用此功能请按[9]  功能九:Ud文g夹到指定目录");
   System.out.println("使用此功能请按[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("你选择了功能一  误入目录名");  
        aa=Bin.readLine();
        fo.newFolder(aa);
        break;
     case 2:System.out.println("你选择了功能二  误入文件名");  
        aa=Bin.readLine();
        System.out.println("误入在"+aa+"中的内容");
        bb=Bin.readLine();
        fo.newFile(aa,bb);
        break;
     case 3:System.out.println("你选择了功能三  误入文件名");  
        aa=Bin.readLine();
        fo.delFile(aa);
        break;
     case 4:System.out.println("你选择了功能四  误入文件名");  
        aa=Bin.readLine();
        fo.delFolder(aa);
        break;
     case 5:System.out.println("你选择了功能五  误入文件名");  
        aa=Bin.readLine();
        fo.delAllFile(aa);
        break;  
     case 6:System.out.println("你选择了功能六  误入文件名");  
        aa=Bin.readLine();
        System.out.println("误入目标文件名"); 
        bb=Bin.readLine();
        fo.copyFile(aa,bb);
        break;
     case 7:System.out.println("你选择了功能七  误入源文g?);  
        aa=Bin.readLine();
        System.out.println("误入目标文件名"); 
        bb=Bin.readLine();
        fo.copyFolder(aa,bb);
        break;       
     case 8:System.out.println("你选择了功能八  误入源文g?);  
        aa=Bin.readLine();
        System.out.println("误入目标文件名"); 
        bb=Bin.readLine();
        fo.moveFile(aa,bb);
        break;
       case 9:System.out.println("你选择了功能九  误入源文g?);  
        aa=Bin.readLine();
        System.out.println("误入目标文件名"); 
        bb=Bin.readLine();
        fo.moveFolder(aa,bb);
        break;       
     case 10:exitnow=true;
         System.out.println("E序l束Q请退?);
        break;
     default:System.out.println("输入错误.误?-10之间的数");               
     }
    
    
    System.out.println("请重新选择功能");
    
    
    }
    catch(Exception e)
    {
    System.out.println("输入错误字符或程序出?);
    }
    
 }   
 }
}


tory 2007-01-30 13:03 发表评论
]]>
(?IBatis的分늠I?http://www.tkk7.com/tory320/archive/2007/01/19/94909.htmltorytoryFri, 19 Jan 2007 05:02:00 GMThttp://www.tkk7.com/tory320/archive/2007/01/19/94909.htmlhttp://www.tkk7.com/tory320/comments/94909.htmlhttp://www.tkk7.com/tory320/archive/2007/01/19/94909.html#Feedback0http://www.tkk7.com/tory320/comments/commentRss/94909.htmlhttp://www.tkk7.com/tory320/services/trackbacks/94909.html在看JPetStore的代码时Q发现它的分处理主要是通过q回PaginatedList对象来完成的。如Q在CatalogServicecM
public PaginatedList getProductListByCategory(String categoryId) 
    
return productDao.getProductListByCategory(categoryId); 
  }
 

分页是操作数据库型系l常遇到的问题。分实现方法很多,但效率的差异很大了。iBatis是通过什么方式来实现q个分页的了。查看它的实现部分:
 
q回的PaginatedList实际上是个接口,实现q个接口的是PaginatedDataListcȝ对象Q查看PaginatedDataListcd玎ͼ每次页的时候最后都会调用下面这D函?
private List getList(int idx, int localPageSize) throws SQLException 
    
return sqlMapExecutor.queryForList(statementName, parameterObject, (idx) * pageSize, localPageSize); 
  }
 
׃
public interface SqlMapClient extends SqlMapExecutor, SqlMapTransactionManager {……} 

所以实际的调用ơ序如下Q?
SqlMapClientImpl.queryForPaginatedList->SqlMapSessionImpl.queryForPaginatedList 
->SqlMapExecutorDelegate.queryForPaginatedList->GeneralStatement.executeQueryForList 
->GeneralStatment.executeQueryWithCallback->GeneralStatment.executeQueryWithCallback 
->SqlExecutor.executeQuery->SqlExecutor.handleMultipleResults()->SqlExecutor.executeQuery-> handleResults 
分页处理的函数如?
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); 
    }
 
  }
 

由此可见QiBatis的分主要依赖于jdbcdriver的如何实C及是否支持rs.absolute(skipResults)。它q不是一个好的分|式。它先要取出所有的W合条g的记录存入ResultSet对象Q然后用absoluteҎq行定位Q来实现分页。当记录数较大(比如十万条)Ӟ整体的查询速度会变得很慢?
所以分还是要考虑采用直接操作sql语句来完成。当然小扚w的可以采用iBatis的分|式。一般分늚sql语句与数据库的具体实现有?
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; 
        }
 
lgQ小扚wQ?lt;2wQ可以采用ibatis自带的分늱Q大扚w的还是直接操UsqlQ当然也可以这些sql自己q行装Q或在包中封装都可以。包装的示例代码如下:
一个封装了分页功能的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;


tory 2007-01-19 13:02 发表评论
]]>
使用JFreeChart生成热点图表http://www.tkk7.com/tory320/archive/2006/12/29/90824.htmltorytoryFri, 29 Dec 2006 15:36:00 GMThttp://www.tkk7.com/tory320/archive/2006/12/29/90824.htmlhttp://www.tkk7.com/tory320/comments/90824.htmlhttp://www.tkk7.com/tory320/archive/2006/12/29/90824.html#Feedback0http://www.tkk7.com/tory320/comments/commentRss/90824.htmlhttp://www.tkk7.com/tory320/services/trackbacks/90824.html
使用JFreeChart生成热点图表
2006-12-14 11:54
Q一Q前aQ?br />
  JFreeChart是开放源代码站点SourceForge.net上的一个JAVA目。它的功能十分强大,能创建饼图、柱状图(普通柱状图以及堆栈q?、线图、区域图、分布图、؜合图、甘特图以及一些A表盘{等Qƈ可生成PNG或JPG囄格式文g?br />  本h在学习过E中发现Q网上很多文章都是讲一些JFreeChart的基本应用,而对JFreeChart生成热点图表q样常用的功能虽有所提及却没有一个完整的例子Q所以我写一个简单示例供大家参考,希望对大家的学习有所帮助。?br />
  Q二Q示例说明:

  假设有一个关于程序员北京Q上Pq洲三地E序员学历,开发语aQ薪金情늚调查。首先要以饼图显C程序员学历的分布情?index.jsp)。点击饼囄每一部分会以q图显C层次E序员所用开发语a和薪金的情况(barview.jsp)。重ҎC怎样在饼图上d链接。?br />
  Q三Q准备工作:

  1.下蝲最新版本的JFreeChart,当前为jfreechart-1.0.0-rc1
下蝲地址Qhttp://www.jfree.org/jfreechart/index.html

  2.解压文gQ将jfreechart-1.0.0-rc1/lib下的jcommon-1.0.0-rc1.jarQjfreechart-1.0.0-rc1.jar复制到WEB应用的lib目录下?br />
  3.在web.xml文g中增加以下内容:

QservletQ?br />Qservlet-nameQDisplayChartQ?servlet-nameQ?br />Qservlet-classQorg.jfree.chart.servlet.DisplayChartQ?servlet-classQ?br />Q?servletQ?br />Qservlet-mappingQ?br />Qservlet-nameQDisplayChartQ?servlet-nameQ?br />Qurl-patternQ?servletDisplayChartQ?url-patternQ?br />Q?servlet-mappingQ?/td>

  Q四Q饼N面代码(index.jspQ?br />

Q?@ page contentType="text/html;charset=GBK"%Q?br />Q?@ page import="org.jfree.data.general.DefaultPieDataset"%Q?br />Q?@ page import="org.jfree.chart.*"%Q?br />Q?@ page import="org.jfree.chart.plot.*"%Q?br />Q?@ page import="org.jfree.chart.servlet.ServletUtilities"%Q?br />Q?@ page import="org.jfree.chart.labels.StandardPieItemLabelGenerator"%Q?br />Q?@ page import="org.jfree.chart.urls.StandardPieURLGenerator"%Q?br />Q?@ page import="org.jfree.chart.entity.StandardEntityCollection"%Q?br />Q?@ page import="java.io.*"%Q?br />QHTMLQ?br />QHEADQ?br />QMETA http-equiv=Content-Type content="text/html; charset=GBK"Q?br />QTITLEQnacl_zhuang@hotmail.comQ?TITLEQ?br />Q?HEADQ?br />QBODYQ?br />Q? 

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"));//讑֮链接 
JFreeChart chart = new JFreeChart("",JFreeChart.DEFAULT_TITLE_FONT, plot, true); 
chart.setBackgroundPaint(java.awt.Color.white);//可选,讄囄背景色?br />chart.setTitle("E序员学历情况调查表");//可选,讄囄标题 
plot.setToolTipGenerator(new StandardPieItemLabelGenerator()); 
StandardEntityCollection sec = new StandardEntityCollection(); 
ChartRenderingInfo info = new ChartRenderingInfo(sec); 
PrintWriter w = new PrintWriter(out);//输出MAP信息 
//500是图片长度,300是图片高度?br />String filename = ServletUtilities.saveChartAsPNG(chart, 500, 300, info, session); 
ChartUtilities.writeImageMap(w, "map0", info, false); 

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

%Q?br />
QP ALIGN="CENTER"Q?br />Qimg src="Q?= graphURL %Q? width=500 height=300 border=0 usemap="#map0"Q?br />Q?PQ?br />Q?BODYQ?br />Q?HTMLQ?/td>

  生成的图片如?br />

  在浏览器中点右键Q>查看源文件会发现有以下一DHTML代码Q?br />
Qmap id="map0" name="map0"Q?br />Qarea shape="poly" coords="247,61,250,61,250,123,250,123" title="博士 = 80" alt="" href="barview.jsp?category=博士&pieIndex=0"/Q?br />Qarea 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"/Q?br />Qarea 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"/Q?br />Qarea 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"/Q?br />Qarea shape="poly" coords="261,62,285,65,307,72,250,123,250,123" title="高中 
 = 1,530" alt="" href="barview.jsp?category=高中&pieIndex=0"/Q?br />Qarea shape="poly" coords="250,61,261,62,250,123,250,123" title="高中以下 = 370" alt="" href="barview.jsp?category=高中以下&pieIndex=0"/Q?br />Q?mapQ?/td>


  q就是MAP信息Q我们在IMG标签中加入usemap="#map0"可以ؓ饼图的每一部分加入链接?br />
  Q五Q柱状图面代码Q?barview.jsp)

QHTMLQ?br />QHEADQ?br />QMETA http-equiv=Content-Type content="text/html; charset=GBK"Q?br />QTITLEQnacl_zhuang@hotmail.comQ?TITLEQ?br />Q?HEADQ?br />
QbodyQ?br />
Q?@ page contentType="text/html;charset=GBK"%Q?br />Q?@ page import="org.jfree.chart.ChartFactory, 
org.jfree.chart.JFreeChart, 
org.jfree.chart.plot.PlotOrientation, 
org.jfree.chart.servlet.ServletUtilities, 
org.jfree.data.category.*"%Q?br />Q? 
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+"E序员在各城市薪金情늻?; 
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; 
%Q?br />QP ALIGN="CENTER"Q?br />Qimg src="Q?= graphURL %Q? width=500 height=300 border=0 usemap="#Q?= filename %Q?Q?br />Q?PQ?br />Q?! 
private static CategoryDataset getDataSet() { 
 DefaultCategoryDataset dataset = new DefaultCategoryDataset(); 
 dataset.addValue(2000, "北京", "VB"); 
 dataset.addValue(1800, "上v", "VB"); 
 dataset.addValue(2200, "q州", "VB"); 
 dataset.addValue(3200, "北京", "JAVA"); 
 dataset.addValue(3500, "上v", "JAVA"); 
 dataset.addValue(3600, "q州", "JAVA"); 
 dataset.addValue(3300, "北京", "DOT NET"); 
 dataset.addValue(3400, "上v", "DOT NET"); 
 dataset.addValue(3700, "q州", "DOT NET"); 
 dataset.addValue(2500, "北京", "DELPHI"); 
 dataset.addValue(2800, "上v", "DELPHI"); 
 dataset.addValue(3200, "q州", "DELPHI"); 
 dataset.addValue(5000, "北京", "VC"); 
 dataset.addValue(3500, "上v", "VC"); 
 dataset.addValue(4600, "q州", "VC"); 
 return dataset; 

private static CategoryDataset getDataSet2() { 
 DefaultCategoryDataset dataset = new DefaultCategoryDataset(); 
 dataset.addValue(2000, "上v", "VB"); 
 dataset.addValue(3000, "北京", "JAVA"); 
 dataset.addValue(3330, "上v", "JAVA"); 
 dataset.addValue(3500, "q州", "JAVA"); 
 dataset.addValue(3500, "北京", "DOT NET"); 
 dataset.addValue(4000, "上v", "DOT NET"); 
 dataset.addValue(4800, "q州", "DOT NET"); 
 dataset.addValue(2600, "北京", "DELPHI"); 
 dataset.addValue(2200, "上v", "DELPHI"); 
 dataset.addValue(4000, "北京", "VC"); 
 dataset.addValue(4000, "上v", "VC"); 
 dataset.addValue(4200, "q州", "VC"); 
 return dataset; 

private static CategoryDataset getDataSet3() { 
 DefaultCategoryDataset dataset = new DefaultCategoryDataset(); 
 dataset.addValue(2100, "北京", "VB"); 
 dataset.addValue(2200, "上v", "VB"); 
 dataset.addValue(2100, "q州", "VB"); 
 dataset.addValue(3000, "北京", "JAVA"); 
 dataset.addValue(3200, "上v", "JAVA"); 
 dataset.addValue(3600, "q州", "JAVA"); 
 dataset.addValue(4100, "北京", "DOT NET"); 
 dataset.addValue(4200, "上v", "DOT NET"); 
 dataset.addValue(4160, "q州", "DOT NET"); 
 dataset.addValue(2400, "北京", "DELPHI"); 
 dataset.addValue(2600, "上v", "DELPHI"); 
 dataset.addValue(2500, "q州", "DELPHI"); 
 dataset.addValue(5400, "北京", "VC"); 
 dataset.addValue(5000, "上v", "VC"); 
 dataset.addValue(5500, "q州", "VC"); 
 return dataset; 

%Q?br />Q?bodyQ?br />Q?htmlQ?/td>

  生成囄如下Q?br />



tory 2006-12-29 23:36 发表评论
]]>
(?JSP ?AJAX 的表单提交中文问题的单解x?http://www.tkk7.com/tory320/archive/2006/12/25/89980.htmltorytoryMon, 25 Dec 2006 13:01:00 GMThttp://www.tkk7.com/tory320/archive/2006/12/25/89980.htmlhttp://www.tkk7.com/tory320/comments/89980.htmlhttp://www.tkk7.com/tory320/archive/2006/12/25/89980.html#Feedback1http://www.tkk7.com/tory320/comments/commentRss/89980.htmlhttp://www.tkk7.com/tory320/services/trackbacks/89980.html 在用 AJAX 开发的q程? 不可避免的会遇到中文问题. 很多原来可以通过表单q行 POST 提交的字W? C?AJAX 实现的时? ׃出现烦h的ؕ码和丢特D字W的现象. 另外服务器端q回值如何解? 也是一个很烦h的问? 本文就个h的一点实늻验作出ȝ, q给Z个尽量简单可? 复用性高的方? 目的不是替代你喜Ƣ的 AJAX 框架, 而是希望帮助您理解和处理可能遇到的问?

开始之? 首先一个问题就是通常 XMLHttpRequest 默认的编码都是UTF-8? 所以我们徏议所有页? 客户端和服务器端都?UTF-8 作ؓ~码.

1. base64 encode ?decode
    q个Ҏ依赖?JavaScript 实现?base64 ~码/解码Ҏ, 在客L发送参数的时候用 base64 q行~码, 服务器端通过 base64 q行解码后还原出原来的字W? q个解决Ҏ可以满需? 但是有个问题是一是增加了客户端代码量, q有个大问题是~码后的内容比原始内容会大很? 另外如果扑ֈ?base64 JS 法不够标准的话, 服务器端无法还原原来的g. 现在|上有很多种 base64 ?JS 实现代码, 例如如下的一个算法实?

<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="转换" ONCLICK="doit()">
</FORM>
</BODY>

在每个表单D提交之前调用 base64encode, 然后在服务器端调?base64 解码器即?
?JSP 中可以通过q样做来实现:
        sun.misc.BASE64Decoder base64decoder = new sun.misc.BASE64Decoder();
        byte[] data = base64decoder.decodeBuffer(request.getParameter("input"));
        String result = new String(data, "UTF-8");// 注意q里制定字符集来Ƣ迎到原来的字符?/span>

在这U情况下服务器端q回的字W也可以通过?base64 ~码的方式传递到客户? 客户端之后调?JS 形式的解码器卛_q原到原来的字符? 服务器端可以使用 sun.misc.BASE64Encoder (不要?java.netURLEncoder).

2.使用 JS 自带?escape() & encodeURI() & encodeURIComponent()

escape() & encodeURI() & encodeURIComponent()q三个函数都可以用来对URIq行encode或过滤特D字W(#/$&+=?/{)。我的经验是最好用encodeURIComponent()Q需要IE 5.5以上QFireFox当然没问题)Q因为对UTF-8支持比较好,不会遇到中文q问题Q否则还需要进行编码{换,很麻烦的。用其它两个函数都会发生丢qD字W的问题,例如I格?h者空?引号,&=?{丢q问题, 臛_使用 JSP 作ؓ服务器端的话会发生这U情? 有兴的朋友可以本文最后的例子代码中的~码部分修改后做个测?

下面是MSDN上对q三个函数的解释Q?/p>

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. 使用一个简便的客户端数据解析方?br />
最h的办法就是返回一D?HTML 昄出来? 至于如果是想带一些数? 解析处理的话, Ҏ很多, 利用 XML ? JSON 啊什么的不一而. 我这里呢qZ个相当简便的Ҏ: 使用 JS 内置?eval Ҏ来解? q个Ҏ是在帮助一个同事想最快的已最短的代码解析q回的对象的多个变量的时候提出的.

服务器端q回一个字W串:
var _dataObject = {
   username : "beansoft",
        age : 24
};

客户端在得到q个字符串后可以通过下面一D代码搞?
var responseText = xmlhttp.responseText;
eval(responseText);
alert("_dataObject.username=" + _dataObject.username);

好了, 解析出来?
如果要传递多个变量呢, q var _dataObject1, var _dataObject2...q样可以了, 客户端就依次?_dataObject1.username, _dataObject2.username...

{等: 我的变量里写了特D字W怎么? 例如我用的字W串?'abc"'', q时候我不得不抛出杀手锏? q就是用 Java 实现?escape(), unescape() Ҏ, 其实本例中只需?escape() ?Java 版本可以了(q个Ҏ也帮助另一个同事解决了从JSP端传递的变量含有'L果导致客L没法昄的问?:

    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();
    }

q样, 在服务器端的时候可以变?
<%
String username = "'abc\"''";// 其实q个普通子串{换成 Java 语言中的字符串也有工具可以用? 例如本h开发的 Native2JavaString, Ҏ再讲.
%>
var _dataObject = {
   username : "<%=escape(username)%>",
        age : 24
};
客户端呢, 可以简单的来JS自带?unescape() 函数来取出原来的字符?
var responseText = xmlhttp.responseText;
eval(responseText);
alert("_dataObject.username=" + unescape(_dataObject.username));
是服务器端?Java 写的 escape(), 客户端呢q JS 自带?unescape().

4. 实例代码
好了, 说了q么? 推Z人的解决Ҏ? 单的讲就是我写了一个脚本对?AjaxFormer, 使用的是 escape来自动的原来的 POST/GET 方式的提交代码自动的转换?AJAX 的方?

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

构造器的第一个参数是?form 对象, W二个是个可选的l果 DIV 对象, 也就是说你可以指定服务器端返回的 HTML 代码昄的地? 如果保持为空的话, 那么q回?HTML 会被附加到文档的末尾. 本对象有一个名字ؓ ajaxSubmitForm() 的方法来自动的遍历所有表单元? 然后结果拼成一个字W串, 最后根据原来的表单的提交方?get/post)来自动再客户端用 AJAX 模拟提交q个表单到原来的表单?action 属性所指定的页面中?

用法CZ:
<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>

U色的字体就是您从一个非 AJAX 的表单提交改变成一?AJAX 的表单提交所需要做的工? 看上d单吧?

q行时的效果如图所C?
http://www.tkk7.com/images/blogjava_net/beansoft/18680/o_ajaxFormer.png

下蝲本文的源? 

AJAXFormer.zip4KB

源码解压羃到JSP服务器的L目录下即? 例如 $TOMCAT_HOME\webapps\ROOT ? 然后在浏览器里键?
http://localhost:8080/ajax_form_submit.htm

作? beansoft@126.com 2006.12.25



tory 2006-12-25 21:01 发表评论
]]>
(?WebWork 初体?/title><link>http://www.tkk7.com/tory320/archive/2006/12/24/89793.html</link><dc:creator>tory</dc:creator><author>tory</author><pubDate>Sun, 24 Dec 2006 14:42:00 GMT</pubDate><guid>http://www.tkk7.com/tory320/archive/2006/12/24/89793.html</guid><wfw:comment>http://www.tkk7.com/tory320/comments/89793.html</wfw:comment><comments>http://www.tkk7.com/tory320/archive/2006/12/24/89793.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.tkk7.com/tory320/comments/commentRss/89793.html</wfw:commentRss><trackback:ping>http://www.tkk7.com/tory320/services/trackbacks/89793.html</trackback:ping><description><![CDATA[ <font face="Arial">  在这?/font> <a > <font face="Arial">ASP.NET 中Session 实现原理析[2] 状态管理器</font> </a> <font face="Arial">Blog中,</font> <a > <font face="Arial">Flier</font> </a> <font face="Arial">老大向大家推荐了Java中几UCache的实玎ͼ于是我就按图索骥Q首先是扑ֈOSCache的老家Q?/font> <a > <font face="Arial">OpenSymphony</font> </a> <font face="Arial">。哇Q这里的资源真多啊,直就是一个宝藏。ؓ什么原来就没有发现呢?感谢Flier老大了!<br />        在OpenSymphony的主上Q我看到了两个让我觉得很亲切的项目:WebWork和Quarts。WebWork作ؓ一个实CIOC的轻量Web Application Framework一直备受开发者的青睐Q而Quarts更是在异步信息处理上大展拌了。看C老朋友,我就只好暂时新ƢOSCache摆一边,扑և我很久没有联pȝ老猫(Tomcat)去跟WebWork聊嗑了?br />        做好了一切的准备工作之后<sup>[1]</sup>Q我试着做一个登陆注册的功能Q以体验一下WebWork。跟其他的Web应用一P我们首先要徏立一个标准的WEB-INF目录(所谓标准就是目录下面包含lib和classes子目录以及Web.xml文g)Q接着在WEB-INF/lib下面放上WebWork所需要的.jar文gq在WEB-INF目录下徏立Web.xml文g<sup>[2]</sup>。在完成了这些千一律的工作之后Q我仔细的看了一下Web.xml中内容,它里面只定义了一个servletQwebworkQ其对应的class为com.opensymphony.webwork.dispatcher.ServletDispatcherQ然后由webworkq个servletd理所?action的请求。看到这里,我暗自窃喜,q跟我熟悉的WAF框架是十分类似的Q只不过MainServlet变成了ServletDispatcherQ?do的请求变成了.action而已?br />        接下来,是到classes目录下徏立xwork.xml文gQ这个文件跟WAF中的mappings.xml很相|因ؓ?action的处理都是在q里被定义的Q而WAF中关?do的处理则定义在mapping.xml中。但是也有一些我q不清楚的东西,如package和Interceptor。在classes目录下还要徏立一个validator.xml文gQ但是这个ƈ不是必需的。做好了q些准备工作之后Q就真正开始WebWork的体验之旅了?br />        1、徏立一个index.jsp(以下Z要部?Q?/font> <div style="BORDER-RIGHT: windowtext 0.5pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: windowtext 0.5pt solid; PADDING-LEFT: 5.4pt; BACKGROUND: #e6e6e6; PADDING-BOTTOM: 4px; BORDER-LEFT: windowtext 0.5pt solid; WIDTH: 98%; PADDING-TOP: 4px; BORDER-BOTTOM: windowtext 0.5pt solid"> <div> <!--StartFragment --> <font face="Arial"> <span style="COLOR: rgb(0,0,255)"><</span><span style="COLOR: rgb(128,0,0)">form </span><span style="COLOR: rgb(255,0,0)">action</span><span style="COLOR: rgb(0,0,255)">="Login.action"</span><span style="COLOR: rgb(255,0,0)"> method</span><span style="COLOR: rgb(0,0,255)">="post"</span><span style="COLOR: rgb(0,0,255)">></span></font> <span style="COLOR: rgb(0,0,0)"> <br /> <font face="Arial"> <img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align="top" />  </font> </span> <font face="Arial"> <span style="COLOR: rgb(0,0,255)"><</span> <span style="COLOR: rgb(128,0,0)">table </span> <span style="COLOR: rgb(255,0,0)">cellspacing</span> <span style="COLOR: rgb(0,0,255)">=0 </span> <span style="COLOR: rgb(255,0,0)">width</span> <span style="COLOR: rgb(0,0,255)">="100%"</span> <span style="COLOR: rgb(0,0,255)">></span> </font> <span style="COLOR: rgb(0,0,0)"> <br /> <font face="Arial"> <img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align="top" />    </font> </span> <font face="Arial"> <span style="COLOR: rgb(0,0,255)"><</span> <span style="COLOR: rgb(128,0,0)">tr</span> <span style="COLOR: rgb(0,0,255)">></span> </font> <span style="COLOR: rgb(0,0,0)"> <br /> <font face="Arial"> <img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align="top" />      </font> </span> <font face="Arial"> <span style="COLOR: rgb(0,0,255)"><</span> <span style="COLOR: rgb(128,0,0)">td</span> <span style="COLOR: rgb(0,0,255)">></span> </font> <font face="Arial"> <span style="COLOR: rgb(0,0,0)">Login ID:<br /><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align="top" />        </span> <span style="COLOR: rgb(0,0,255)"><</span> <span style="COLOR: rgb(128,0,0)">input </span> <span style="COLOR: rgb(255,0,0)">type</span> <span style="COLOR: rgb(0,0,255)">="text"</span> <span style="COLOR: rgb(255,0,0)"> name</span> <span style="COLOR: rgb(0,0,255)">="loginId"</span> <span style="COLOR: rgb(255,0,0)"> width</span> <span style="COLOR: rgb(0,0,255)">=100 </span> <span style="COLOR: rgb(0,0,255)">/></span> <span style="COLOR: rgb(255,0,0)">&nbsp;&nbsp;</span> </font> <span style="COLOR: rgb(0,0,0)"> <br /> <font face="Arial"> <img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align="top" />          Password:<br /><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align="top" />        </font> </span> <font face="Arial"> <span style="COLOR: rgb(0,0,255)"><</span> <span style="COLOR: rgb(128,0,0)">input </span> <span style="COLOR: rgb(255,0,0)">type</span> <span style="COLOR: rgb(0,0,255)">="password"</span> <span style="COLOR: rgb(255,0,0)"> name</span> <span style="COLOR: rgb(0,0,255)">="loginPassword"</span> <span style="COLOR: rgb(255,0,0)"> width</span> <span style="COLOR: rgb(0,0,255)">=100 </span> <span style="COLOR: rgb(0,0,255)">/></span> <span style="COLOR: rgb(255,0,0)">&nbsp;&nbsp;</span> </font> <span style="COLOR: rgb(0,0,0)"> <br /> <font face="Arial"> <img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align="top" />        </font> </span> <font face="Arial"> <span style="COLOR: rgb(0,0,255)"><</span> <span style="COLOR: rgb(128,0,0)">input </span> <span style="COLOR: rgb(255,0,0)">type</span> <span style="COLOR: rgb(0,0,255)">="submit"</span> <span style="COLOR: rgb(255,0,0)"> value</span> <span style="COLOR: rgb(0,0,255)">="Login"</span> <span style="COLOR: rgb(255,0,0)"> </span> <span style="COLOR: rgb(0,0,255)">/></span> </font> <span style="COLOR: rgb(0,0,0)"> <br /> <font face="Arial"> <img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align="top" />      </font> </span> <font face="Arial"> <span style="COLOR: rgb(0,0,255)"></</span> <span style="COLOR: rgb(128,0,0)">td</span> <span style="COLOR: rgb(0,0,255)">></span> </font> <span style="COLOR: rgb(0,0,0)"> <br /> <font face="Arial"> <img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align="top" />      </font> </span> <font face="Arial"> <span style="COLOR: rgb(0,0,255)"><</span> <span style="COLOR: rgb(128,0,0)">td </span> <span style="COLOR: rgb(255,0,0)">align</span> </font> <font face="Arial"> <span style="COLOR: rgb(0,0,255)">=right><br /><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align="top" />         </span> <span style="COLOR: rgb(255,0,0)">Hello, <ww:property value</span> <span style="COLOR: rgb(0,0,255)">="loginId"</span> <span style="COLOR: rgb(255,0,0)"> </span> <span style="COLOR: rgb(0,0,255)">/></span> </font> <span style="COLOR: rgb(0,0,0)"> <br /> <font face="Arial"> <img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align="top" />      </font> </span> <font face="Arial"> <span style="COLOR: rgb(0,0,255)"></</span> <span style="COLOR: rgb(128,0,0)">td</span> <span style="COLOR: rgb(0,0,255)">></span> </font> <span style="COLOR: rgb(0,0,0)"> <br /> <font face="Arial"> <img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align="top" />    </font> </span> <font face="Arial"> <span style="COLOR: rgb(0,0,255)"></</span> <span style="COLOR: rgb(128,0,0)">tr</span> <span style="COLOR: rgb(0,0,255)">></span> </font> <span style="COLOR: rgb(0,0,0)"> <br /> <font face="Arial"> <img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align="top" />  </font> </span> <font face="Arial"> <span style="COLOR: rgb(0,0,255)"></</span> <span style="COLOR: rgb(128,0,0)">table</span> <span style="COLOR: rgb(0,0,255)">></span> </font> <span style="COLOR: rgb(0,0,0)"> <br /> <font face="Arial"> <img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align="top" /> </font> </span> <font face="Arial"> <span style="COLOR: rgb(0,0,255)"></</span> <span style="COLOR: rgb(128,0,0)">form</span> <span style="COLOR: rgb(0,0,255)">></span> </font> <span style="COLOR: #0000ff"> <span style="COLOR: #ff0000"> <?xml:namespace prefix = ww /?> <ww:property value>< SPAN><span style="COLOR: #0000ff"><span style="COLOR: #0000ff"><span style="COLOR: #0000ff"><span style="COLOR: #0000ff"></span></span></span></span></ww:property value> </span> </span> </div> </div> <p> <font face="Arial" color="#000000">        需要注意的地方是form的action属性的写法了;<br />        2、在xwork.xml中增加相应的处理action的节?/font> </p> <div style="BORDER-RIGHT: windowtext 0.5pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: windowtext 0.5pt solid; PADDING-LEFT: 5.4pt; BACKGROUND: #e6e6e6; PADDING-BOTTOM: 4px; BORDER-LEFT: windowtext 0.5pt solid; WIDTH: 98%; PADDING-TOP: 4px; BORDER-BOTTOM: windowtext 0.5pt solid"> <div> <!--StartFragment --> <font face="Arial"> <span style="COLOR: rgb(0,0,255)"><</span><span style="COLOR: rgb(128,0,0)">action </span><span style="COLOR: rgb(255,0,0)">name</span><span style="COLOR: rgb(0,0,255)">="Login"</span><span style="COLOR: rgb(255,0,0)"> class</span><span style="COLOR: rgb(0,0,255)">="fantasysoft.webwork.Login"</span><span style="COLOR: rgb(0,0,255)">></span></font> <span style="COLOR: rgb(0,0,0)"> <br /> <font face="Arial"> <img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align="top" />   </font> </span> <font face="Arial"> <span style="COLOR: rgb(0,0,255)"><</span> <span style="COLOR: rgb(128,0,0)">result </span> <span style="COLOR: rgb(255,0,0)">name</span> <span style="COLOR: rgb(0,0,255)">="error"</span> <span style="COLOR: rgb(255,0,0)"> type</span> <span style="COLOR: rgb(0,0,255)">="dispatcher"</span> <span style="COLOR: rgb(0,0,255)">></span> <span style="COLOR: rgb(0,0,0)">index.jsp</span> <span style="COLOR: rgb(0,0,255)"></</span> <span style="COLOR: rgb(128,0,0)">result</span> <span style="COLOR: rgb(0,0,255)">></span> </font> <span style="COLOR: rgb(0,0,0)"> <br /> <font face="Arial"> <img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align="top" />   </font> </span> <font face="Arial"> <span style="COLOR: rgb(0,0,255)"><</span> <span style="COLOR: rgb(128,0,0)">result </span> <span style="COLOR: rgb(255,0,0)">name</span> <span style="COLOR: rgb(0,0,255)">="success"</span> <span style="COLOR: rgb(255,0,0)"> type</span> <span style="COLOR: rgb(0,0,255)">="dispatcher"</span> <span style="COLOR: rgb(0,0,255)">></span> <span style="COLOR: rgb(0,0,0)">index.jsp</span> <span style="COLOR: rgb(0,0,255)"></</span> <span style="COLOR: rgb(128,0,0)">result</span> <span style="COLOR: rgb(0,0,255)">></span> </font> <span style="COLOR: rgb(0,0,0)"> <br /> <font face="Arial"> <img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align="top" /> </font> </span> <font face="Arial"> <span style="COLOR: rgb(0,0,255)"></</span> <span style="COLOR: rgb(128,0,0)">action</span> <span style="COLOR: rgb(0,0,255)">></span> </font> <span style="COLOR: #0000ff"> <span style="COLOR: #0000ff"> <span style="COLOR: #0000ff"> <span style="COLOR: #000000"> <br /> <font face="Arial"> <img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align="top" /> </font> </span> </span> </span> </span> </div> </div> <p> <font face="Arial" color="#000000">        q里需要注意的是action节点中name的D与index.jsp中定义的action的名字要严格匚wQ对于大?/font> <font face="Arial" color="#000000">写是敏感的。在action节点中还包含?result>节点Q以说明处理action之后会可能出现的不同l果(name)和相应的处理方式(type)。譬如说Q如果Login的这个action处理success了,则用dispatcher结果分(dispatch)到相应的面。而在WAF框架中ƈ没有q样的定义,因ؓ在默认情况下如果不成功则会返回当前页面,不过可以定义FlowHandlerQƈ拥有cM的功能且更加灉|Q?br />        3、实现类Login的代码:</result></font> </p> <div style="BORDER-RIGHT: windowtext 0.5pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: windowtext 0.5pt solid; PADDING-LEFT: 5.4pt; BACKGROUND: #e6e6e6; PADDING-BOTTOM: 4px; BORDER-LEFT: windowtext 0.5pt solid; WIDTH: 98%; PADDING-TOP: 4px; BORDER-BOTTOM: windowtext 0.5pt solid"> <div> <font face="Arial"> <img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align="top" /> </font> <font face="Arial"> <span style="COLOR: #000000">package fantasysoft.webwork;<br /><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align="top" /><br /><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align="top" />import com.opensymphony.xwork.ActionSupport;<br /><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align="top" /><br /><img id="Codehighlighter1_116_679_Open_Image" onclick="this.style.display='none'; Codehighlighter1_116_679_Open_Text.style.display='none'; Codehighlighter1_116_679_Closed_Image.style.display='inline'; Codehighlighter1_116_679_Closed_Text.style.display='inline';" src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align="top" /><img id="Codehighlighter1_116_679_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_116_679_Closed_Text.style.display='none'; Codehighlighter1_116_679_Open_Image.style.display='inline'; Codehighlighter1_116_679_Open_Text.style.display='inline';" src="http://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif" align="top" /></span> <span style="COLOR: #0000ff">public</span> <span style="COLOR: #000000"> </span> <span style="COLOR: #0000ff">class</span> <span style="COLOR: #000000"> Login extends ActionSupport</span> <span id="Codehighlighter1_116_679_Closed_Text" style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"> <img src="http://www.cnblogs.com/Images/dot.gif" /> </span> </font> <span id="Codehighlighter1_116_679_Open_Text"> <font face="Arial"> <span style="COLOR: #000000">{<br /><img src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align="top" />    </span> <span style="COLOR: #0000ff">private</span> </font> <font face="Arial"> <span style="COLOR: #000000"> String loginId;<br /><img src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align="top" />    </span> <span style="COLOR: #0000ff">private</span> </font> <font face="Arial"> <span style="COLOR: #000000"> String loginPassword;<br /><img src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align="top" /><br /><img id="Codehighlighter1_218_254_Open_Image" onclick="this.style.display='none'; Codehighlighter1_218_254_Open_Text.style.display='none'; Codehighlighter1_218_254_Closed_Image.style.display='inline'; Codehighlighter1_218_254_Closed_Text.style.display='inline';" src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" /><img id="Codehighlighter1_218_254_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_218_254_Closed_Text.style.display='none'; Codehighlighter1_218_254_Open_Image.style.display='inline'; Codehighlighter1_218_254_Open_Text.style.display='inline';" src="http://www.cnblogs.com/Images/OutliningIndicators/ContractedSubBlock.gif" align="top" />    </span> <span style="COLOR: #0000ff">public</span> <span style="COLOR: #000000"> String getLoginPassword() </span> <span id="Codehighlighter1_218_254_Closed_Text" style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"> <img src="http://www.cnblogs.com/Images/dot.gif" /> </span> </font> <span id="Codehighlighter1_218_254_Open_Text"> <font face="Arial"> <span style="COLOR: #000000">{<br /><img src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align="top" />        </span> <span style="COLOR: #0000ff">return</span> </font> <span style="COLOR: #000000"> <font face="Arial"> loginPassword;<br /><img src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" />    }</font> </span> </span> <span style="COLOR: #000000"> <br /> <font face="Arial"> <img id="Codehighlighter1_311_361_Open_Image" onclick="this.style.display='none'; Codehighlighter1_311_361_Open_Text.style.display='none'; Codehighlighter1_311_361_Closed_Image.style.display='inline'; Codehighlighter1_311_361_Closed_Text.style.display='inline';" src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" /> <img id="Codehighlighter1_311_361_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_311_361_Closed_Text.style.display='none'; Codehighlighter1_311_361_Open_Image.style.display='inline'; Codehighlighter1_311_361_Open_Text.style.display='inline';" src="http://www.cnblogs.com/Images/OutliningIndicators/ContractedSubBlock.gif" align="top" />    </font> </span> <font face="Arial"> <span style="COLOR: #0000ff">public</span> <span style="COLOR: #000000"> </span> <span style="COLOR: #0000ff">void</span> <span style="COLOR: #000000"> setLoginPassword(String loginPassword) </span> <span id="Codehighlighter1_311_361_Closed_Text" style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"> <img src="http://www.cnblogs.com/Images/dot.gif" /> </span> </font> <span id="Codehighlighter1_311_361_Open_Text"> <font face="Arial"> <span style="COLOR: #000000">{<br /><img src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align="top" />        </span> <span style="COLOR: #0000ff">this</span> <span style="COLOR: #000000">.loginPassword </span> <span style="COLOR: #000000">=</span> </font> <span style="COLOR: #000000"> <font face="Arial"> loginPassword;<br /><img src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" />    }</font> </span> </span> <span style="COLOR: #000000"> <br /> <font face="Arial"> <img id="Codehighlighter1_394_424_Open_Image" onclick="this.style.display='none'; Codehighlighter1_394_424_Open_Text.style.display='none'; Codehighlighter1_394_424_Closed_Image.style.display='inline'; Codehighlighter1_394_424_Closed_Text.style.display='inline';" src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" /> <img id="Codehighlighter1_394_424_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_394_424_Closed_Text.style.display='none'; Codehighlighter1_394_424_Open_Image.style.display='inline'; Codehighlighter1_394_424_Open_Text.style.display='inline';" src="http://www.cnblogs.com/Images/OutliningIndicators/ContractedSubBlock.gif" align="top" />    </font> </span> <font face="Arial"> <span style="COLOR: #0000ff">public</span> <span style="COLOR: #000000"> String getLoginId() </span> <span id="Codehighlighter1_394_424_Closed_Text" style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"> <img src="http://www.cnblogs.com/Images/dot.gif" /> </span> </font> <span id="Codehighlighter1_394_424_Open_Text"> <font face="Arial"> <span style="COLOR: #000000">{<br /><img src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align="top" />        </span> <span style="COLOR: #0000ff">return</span> </font> <span style="COLOR: #000000"> <font face="Arial"> loginId;<br /><img src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" />    }</font> </span> </span> <span style="COLOR: #000000"> <br /> <font face="Arial"> <img id="Codehighlighter1_469_507_Open_Image" onclick="this.style.display='none'; Codehighlighter1_469_507_Open_Text.style.display='none'; Codehighlighter1_469_507_Closed_Image.style.display='inline'; Codehighlighter1_469_507_Closed_Text.style.display='inline';" src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" /> <img id="Codehighlighter1_469_507_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_469_507_Closed_Text.style.display='none'; Codehighlighter1_469_507_Open_Image.style.display='inline'; Codehighlighter1_469_507_Open_Text.style.display='inline';" src="http://www.cnblogs.com/Images/OutliningIndicators/ContractedSubBlock.gif" align="top" />    </font> </span> <font face="Arial"> <span style="COLOR: #0000ff">public</span> <span style="COLOR: #000000"> </span> <span style="COLOR: #0000ff">void</span> <span style="COLOR: #000000"> setLoginId(String loginId) </span> <span id="Codehighlighter1_469_507_Closed_Text" style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"> <img src="http://www.cnblogs.com/Images/dot.gif" /> </span> </font> <span id="Codehighlighter1_469_507_Open_Text"> <font face="Arial"> <span style="COLOR: #000000">{<br /><img src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align="top" />        </span> <span style="COLOR: #0000ff">this</span> <span style="COLOR: #000000">.loginId </span> <span style="COLOR: #000000">=</span> </font> <span style="COLOR: #000000"> <font face="Arial"> loginId;<br /><img src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" />    }</font> </span> </span> <span style="COLOR: #000000"> <br /> <font face="Arial"> <img id="Codehighlighter1_553_677_Open_Image" onclick="this.style.display='none'; Codehighlighter1_553_677_Open_Text.style.display='none'; Codehighlighter1_553_677_Closed_Image.style.display='inline'; Codehighlighter1_553_677_Closed_Text.style.display='inline';" src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" /> <img id="Codehighlighter1_553_677_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_553_677_Closed_Text.style.display='none'; Codehighlighter1_553_677_Open_Image.style.display='inline'; Codehighlighter1_553_677_Open_Text.style.display='inline';" src="http://www.cnblogs.com/Images/OutliningIndicators/ContractedSubBlock.gif" align="top" />    </font> </span> <font face="Arial"> <span style="COLOR: #0000ff">public</span> <span style="COLOR: #000000"> String execute() throws Exception</span> <span id="Codehighlighter1_553_677_Closed_Text" style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"> <img src="http://www.cnblogs.com/Images/dot.gif" /> </span> </font> <span id="Codehighlighter1_553_677_Open_Text"> <font face="Arial"> <span style="COLOR: #000000">{             <br /><img src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align="top" />        </span> <span style="COLOR: #0000ff">if</span> <span style="COLOR: #000000"> (!checkUserId()</span> <span style="COLOR: #000000">) </span> <span style="COLOR: #0000ff">return</span> </font> <font face="Arial"> <span style="COLOR: #000000"> ERROR;  // checkUserId is the method that will be implemented<br /><img src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align="top" />            </span> <span style="COLOR: #0000ff">else</span> <span style="COLOR: #000000"> </span> <span style="COLOR: #0000ff">return</span> </font> <span style="COLOR: #000000"> <font face="Arial"> SUCCESS;<br /><img src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" />    }</font> </span> </span> <span style="COLOR: #000000"> <br /> <font face="Arial"> <img src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align="top" />}</font> </span> </span> </div> </div> <p> <font face="Arial"> <font color="#000000">        在代码中Q你会发现有两个l承变量ERROR与SUCCESS。这两个变量是定义在Actionq个接口的,而ActionSupport则实CAction接口。在接口Action的代码中Q我们可以看到ERROR = "error"、SUCCESS = "success"。我们可以发现这两个变量的gxwork.xml中result子节点中的name的值是相匹配。除此之外,在代码中Q我也找不到了原来在开发中l常要用到的一个APIQgetParameter。事实上Q将表单中数据析取出来的工作是由webworkq个唯一定义的servletd成的Q而这个类会调用LogincMset的方法将用户输入的数据赋lLogincȝ属性:loginId和loginPassword。在q里Q我们也要跟前面index.jsp中的包含的标{联pv来。当数据被dispatch回index.jsp的时候,在index.jsp面render的过E中是调用了get的方法去获取相应的数据的?br />        最后,我们可以ȝ一下,整个Web应用E序的处理流E了Q?br />        首先Q当用户提交了表?form)至Login.action后,由web.xml中定义的唯一的一个servletQwebworkd理这个请求。webwork会以action的nameQLogin到xwork.xml中寻扄应的处理action的类Q于是就扑ֈ了fantasysoft.webwork包中的Loginc,由LogincM的executeҎ来处理提交的form的数据了Q?br />        然后Q根据executeҎ的返回|再到xwork.xml中对应的action节点中去扑֌配的result子节点;<br />        最后,Ҏresult子节点的定义Q将处理l果分发(dispatch)或者重定向(redirect)至下一个页?sup>[3]</sup>?/font> <br /> </font> <font color="#000000"> <font face="Arial">        <br /><!--StartFragment -->        [1] 准备工作可以参?</font> <a > <font face="Arial">WebWork Getting Started</font> </a> <font face="Arial">Q?br />        [2] web.xml文g的具体内容,可以参?</font> <a > <font face="Arial">WebWork Tutorial Lesson 2  </font> </a> <font face="Arial">Q?br />        [3] 对于result的Type的更多介l,可以参?</font> <a > <font face="Arial">WebWork Tutorial Lesson 3</font> </a> <font face="Arial">     </font> </font> <font face="Arial"> </font> </p>/SPAN><img src ="http://www.tkk7.com/tory320/aggbug/89793.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.tkk7.com/tory320/" target="_blank">tory</a> 2006-12-24 22:42 <a href="http://www.tkk7.com/tory320/archive/2006/12/24/89793.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Ajaxhttp://www.tkk7.com/tory320/archive/2006/12/21/89376.htmltorytoryThu, 21 Dec 2006 14:40:00 GMThttp://www.tkk7.com/tory320/archive/2006/12/21/89376.htmlhttp://www.tkk7.com/tory320/comments/89376.htmlhttp://www.tkk7.com/tory320/archive/2006/12/21/89376.html#Feedback0http://www.tkk7.com/tory320/comments/commentRss/89376.htmlhttp://www.tkk7.com/tory320/services/trackbacks/89376.html阅读全文

tory 2006-12-21 22:40 发表评论
]]>
(?重蝲overloading和覆写overriding哪个更早执行-- visitor帮助?http://www.tkk7.com/tory320/archive/2006/12/18/88651.htmltorytoryMon, 18 Dec 2006 14:38:00 GMThttp://www.tkk7.com/tory320/archive/2006/12/18/88651.htmlhttp://www.tkk7.com/tory320/comments/88651.htmlhttp://www.tkk7.com/tory320/archive/2006/12/18/88651.html#Feedback0http://www.tkk7.com/tory320/comments/commentRss/88651.htmlhttp://www.tkk7.com/tory320/services/trackbacks/88651.html 重蝲overloading和覆写overriding哪个更早执行-- visitor帮助?

重蝲overloading和覆写overriding哪个更早执行--   visitor帮助?
一Q问题提?br />虽然我们l常写程序用到重载和覆写Q但是很会考虑他们的执行顺序。下边的内容是关于Q他们同时出现时
哪个先v作用Q?br />二:问题分析
Java?动态单分派静态多分派语言"Q这个定义已l多ơ提P如果你不了解q些概念Q看q里"visitor模式准备"
所以就注定了重?静态多分派)要早于覆?动态单分派)Q因为静态分z是~绎期实现的Q动态分z是执行期实现的?br />三:验证
单验证一下,变提高记忆

 1 public   class  Parent  {
 2      public   void  run(Object o) {
 3         System.out.println( " in Parent +param:object " );
 4     }

 5      public   void  run( int  i) {
 6         System.out.println( " in Parent + param:int " );
 7     }

 8 }

 9
10 public   class  Child  extends  Parent  {
11
12      public   void  run(Object o) {
13         System.out.println( " in Child +param:Object " );
14     }

15      public   void  run(String str) {
16         System.out.println( " in Child + param:String " );
17     }

18      public   static   void  main(String[] args)  {
19         Parent p  =   new  Child();
20         String str  =   new  String();
21         p.run(str);
22     }

23 }


q行l果是什么?
in Child +param:Object
inChild是确认的Q但是ؓ什么是objectQ而不是StringQ我们放入的是String啊?br />首先来分析执行过E?br />定义韦类型Parent p在执行run(Str)的时候,

1Q如果是先执行重载,然後是执行覆写的q程
重蝲时因为找不到对应的String参数的函敎ͼ所以定位到接受父类的run(Object o)函数Q?br />覆写时因Z入时父类告诉子类的对象类型是ObjectQ所以执行run(Object o);
正是我们看到的结果,所以在Java中执行的序是这L?/p>

2Qؓ了对比,说一下先覆写后重载的q程
如果是先覆写Q再重蝲
覆写时因为确定对象实际是子类Q所以直接覆写到ChildQ然後重载,发现有对应的String为参数的函数
执行Qrun(String str);
应该输出的结?in Child +param:String
但我们看到结果显然是1Q所以验证了Java是先重蝲后覆写的?/p>


最后的部分Q?/p>

看完本文Q如果你对visitor模式有更多的兴趣Q想了解更多L如下几篇文章?br />1,静态分z,动态分z,多分z,单分z?--------------   visitor模式准备
2,讉K差异cd的集合类 ------------------------   visitor模式入门
3,visitor模式理论及学术概?------------Q?----   visitor模式深入
4,visitor模式和其它模式的比较和关p?------------   visitor模式ȝ 
5Q重载overloading和覆写overriding哪个更早执行--   visitor帮助?Q本文)
虽然排列序?,2,3,4,5 但是我个人徏议的学习方式?,1,3,4,5因ؓq个序更方便一般h理解



tory 2006-12-18 22:38 发表评论
]]>
(?使用Eclipse RCPq行桌面E序开?/title><link>http://www.tkk7.com/tory320/archive/2006/12/10/86639.html</link><dc:creator>tory</dc:creator><author>tory</author><pubDate>Sun, 10 Dec 2006 00:59:00 GMT</pubDate><guid>http://www.tkk7.com/tory320/archive/2006/12/10/86639.html</guid><wfw:comment>http://www.tkk7.com/tory320/comments/86639.html</wfw:comment><comments>http://www.tkk7.com/tory320/archive/2006/12/10/86639.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.tkk7.com/tory320/comments/commentRss/86639.html</wfw:commentRss><trackback:ping>http://www.tkk7.com/tory320/services/trackbacks/86639.html</trackback:ping><description><![CDATA[所谓RCPQ就是Rich Client Platform的羃写,卛_客户q_Q是Eclipseq化的物(?.0版以后出玎ͼQ是Eclipsel织向用h供的强大的开放性开发^収ͼ能够使用h便地创徏自己的基于Eclipse的应用程序,q且q些应用E序能够得到Eclipse的底层支持。更重要的是Q我们可以利用Java创徏象Eclipseq么漂亮的桌面程序?br /><br />  我相信,在未来的几年里,RCP一定会变得非常行。用RCPQ我们可以开发界面象Eclipseq样漂亮的桌面程序,比如医院理pȝ啊、CAD软g{等。遗憄是,目前在国内基本上找不到关于RCP的中文资料,我们只能通过自己的探索来为我们的E序d我们惌的功能?br /><br />  下面让我们一步一步来建立一个Eclipse RCPE序Q下面的内容可以说在Google上一搜一大把Q有些h会觉得乏呻I但是没关p,q只是一个快速的h?br /><br />  选择“新建-Q项目”,选择“插仉目”:<br /><img height="100" alt="rcp00.JPG" src="http://www.tkk7.com/images/blogjava_net/youxia/rcp00.JPG" width="539" border="1" /><br /><br /><img height="503" alt="rcp01.JPG" src="http://www.tkk7.com/images/blogjava_net/youxia/rcp01.JPG" width="532" border="1" /><br /><br />点下一步,输入目名称Q选择Eclipse版本Q我q里选择的是3.2Q?br /><img height="505" alt="rcp02.JPG" src="http://www.tkk7.com/images/blogjava_net/youxia/rcp02.JPG" width="533" border="1" /><br /><br />  点下一步,插g标识和插件名U可以更改,其他的内定w可以保持默认Q一定要记得选中富客h应用E序支持Q?br /><img height="506" alt="rcp03.JPG" src="http://www.tkk7.com/images/blogjava_net/youxia/rcp03.JPG" width="534" border="1" /><br /><br />  点下一步,选中一个模板,q里选一个最单的Q到时候看源代码的时候便于理解:<br /><img height="505" alt="rcp04.JPG" src="http://www.tkk7.com/images/blogjava_net/youxia/rcp04.JPG" width="534" border="1" /><br /><br />  点下一步,改一下应用程序标题:<br /><img height="505" alt="rcp05.JPG" src="http://www.tkk7.com/images/blogjava_net/youxia/rcp05.JPG" width="529" border="1" /><br /><br />  点完成,我们可以在项目上面点右键Q选择按EclipseE序q行Q就可以看到效果了:<br /><img height="407" alt="rcp16.JPG" src="http://www.tkk7.com/images/blogjava_net/youxia/rcp16.JPG" width="605" border="1" /><br /><br /><img height="304" alt="rcp17.JPG" src="http://www.tkk7.com/images/blogjava_net/youxia/rcp17.JPG" width="405" border="1" /><br /><br />  在这个程序中Q窗口上昄的是一个透视图,透视图中含有一个编辑器区域Q以后,我们可以逐步个程序添加菜单、工h和ؓq个透视图添加视图、编辑器{等?br /><br />  现在Q这个程序只能在Eclipse环境下运行,而RCP的目标是创徏可以独立q行的应用程序,我们的事情还没完呢。下一步,在项目上点右键,创徏产品配置文gQ?br /><img height="98" alt="rcp06.JPG" src="http://www.tkk7.com/images/blogjava_net/youxia/rcp06.JPG" width="458" border="1" /><br /><br />  输入产品配置文g名:<br /><br /><img height="628" alt="rcp07.JPG" src="http://www.tkk7.com/images/blogjava_net/youxia/rcp07.JPG" width="535" border="1" /><br /><br />  生成的品配|文件在~辑器中打开Q应该是q个样子的:<br /><img height="454" alt="rcp09.JPG" src="http://www.tkk7.com/images/blogjava_net/youxia/rcp09.JPG" width="567" border="1" /><br /><br />  刚开始,上面的几个文本框都是I的Q点新徏按钮之后Q弹出如下的对话框,输入产品名称后,点完成就行了?br /><br /><img height="418" alt="rcp08.JPG" src="http://www.tkk7.com/images/blogjava_net/youxia/rcp08.JPG" width="530" border="1" /><br /><br />  点击配置文g中的“启动程序”,我们可以试着启动我们的RCPE序。结果呢Q会出错。原因很单,因ؓ我们没有为我们的E序选中它依赖的插g?br /><br />   选中配置文g的“配|”选项卡,d以下几个依赖,CQ一定要把我们自己,也就是com.blogjava.youxia.rcp_start加进依赖,否则会出错。最开始的时候,是q么一点小问题Q让我浪费了几天旉?br /><img height="456" alt="rcp10.JPG" src="http://www.tkk7.com/images/blogjava_net/youxia/rcp10.JPG" width="571" border="1" /><br /><br />  再点L加必ȝ插gQ自动添加其它的依赖V?br /><br />  再下一步,讄目的构\径,如下图:<br /><img height="449" alt="rcp11.JPG" src="http://www.tkk7.com/images/blogjava_net/youxia/rcp11.JPG" width="569" border="1" /><br /><br />  下一步,导出我们的程序:<br /><img height="304" alt="rcp12.JPG" src="http://www.tkk7.com/images/blogjava_net/youxia/rcp12.JPG" width="339" border="1" /><br /><br /><img height="554" alt="rcp13.JPG" src="http://www.tkk7.com/images/blogjava_net/youxia/rcp13.JPG" width="532" border="1" /><br /><br />  点下一步,输入我们E序导出的目录,如下图:<br /><img height="555" alt="rcp14.JPG" src="http://www.tkk7.com/images/blogjava_net/youxia/rcp14.JPG" width="531" border="1" /><br /><br />  点完成按钮之后,我们的程序就导出到我们的指定的目录中了,打开q个目录Q可以看C个类似eclipse的程序图标,双击q行Q效果如下图Q?img height="515" alt="rcp15.JPG" src="http://www.tkk7.com/images/blogjava_net/youxia/rcp15.JPG" width="718" border="1" /><br /><br />  最后,需要说明两点:W一Q如果希望生成的E序有自q图标Q可以在产品配置文g中的最后两个配|文件中讄Q第二,生成的程序应该是没有菜单栏的Q因为我的Eclipse安装了MyEclipseQ所以导出的E序多了两个菜单?br /><br />  好了Q快速v步就到这里了Q以后再仔细研究生成的代码和为我们的E序d功能?img src ="http://www.tkk7.com/tory320/aggbug/86639.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.tkk7.com/tory320/" target="_blank">tory</a> 2006-12-10 08:59 <a href="http://www.tkk7.com/tory320/archive/2006/12/10/86639.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title> JAXP 专述 http://www.tkk7.com/tory320/archive/2006/11/25/83475.htmltorytorySat, 25 Nov 2006 09:27:00 GMThttp://www.tkk7.com/tory320/archive/2006/11/25/83475.htmlhttp://www.tkk7.com/tory320/comments/83475.htmlhttp://www.tkk7.com/tory320/archive/2006/11/25/83475.html#Feedback0http://www.tkk7.com/tory320/comments/commentRss/83475.htmlhttp://www.tkk7.com/tory320/services/trackbacks/83475.html JAXP 专述

Sun ?Java API for XML 语法分析

 

 

未显C需?JavaScript 的文档选项


 


U别: 初

Brett McLaughlin , Enhydra {略N, Lutris Technologies

2000 q?11 ?01 ?/p>

q是细?JAXPQSun ?Java API for XML 的文章,帮助解除了有?JAXP 本质和服务目的的疑惑。本文讲解了 JAXP 的基本概念,演示 XML 语法分析Z么需?JAXPQƈ昄如何L更改 JAXP 使用的语法分析器。本文还q一步讲qC SAX ?DOM q两个流行的?JAXP 相关?Java ?XML API?/blockquote>

Java ?XML 在每一个技术领域都刉了新闻Qƈ且对于Y件开发h员来_g?1999 q和 2000 q最重要的发展。结果,Java ?XML API 的数量激增。其中两个最行?DOM ?SAX q引h大兴,?JDOM 和数据绑?API 也接t而来。只透彻理解q些技术中的一个或两个是一艰巨Q务,而正用所有这些技术就会您成Z家。但在去q_另一?API lh留下了深d象,它就?Sun ?Java API for XMLQ通常UCؓ JAXP。如果考虑?Sun 在其q_上还没有M特定?XML 的品,那么q个q展׃ؓ奇。而o人惊奇的是h们对 JAXP 了解的缺乏。多C用它的开发h员在他们所用的q个 API 的概느解上都有错误?/p>

什么是 JAXPQ?/font>

本文假设您有 SAX ?DOM 的基本知识。这里实在没有够篇q来解释 SAX、DOM ?JAXP。如果您?XML 语法分析的新手,那么可能要通过联机资源阅读 SAX ?DOMQ或者浏览我的书。( 参考资?/font> 一节中有至 API 和我的书的链接。)获得基本知识后再看本文会比较好?





回页?/font>


API q是抽象Q?/font>

在讲解代码之前,介绍一些基本概念很重要。严格地_JAXP ?APIQ但是将其称为抽象层更准。它不提供处?XML 的新方式Q不补充 SAX ?DOMQ也不向 Java ?XML 处理提供新功能。(如果在这点上理解有误Q则本文正好适合您!Q它只是佉K过 DOM ?SAX 处理一些困难Q务更Ҏ。如果在使用 DOM ?SAX API 旉到特定于供应商的dQ它q通过独立于供应商的方式处理这些Q务成为可能?/p>

虽然要分别讲q所有这些特性,但是真正需要掌握的是:JAXP 不提供语法分析功?/i> Q没?SAX、DOM 或另一?XML 语法分析 APIQ就 无法分析 XML 语法 。有很多人曾让我?DOM、SAX ?JDOM ?JAXP q行Ҏ。但q行q些Ҏ是不可能的,因ؓ前三?API ?JAXP 的目的完全不同。SAX、DOM ?JDOM 都分?XML 语法。?JAXP 却提供到达这些语法分析器和结果的方式。它自n不提供分析文档语法的新方法。如果要正确使用 JAXPQ则一定要弄清q点。这您比其它 XML 开发h员领先一大截?

如果仍然怀疑(或认为我故弄玄虚Q,请从 Sun ?Web 站点下蝲 JAXP 分发Q请参阅 参考资?/font> 一节)Q然后就会知道基?JAXP 是什么。在包括?jar ( jaxp.jar ) ?只有六个c?/i> Q这?API 会有多难哪?所有这些类Q?javax.xml.parsers 包的一部分Q都位于现有语法分析器之上。这些类中的两个q用于错误处理。JAXP 比h们想象的要简单得多。那么,Z么还感到困惑哪?





回页?/font>


Sun ?JAXP ?Sun 的语法分析器

JAXP 下蝲时包?Sun 的语法分析器。所?parser 器类作ؓ com.sun.xml.parser 包和相关子包的一部分位于 parser.jar 档案中。应该知道,该语法分析器Q代码名?CrimsonQ??/i> ?JAXP 自n的一部分。它?JAXP 版本的一部分Q但不是 JAXP API 的一部分。o人困惑吗Q有一炏V换q种方式xQJDOM ?Apache Xerces 语法分析器一h供。该语法分析器不?JDOM 的一部分Q但?JDOM 使用Q所以包括它Q以保 JDOM 可以单独使用。JAXP 也是如此Q但不象 JDOM 那样好表达:JAXP ?Sun 的语法分析器一h供,以便可以立即使用。但是,很多人将 Sun 的语法分析器中包括的cd?JAXP API 的一部分。例如,新闻l中一个常见的问题是:“怎样使用 JAXP 中的 XMLDocument c?其目的是什么?”这个答案可有些复杂?

首先Q?com.sun.xml.tree.XMLDocument cM?JAXP 的一部分。它?Sun 语法分析器的一部分。所以,q个问题从一开始就lh以误对{其ơ,JAXP 的整个意义在于在处理语法分析器时提供供应商独立性。?JAXP 的同一代码可以?Sun ?XML 语法分析器、Apache ?Xerces XML 语法分析器和 Oracle ?XML 语法分析器一起用。而用特定于 Sun 的类是个坏主意。这?JAXP 的整个意义相背离。现在看出来q个问题怎样h概念了吗Q语法分析器?JAXP 发行版本Q至是 Sun 的版本)中的 API 被؜Z谈,开发h员将其中一个的cdҎ当成是另一个的了,反之亦然?





回页?/font>


旧和?/font>

关于 JAXPQ最后需要指出的是:使用 JAXP 有一些缺陗例如,JAXP 只支?SAX 1.0 ?DOM W一层规范。SAX 2.0 ?2000 q?5 月v完成,DOM W二层规范支持甚臛_大多数语法分析器中存在更长时间。DOM W二层规范还没有完成Q但实_E_以用于生产。这两个 API 的新版本都有重大改进Q最明显的是?XML 名称I间的支持。该支持q允许“XML Schema 认”,q个?XML 相关的另一热门技术。公q__?JAXP 发布 1.0 最l发行版ӞSAX 2.0 ?DOM W一层规范都q没有完成。但是,׃没有包括q些新版本,实为开发h员带来很大不ѝ?/p>

q可以?JAXPQ但是也可以{待 JAXP 1.1Q它支持 SAX 2.0 ?DOMW二层规?。否则,发玎ͼJAXP 提供的优点以 SAX ?DOM 最新版本中的功能ؓ代hQƈ使应用程序更加难以编码。无论是否等待下一?JAXP 发行版,都要留意q个问题。如果将 JAXP 与语法分析器一起用,而语法分析器支持?DOM ?SAX 版本?JAXP 支持的要高,则可能会有类路径问题。所以,事先留意一下,q且Q一旦有 JAXP 1.1Q马上升U。基本理?JAXP 之后Q让我们看一?JAXP 依赖?APIQSAX ?DOM?/p>



回页?/font>


?SAX 开?/font>

SAX QSimple API for XMLQ是用于处理 XML 的事仉动方法。它基本p多回调函数组成。例如,每当 SAX 语法分析器遇到元素的开始标记时p?startElement() 。对于字W串Q将调用 characters() 回调函数Q然后在元素l束标记处调?endElement() 。还有很多回调函数用于文档处理、错误和其它词汇l构。现在知道这是怎么回事了。SAX E序员实C个定义这些回调函数的 SAX 接口。SAX q实C个名?HandlerBase 的类Q该cd现所有这些回调函敎ͼq提供所有这些回调方法的~省I实现。(提到q一Ҏ因ؓ它在后面讲到?DOM 中很重要。)SAX 开发h员只需扩展q个c,然后实现需要插入特定逻辑的方法。所以,SAX 的关键在于ؓq些不同的回调函数提供代码,然后允许语法分析器在适当的时候触发这些回调函C的每一个?

因此Q典型的 SAX q程如下Q?/p>

  • 用特定供应商的语法分析器实现创徏一?SAXParser 实例
  • 注册回调实现Q例如,通过使用扩展 HandlerBase 的类Q?
  • 开始进行语法分析,然后在触发回调实现时{待

JAXP ?SAX lg提供执行所有这些步骤的单方式。如果没?JAXPQSAX 语法分析器要直接从供应商c(?org.apache.xerces.parsers.SAXParser Q进行实例化Q或者必M用名?ParserFactory 的帮助类。第一个方法的问题很明显:不独立于供应商。第二个Ҏ的问题在于类厂需要一个自变量Q即要用的语法分析器类的字W串名称Q还是那?Apache c?org.apache.xerces.parsers.SAXParser Q。可以通过不同语法分析器作ؓ String 传递来更改语法分析器。用这U方法不必更改Q?import 语句Q但是还是要重新~译cR这昄不是最佌x案。如果能够不重新~译c而更改语法分析器Q可能会单得多,是不是这样呢Q?

JAXP 提供了更好的替代ҎQ它允许语法分析器作ؓ Java pȝ属性来提供。当Ӟ当从 Sun 下蝲版本Ӟ得C?Sun 语法分析器的 JAXP 实现。可以从 Apache XML Web 站点下蝲?Apache Xerces 上构建其实现的相?JAXP 接口。因此(无论哪一U情况)Q更Ҏ在用的语法分析器需要更改类路径讄Q即从一U语法分析器实现更改到另一个,但是 ?/i>要求重新~译代码。这是 JAXP 的魔力,或抽象性?

SAX 语法分析器一?/font>

JAXP SAXParserFactory cL能够L更改语法分析器实现的关键所在。必d个类的新实例Q等一会将讲到Q。创建新实例之后Q类厂提供一个方法来获得支持 SAX 的语法分析器。在内部QJAXP 实现处理依赖于供应商的代码,使您的代码不受媄响。这个类厂还提供其它一些优UҎ?

除创?SAX 语法分析器实例的基本工作之外Q类厂还允许讄配置选项。这些选项影响所有通过cd获得的语法分析器实例。JAXP 1.0 中两个可用的功能是设|名U空间敏感?( setNamespaceAware (boolean awareness))Q和打开认 ( setValidating (boolean validating))。请CQ一旦设|了q些选项Q在调用该方法之后,它们媄?所?/i>?cd获得的实例?

讄了类厂之后,调用 newSAXParser() 返回一个随时可用的 JAXP SAXParser cd例。这个类装了一个下层的 SAX 语法分析器(SAX c?org.xml.sax.Parser 的实例)。它q防止向语法分析器类dM特定于供应商的附加功能。(q记得以前对 XmlDocument 的讨论吗Q)q个cd以开始进行实际的语法分析。以下清单显C如何创建、配|和使用 SAX cd?


清单 1. 使用 SAXParserFactory
												
														import java.io.File;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.Writer;

// JAXP
import javax.xml.parsers.FactoryConfigurationError;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParserFactory;
import javax.xml.parsers.SAXParser;

// SAX
import org.xml.sax.AttributeList;
import org.xml.sax.HandlerBase;
import org.xml.sax.SAXException;

public class TestSAXParsing {

 public static void main(String[] args) {
 try {
 if (args.length != 1) {
 System.err.println ("Usage: java TestSAXParsing [filename]");
 System.exit (1);
 }

 // 获得SAX 语法分析器类?
 SAXParserFactory factory = SAXParserFactory.newInstance();

 //讄讄名称I间敏感性选项Q关掉确认选项
 factory.setValidating(true);
 factory.setNamespaceAware(false);

 SAXParser parser = factory.newSAXParser();
 parser.parse(new File(args[0]), new MyHandler());

 } catch (ParserConfigurationException e) {
 System.out.println("The underlying parser does not support " +
 " the requested features.");
 } catch (FactoryConfigurationError e) {
 System.out.println("Error occurred obtaining SAX Parser Factory.");
 } catch (Exception e) {
 e.printStackTrace();
 }
 }
}

class MyHandler extends HandlerBase {
 //通过 DocumentHandler, ErrorHandler{实现的SAX回调函数
}

												
										

h意,在这D代码中Q在使用cd时可能发生两个特定于 JAXP 的问题:无法获得或配|?SAX cdQ以及无法配|?SAX 语法分析器。当无法获得 JAXP 实现中指定的语法分析器或pȝ属性时Q通常会发生第一个问?FactoryConfigurationError 。当正在使用的语法分析器中的Ҏ不可用Ӟ会发生第二个问题 ParserConfigurationException 。这两个问题都容易处理,应该不会?JAXP 的用造成M困难?

在获得类厂、关闭名U空间ƈ打开“确认”之后,获?SAXParser Q然后开始语法分析。请注意Q?SAX 语法分析器的 parse() Ҏ取得前面提到?SAX HandlerBase cȝ一个实例。(可以通过完整?Java 清单 查看该类的实?/font> 。)q要传递要q行语法分析的文件。但是, SAXParser 所包含的远不止q一个方法?

使用 SAX 语法分析?/font>

获得 SAXParser cȝ实例之后Q除了向语法分析器传?File q行语法分析之外Q还可以用它做更多的事。由于如今大型应用中的应用程序组件之间通信方式Q“对象实例创就是其使用者”这L假定q不L安全的。换句话_一个组件可能创?SAXParser 实例Q而另一lgQ可能由另一开发h员编码)可能需要用那个实例。由于这个原因,提供了一些方法来定语法分析器的讄。执行此d的两个方法是 isValidating() Q它通知调用E序Q语法分析器要、或不要执行“确认”,以及 isNamespaceAware() Q它q回一个指C,说明语法分析器可以或不可以处?XML 文档中的名称I间。虽然这些方法能提供有关语法分析器可以执行功能的信息Q但是无法更改这些特性。必d语法分析器类厂别执行该操作?

另外Q有多种Ҏ来请求对文档q行语法分析。除了只接受 File ?SAX HandlerBase 实例QSAXParser ?parse() Ҏq能?String 形式接受 SAX InputSource 、Java InputStream ?URLQ所有这些都要与 HandlerBase 实例一h供。所以,不同cd的输入文档可以用不同方式的语法分析来处理?

最后,可以直接通过 SAXParser ?getParser() Ҏ获得和用下层的 SAX 语法分析器( org.xml.sax.Parser 的实例)。获得这个下层实例之后,可以获得通常?SAX Ҏ。下一个清单显C?SAXParser c(q个 JAXP ?SAX 语法分析的核心类Q的各种使用CZ?


清单 2. 使用 JAXP SAXParser
												
														 //获得SAXP的一个实?
 SAXParser saxParser = saxFactory.newSAXParser();

 //查看是否支持 Validate 选项
 boolean isValidating = saxParser.isValidating();

 //查看是否支持 namespace 选项
 boolean isNamespaceAware = saxParser.isNamespaceAware();

 // q用一个File 和一个SAX HandlerBase 的实例进行多UŞ式的语法分析
 saxParser.parse(new File(args[0]), myHandlerBaseInstance);

 // q用一?SAX InputSource实例 和一?SAX HandlerBase 实例
 saxParser.parse(mySaxInputSource, myHandlerBaseInstance);

 //q用一?InputStream 实例和一个SAX HandlerBase 实例
 saxParser.parse(myInputStream, myHandlerBaseInstance);

 // q用一?URI 和一个SAX HandlerBase 实例
 saxParser.parse("http://www.newInstance.com/xml/doc.xml", myHandlerBaseInstance);

 //获得底层的(装QSAX 语法分析?
 org.xml.sax.Parser parser = saxParser.getParser();

 //利用底层的语法分析器
 parser.setContentHandler(myContentHandlerInstance);
 parser.setErrorHandler(myErrorHandlerInstance);
 parser.parse(new org.xml.sax.InputSource(args[0]));

												
										

目前为止Q关?SAX 已经讲了很多Q但是还没有揭示M不寻常或令h惊奇的东ѝ事实上QJAXP 的功能很,特别是当 SAX 也牵涉进来时。这很好Q因为有最的功能性意味着代码可移植性更强,q可以由其他开发h员与M?SAX 兼容?XML 语法分析器一起用,无论是免费(通过开放源码,希望如此Q还是通过商业途径。就是这栗在 JAXP 中?SAX 没有更多的东ѝ如果已l知?SAXQ那么现在已l掌握大U?98% 的内宏V只需学习两个新类和两?Java 异常Q您可以开始了。如果从没用过 SAXQ那也很单,现在可以开始?/p>



回页?/font>


处理 DOM

如果要休息以q接 DOM 挑战Q那么先别休息。在 JAXP 中?DOM 的过E与 SAX 几乎相同Q所要做的全部只是更改两个类名和一个返回类型,q样差不多了。如果理?SAX 的工作原理和 DOM 是什么,则不会有M问题?/p>

DOM ?SAX 的主要差异是它们?API l构。SAX 包含一个基于事件的回调函数集,?DOM 有一个内存中的树状结构。换句话_?SAX 中,从不需要操作数据结构(除非开发h员手工创建)。因此,SAX 不提供修?XML 文档的功能。?DOM 正好提供q种cd的功能?org.w3c.dom.Document c表C?XML 文档Q它pC元素、属性和其它 XML l构?DOM 节点 l成。所以,JAXP 无需触发 SAX 回调Q它只负责从语法分析q回一?DOM Document 对象?

DOM 语法分析器类厂一?/font>

基本理解 DOM 以及 DOM ?SAX 的差异之后,没什么好说的了。以下代码看h?SAX 代码cM。首先,获得 DocumentBuilderFactory Q与 SAX 中的方式相同)。然后,配置cd来处理确认和名称I间Q与 SAX 中的方式相同)。下一步,从类厂中?DocumentBuilder Q它?SAXParser cMQ(?SAX 中的方式相同. . . 啊,您都知道了)。然后,可以进行语法分析了Q生的 DOM Document 对象传递给打印 DOM 树的Ҏ?


清单 3. 使用文档构徏器类?/b>
												
														import java.io.File;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.Writer;

// JAXP
import javax.xml.parsers.FactoryConfigurationError;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.DocumentBuilder;

// DOM
import org.w3c.dom.Document;
import org.w3c.dom.DocumentType;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

public class TestDOMParsing {

 public static void main(String[] args) {
 try {
 if (args.length != 1) {
 System.err.println ("Usage: java TestDOMParsing [filename]");
 System.exit (1);
 }

 // 获得 Document Builder Factory
 DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();

 //打开认选项Q关掉名U空间敏感性选项?
 factory.setValidating(true);
 factory.setNamespaceAware(false);

 DocumentBuilder builder = factory.newDocumentBuilder();
 Document doc = builder.parse(new File(args[0]));

 // 从DOM C打印文档Qƈ加一初始I格
 printNode(doc, "");

 // 在这里也可以?DOM 文档q行修改
 } catch (ParserConfigurationException e) {
 System.out.println("The underlying parser does not support the requested features.");
 } catch (FactoryConfigurationError e) {
 System.out.println("Error occurred obtaining Document Builder Factory.");
 } catch (Exception e) {
 e.printStackTrace();
 }
 }

 private static void printNode(Node node, String indent) {
 // 打印 DOM ?
}

												
										

此代码中可能会出C个不同的问题Q与 JAXP 中的 SAX cMQ: FactoryConfigurationError ?ParserConfigurationException 。每一个的原因?SAX 中的相同。不是实现类 ( FactoryConfigurationError ) 中有问题Q就是语法分析器不支持请求的Ҏ?( ParserConfigurationException )。DOM ?SAX 的唯一差异是:?DOM 中,?DocumentBuilderFactory 替代 SAXParserFactory Q用 DocumentBuilder 替代 SAXParser 。就q么单!Q可?查看完整代码清单 Q该清单包括用于打印 DOM 树的Ҏ。)

使用 DOM 语法分析?/font>

有了 DOM cd之后Q就可以获得 DocumentBuilder 实例?DocumentBuilder 实例可以使用的方法与 SAX 的非常类伹{主要差异是 parse() 的变U不需?HandlerBase cȝ实例。它们返回表C法分析之后的 XML 文档?DOM Document 实例。另一唯一不同之处是:为类g SAX 的功能提供了两个ҎQ用 SAX ErrorHandler 实现来处理语法分析时可能出现的问题的 setErrorHandler() Q和?SAX EntityResolver 实现来处理实体解析的 setEntityResolver() 。如果不熟悉q些概念Q则需要通过联机或在我的书中学习 SAX。以下清单显CZ用这些方法的CZ?


清单 4. 使用 JAXP DocumentBuilder
												
														    //获得一?DocumentBuilder 实例
 DocumentBuilder builder = builderFactory.newDocumentBuilder();

 //查看是否支持 Validate 选项
 boolean isValidating = builder.isValidating();

  //查看是否支持 namespace 选项
 boolean isNamespaceAware = builder.isNamespaceAware();

 // 讄一?SAX ErrorHandler
 builder.setErrorHandler(myErrorHandlerImpl);

 // 讄一?SAX EntityResolver
 builder.setEntityResolver(myEntityResolverImpl);

 // q用多种Ҏ?file q行语法分析
 Document doc = builder.parse(new File(args[0]));

 // q用 SAX InputSource 
 Document doc = builder.parse(mySaxInputSource);

 // q用 InputStream
 Document doc = builder.parse(myInputStream, myHandlerBaseInstance);

 // q用 URI
 Document doc = builder.parse("http://www.newInstance.com/xml/doc.xml");

												
										

是不是感?DOM q一节有些o人厌烦?有这U想法的不止您一个,?DOM 代码有些令h厌烦是因为它是直接取得所学的 SAX 知识Q然后将其用?DOM。因此,和朋友、同事打赌吧Q说使用 JAXP 只是菜一?/p>



回页?/font>


更改语法分析?/font>

最后要探讨的主题是 JAXP L更改cdcM用的语法分析器的能力。更?JAXP 使用的语法分析器实际意味着更改 cdQ因为所?SAXParser ?DocumentBuilder 实例都来自这些类厂。既然确定装入哪个语法分析器的是cdQ因此,必须更改cd。可以通过讄 Java pȝ属?javax.xml.parsers.SAXParserFactory 来更改要使用?SAXParserFactory 接口实现。如果没有定义该属性,则返回缺省实玎ͼ供应商指定的M语法分析?。相同原理适用?DocumentBuilderFactory 实现。在q种情况下,查?javax.xml.parsers.DocumentBuilderFactory pȝ属性。就q么单,我们已经学完了!q就?SAXP 的全部:提供?SAX 的挂钩,提供?DOM 的挂钩,q允许轻易更改语法分析器?





回页?/font>


l束?/font>

如您所见,没多复杂的东西。更改系l属性,通过cd、而不是语法分析器或构建器来设|“确认”,以及弄清楚JAXP实际上不是h们通常所认ؓ的那Pq些是?JAXP 的最困难部分。除了没?SAX 2.0 ?DOMW二层规范支持之外,JAXP 在两个流行的 Java ?XML API 之上提供一个有帮助的可插入层。它使代码独立于供应商,q允怸~译语法分析代码而更改语法分析器。那么,?Sun、Apache XML 或其它方便之处下?JAXPQƈ使用它吧Ql关?JAXP 1.1Qƈ增加?SAX 2 ?DOM 2、XSLT 及更多内容的支持。您在q里获得W一手新闻,所以,请关?developerWorks?



tory 2006-11-25 17:27 发表评论
]]> վ֩ģ壺 Ƶվ| þþù޾Ʒ| 2019ĻѵӰ߲| 67paoǿ67194ҹ| òƵ| ޾Ʒ߹ۿ | þƷѹۿ| XOɫXO| ƷһʽӰ | Ʒþһ| պһƷ߲ƵһƷ| պþӰԺ | ɫƷһ| ޾ƷþëƬ| 97Ƶ| ػһһƬ| AVһ| ޹ƷƷ | ޹Ʒþþ| ѿAVëƬһ| ȫƵѹۿӾ| Ļ뱬app| ޹Ʒ˾Ʒ| ڵƵվ| ձһ| ͵͵޸| վ߲| ˾þþƷҹ| һҹߴ| 91㽶߹ۿ| һƷƵ߲ | Ůվ߿| þѹƵ| 뾫Ʒһ| 2020Ʒۺ| þþþAV鶹| ˳վ߹ۿ| vƬ߹ۿڵ| ëƬ߲| ÿƬѵƵ| ձѹۿ|