??xml version="1.0" encoding="utf-8" standalone="yes"?>亚洲毛片无码专区亚洲乱,亚洲精品综合一二三区在线,337p日本欧洲亚洲大胆人人http://www.tkk7.com/hallywang/archive/2007/03/12/103327.htmlHallyHallyMon, 12 Mar 2007 07:03:00 GMThttp://www.tkk7.com/hallywang/archive/2007/03/12/103327.htmlhttp://www.tkk7.com/hallywang/comments/103327.htmlhttp://www.tkk7.com/hallywang/archive/2007/03/12/103327.html#Feedback0http://www.tkk7.com/hallywang/comments/commentRss/103327.htmlhttp://www.tkk7.com/hallywang/services/trackbacks/103327.html  W一ơ握手:(x)建立q接Ӟ客户端发送syn?syn=j)到服务器Qƈq入SYN_SEND状态,{待服务器确认;

  W二ơ握手:(x)服务器收到syn包,必须认客户的SYNQack=j+1Q,同时自己也发送一个SYN包(syn=kQ,即SYN+ACK包,此时服务器进入SYN_RECV状态;

  W三ơ握手:(x)客户端收到服务器的SYNQACK包,向服务器发送确认包ACK(ack=k+1)Q此包发送完毕,客户端和服务器进入ESTABLISHED状态,完成三次握手?/p>

  完成三次握手Q客L(fng)与服务器开始传送数据,在上q过E中Q还有一些重要的概念Q?/p>

  未连接队列:(x)在三ơ握手协议中Q服务器l护一个未q接队列Q该队列为每个客L(fng)的SYN包(syn=jQ开设一个条目,该条目表明服务器已收到SYN包,q向客户发出认Q正在等待客L(fng)认包。这些条目所标识的连接在服务器处于Syn_RECV状态,当服务器收到客户的确认包Ӟ删除该条目,服务器进入ESTABLISHED状态?br />Backlog参数Q表C未q接队列的最大容Ux目?/p>

  SYN-ACK 重传ơ数 服务器发送完SYNQACK包,如果未收到客L(fng)认包Q服务器q行首次重传Q等待一D|间仍未收到客L(fng)认包Q进行第二次重传Q如果重传次数超q系l规定的最大重传次敎ͼpȝ该q接信息从半q接队列中删除。注意,每次重传{待的时间不一定相同?/p>

  半连接存?gu)zL_(d)(x)是指半连接队列的条目存活的最长时_(d)也即服务从收到SYN包到认q个报文无效的最长时_(d)该时间值是所有重传请求包的最长等待时间d。有时我们也U半q接存活旉为Timeout旉、SYN_RECV存活旉?/p>

Hally 2007-03-12 15:03 发表评论
]]>
POI处理Excel[z]http://www.tkk7.com/hallywang/archive/2006/10/25/77218.htmlHallyHallyWed, 25 Oct 2006 08:03:00 GMThttp://www.tkk7.com/hallywang/archive/2006/10/25/77218.htmlhttp://www.tkk7.com/hallywang/comments/77218.htmlhttp://www.tkk7.com/hallywang/archive/2006/10/25/77218.html#Feedback0http://www.tkk7.com/hallywang/comments/commentRss/77218.htmlhttp://www.tkk7.com/hallywang/services/trackbacks/77218.html本文阐q如何用POI来读?写入完整的Excel文g?br />  
  U定QPOI目2.0版现在已l接q正式发行阶D,开发进度迅速,不断有新的功能集成到原有的系l,同时也有对原有系l的修改?br />  
  Z(jin)保证本文的及(qing)时性,本文按照最q的1.9开发版说明。虽然编译最q的发行版源代码也能正常q行Q但现在的代码和2.0的发行版?x)有一些出入?br />  
  一、Excel基础
  
  Microsoft Excel 97文g格式也被UCؓ(f)BIFF8Q最q版本的Excel只对该格式作?jin)少量的改动。增加对新格式的支持除了(jin)增加目的复杂性之外,唯一的效果也许只是不得不使每个用户升U代码,没有什么实际的好处?br />  
  因此Q在下文说明中,凡是提到Excel 97格式的地方其实都是指Excel?7到XP的格式?br />  
  二、HSSF概况
  
  POI目实现的Excel 97文g格式UCؓ(f)HSSF??也许你已l猜刎ͼHSSF是Horrible SpreadSheet Format的羃写,也即“讨厌的?sh)子表格格式”(微Y使某些原本简单的事情q分复杂Q同时又q分单地处理?jin)某些原本需要灵zL的事情Q让Z胜佩服!Q?br />  
  也许HSSF的名字有Ҏ(gu)E,本质而言它是一个非怸肃、正规的API。通过HSSFQ你可以用纯Java代码来读取、写入、修改Excel文g?br />  
  前面一文章提C(jin)POIFSQ那么HSSF和POIFS又有什么关pdQ就象其他POI的API一PHSSF建立在POIFS的基上,因此在HSSF内的有些代码和前文的某些代码很相伹{不q,当我们编写基于HSSF API的代码时Q一般不需要了(jin)解POIFS API的细节?br />  
  HSSF取操作提供了(jin)两类APIQusermodel和eventusermodelQ即“用h型”和“事?用户模型”。前者很好理解,后者比较抽象,但操作效率要高得多。usermodel主要有org.apache.poi.hssf.usermodel和org.apache.poi.hssf.eventusermodel包实玎ͼ在HSSF的早期版本中Qorg.apache.poi.hssf.eventusermodel属于eventmodel包)(j)?br />  
  usermodel包把Excel文g映射成我们熟(zhn)的l构Q诸如Workbook、Sheet、Row、Cell{,它把整个l构以一l对象的形式保存在内存之中。eventusermodel要求用户熟?zhn)文g格式的底层结构,它的操作风格cM于XML的SAX API和AWT的事件模型(q就是eventusermodel名称的v源)(j)Q要掌握H门才能用好?br />  
  另外Qeventusermodel的API只提供读取文件的功能Q也是说不能用q个API来修Ҏ(gu)件?br />  
  三、通过usermodeld文g
  
  用HSSF的usermodeld文g很简单。首先创Z个InputStreamQ然后创Z个HSSFWorkbookQ?br />  
  InputStream myxls = new FileInputStream("workbook.xls"));
  HSSFWorkbook wb   = new HSSFWorkbook(myxls);
  
  有了(jin)HSSFWorkbook实例Q接下来可以提取工作表、工作表的行和列Q例如:(x)
  
  HSSFSheet sheet = wb.getSheetAt(0);    // W一个工作表
  HSSFRow row   = sheet.getRow(2);    // W三?br />  HSSFCell cell  = row.getCell((short)3); // W四个单元格
  
  上面q段代码提取出第一个工作表W三行第四单元格。利用单元格对象可以获得它的|提取单元格的值时h意它的类型:(x)
  
  if (cell.getCellType() == HSSFCell.CELL_TYPE_STRING) {
  ("单元格是字符Ԍ值是Q?" + cell.getStringCellValue());
  } else if (cell.getCellType() == HSSFCell.CELL_TYPE_NUMERIC) {
  ("单元格是数字Q值是Q?" + cell.getCellValue());
  } else () {
  ("单元格的g是字W串或数倹{?);
  }
  
  如果搞错?jin)数据类型,E序遇到异常。特别地Q用HSSF处理日期数据要小?j)。Excel内部以数值的形式保存日期数据Q区别日期数据的唯一办法是通过单元格的格式Q如果你曄在Excel中设|过日期格式Q应该明白这是什么意思)(j)?br />  
  因此Q对于包含日期数据的单元|cell.getCellType()返回HSSFCell.CELL_TYPE_NUMERICQ不q利用工具函数HSSFDateUtil.isCellDateFormatted(cell)可以判断出单元格的值是否ؓ(f)日期。isCellDateFormatted函数通过比较单元格的日期和Excel的内|日期格式得出结??可以惌Q按照这U判断方法,很多时候isCellDateFormatted函数?x)返回否定的l论Q存在一定的误判可能?br />  
  本文附录包含?jin)一个在Servlet环境中利用HSSF创徏和返回Excel工作的实例?br />  
  四、通过usermodel写入文g
  
  写入XLS文g比读取XLS文gq要单。创Z个HSSFWorkbook实例Q然后在适当的时候创Z个把文g写入盘的OutputStreamQ但延迟到处理结束时创徏OutputStream也可以:(x)
  
  HSSFWorkbook wb = new HSSFWorkbook();
  FileOutputStream fileOut
  = new FileOutputStream("workbook.xls");
  wb.write(fileOut);
  fileOut.close();
  
  创徏工作表及(qing)其内容必M相应的父对象出发Q例如:(x)
  
  HSSFSheet sheet = wb.createSheet();
  HSSFRow row   = sheet.createRow((short)0);
  HSSFCell cell  = row.createCell((short)0);
  cell.setCellValue(1);
  row.createCell((short)1).setCellValue(1.2);
  row.createCell((short)2).setCellValue("一个字W串");
  row.createCell((short)3).setCellValue(true);
  
  如果要设|单元格的样式,首先要创Z个样式对象,然后把它指定l一个单元格??或者把它指定给多个h相同样式的单元格Q例如,如果Excel表格中有一个摘要行Q摘要行的数据必L_体、斜体,你可以创Z个summaryRowStyle样式对象Q然后把q个样式指定l所有摘要行上的单元根{?br />  
  注意QCellFormat和CellStyle对象是工作簿对象的成员,单元格对象只是引用它们?br />  ...
  HSSFCellStyle style = workbook.createCellStyle();
  style.setDataFormat
  (HSSFDataFormat.getBuiltinFormat("($#,##0_);[Red]($#,##0)"));
  style.setFillBackgroundColor(HSSFColor.AQUA.index);
  style.setFillPattern(HSSFCellStyle.BIG_SPOTS);
  ...
  someCell.setCellStyle(style);
  someOtherCell.setCellStyle(style);
  
  版本较新的HSSF允许使用数量有限的Excel公式。这一功能目前q是“BetaU质量”,正式使用之前务必仔细试。指定公式的方式cdQsomeCell.setCellFormula(SUM(A1:A2:);?br />  
  当前Q公式中已经可以调用所有内建的函数或操作符Q但逻辑操作W和函数Q例如IF函数Q除外,q部分功能目前还在开发之中?

五、通过eventusermodeld文g
  
  通过eventusermodeld文g要比使用usermodel复杂得多Q但效率也要高不,因ؓ(f)它要求应用程序一边读取数据,一边处理数据?br />  
  eventusermodel实际上模拟了(jin)DOM环境下SAX处理XML文的办法,应用E序首先要注册期望处理的数据Qeventusermodel在遇到匚w的数据结构时回调应用E序注册的方法。用eventusermodel最大的困难在于你必ȝ(zhn)Excel工作的内部l构?br />  
  在HSSF中,低层ơ的二进制结构称录(RecordQ。记录有不同的类型,每一U类型由org.apache.poi.hssf.record包中的一个JavacLq。例如,BOFRecord记录表示Workbook或Sheet区域的开始,RowRecord表示有一个行存在q保存其样式信息?br />  
  所有具有CellValueRecordInterface接口的记录表CExcel的单元格Q包括NumericRecord、LabelSSTRecord和FormulaRecordQ还有其他一些,其中部分已被弃置不用Q部分用于优化处理,但一般而言QHSSF可以转换它们Q?br />  
  下面是一个注册事件处理句柄的例子Q?br />  
  private EventRecordFactory factory = new EventRecordFactory();
  factory.registerListener(new ERFListener() {
  public boolean processRecord(Record rec) {
  (got BOF Record);
  return true;
  }
  }, new short[] {BOFRecord.sid});
  factory.processRecords(someInputStream);
  
  六、HSSF?sh)子表格l构
  
  如前所qͼHSSF建立在POIFS的基上。具体地_(d)Excel 97+文g是OLE 2复合文Q?OLE 2 Compound DocumentQ,底层的OLE 2复合文档保存?jin)一个L命名为WorkbookQExcel 95除外QHSSF不支持Excel 95Q的?br />  
  然而,宏和囄q不保存在Workbook,它们有自q立的,有时甚至?x)放到OLE 2 CDF文g之内的另一个目录。理x况下Q宏也应该被保留Q不q目前POI目中还没有合适的API来处理宏?br />  
  每一个流之内是一l记录,一个记录其实就是一个字节数l,可分录头、记录体两部分。记录头指明?jin)记录的cdQ也即IDQ以?qing)后l数据的长度Q记录体被分割成多个字段QF(tun)ieldQ,字段包含数值数据(包括对其他记录的引用Q、字W数据或标记?br />  
  Excel工作的l构Q?br />  
  Bla.xls {
  OLE2CDF headers
  "Workbook" stream {
  Workbook {
  Static String Table Record..
  Sheet names?and pointers
  }
  Sheet {
  ROW
  ROW
  ?br />  NUMBER RECORD (cell)
  LABELSST Record (cell)
  ?br />  }
  Sheet
  }
  }
  ?images, macros, etc.
  Document Summary
  Summary
  
  七、通过HPSFd文属?/b>
  
  在Microsoft Word、Excel、PowerPoint{Y件中Q用户可以通过“文件”→“属性”菜单给文档d附加信息Q包括文的标题、主题、摘要、类别、关键词{,同时应用软g本nq会(x)加入最后访问的用户、最后访问和修改/打印的日期时间等信息?br />  
  文档的属性和正文是分开保存的。如前所qͼOLE 2 CDF文g内部p是一个容器,里面包含许多cM目录和文件的l构Q而POIFS是用来讉K其中的文件的工具。这些文件也UCؓ(f),文的属性就保存在POIFS文gpȝ中专用的里面?br />  
  以一个Word文档ZQ虽然在资源理器中你只看到一个叫做MyFile.doc的文,其实在这个文档的内部Q又包含?jin)一个WordDocument、一个SummaryInformation和一个DocumentSummaryInformation文档Q通常q会(x)有其他的文Q这里暂且不?br />  
  你能够猜?gu)些文档(?j)分别包含什么内容吗Q不错,W(xu)ordDocument包含?jin)你在Word里面~辑的文本,文档的属性保存在SummaryInformation和DocumentSummaryInformation里面。也许将所有属性保存在单个文档里面看v来太单了(jin)Q所以Microsoft军_(j)要用两个流Qؓ(f)?jin)事情更复杂一点,q两个流的名字前面还加上?jin)八q制的\005字符??q是一个不可打印的字符Q因此前面就把它省略?jin)?br />  
  Microsoft定义的标准属性有一个好处,它们q不在乎L到底是什么类??不管是Word文档、Excel工作还是PowerPointqȝ。只要你知道如何dExcel文档的属性,q道了(jin)如何d其他文的属性?br />  
  d文档属性其实ƈ不复杂,因ؓ(f)JavaE序可以利用POI目的HPSF包。HPSF?Horrible Property Set Format的羃写,译成中文是“讨厌的属性集格式”。HPSF包是POI目实现的读取属性工P目前q不支持属性写入?br />  
  对于dMicrosoft定义的标准属性,通过HPSF提供的API可以很方便地办到Q但如果要读取Q意属性集p用到更一般化的APIQ可以想象它要比d标准属性的API复杂不少。本文只介绍d标准属性的单APIQ因为对大多数应用程序来说这已经完全_?jin)?br />  
  下面是一个读取OLE 2 CDF文档的标题(titleQ属性的JavaE序Q?br />  
  import java.io.*;
  import org.apache.poi.hpsf.*;
  import org.apache.poi.poifs.eventfilesystem.*;
  
  /**
  * dOLE 2文档标题的示例程序,
  * 在命令行参数中指定文的文g名字?br />  */
  
  public class ReadTitle
  {
  public static void main(String[] args) throws IOException
  {
  final String filename = args[0];
  POIFSReader r     = new POIFSReader();
  r.registerListener(new MyPOIFSReaderListener(),
  "\005SummaryInformation");
  r.read(new FileInputStream(filename));
  }
  
  static class MyPOIFSReaderListener
  implements POIFSReaderListener
  {
  public void processPOIFSReaderEvent(POIFSReaderEvent event)
  {
  SummaryInformation si = null;
  try
  {
  si = (SummaryInformation)
  PropertySetFactory.create(event.getStream());
  }
  catch (Exception ex)
  {
  throw new RuntimeException
  ("属性集\"" + event.getPath() +
  event.getName() + "\": " + ex);
  }
  
  final String title = si.getTitle();
  
  if (title != null)
  System.out.println("标题: \"" + title + "\"");
  else
  System.out.println("该文档没有标?");
  }
  }
  }

main()Ҏ(gu)利用POIFS的事件系l从命o(h)行指定的OLE 2文档d名ؓ(f)\005SummaryInformation的流Q当P(yng)OIFSReader 遇到q个时Q它把控制传递给MyPOIFSReaderListener的processPOIFSReaderEvent()Ҏ(gu)?br />  
  processPOIFSReaderEvent()到底有什么用呢?它通过参数获得一个输入流Q该输入包含了(jin)文标题{属性。ؓ(f)?jin)访问文档的属性,我们从输入流创徏一个PropertySet实例Q如下所C:(x)
  
  si = (SummaryInformation) PropertySetFactory.create(event.getStream());
  
  q个语句其实包含三个步骤的操作:(x)
  
  ?event.getStream()从POIFSReader传入的POIFSReaderEvent获得输入?br />  
  ?以刚才获得的输入ؓ(f)参数Q调用PropertySetFactory的静(rn)态方法create()。正如其名字所暗示的,PropertySetFactory是一个工厂类Q它有一台“机器”能够把一个输入流转换成一个PropertySet实例Q这台机器就是create()Ҏ(gu)?br />  
  ?把create()Ҏ(gu)q回的PropertySet定型QcastQ成为SummaryInformation。PropertySet提供?jin)按照一般办法读取属性集的各U机ӞSummaryInformation是PropertySet的子c,即SummaryInformationcdPropertySetcȝ基础上增加了(jin)操作Microsoft标准属性的便捷Ҏ(gu)?br />  
  在这个处理过E中Q可能引起错误的因素很多Q因此我们把q部分内Ҏ(gu)入了(jin)一个try块,不过q个CZE序只按照最单的方式处理?jin)异常,在实际应用中Q最好能够对可能出现的不同异常类型分别处理?br />  
  除了(jin)一般的I/O异常之外Q还有可能遇到HPSFҎ(gu)的异常,例如Q如果输入流不包含属性集或属性集非法Q就?x)抛出NoPropertySetStreamException异常?br />  
  有一U错误不太常见,但也不是l无可能\005SummaryInformation包含一个合法的属性集Q但不是摘要信息属性集。如果出现这U情况,则定型成SummaryInformation操作?x)失败,引发ClassCastException异常?br />  
  获得SummaryInformation实例之后Q剩下的事情很单了(jin)Q只要调用getTitle()Ҏ(gu)Q然后输出结果?br />  
  除了(jin)getTitle()之外QSummaryInformationq包含其他一些便h法,例如getApplicationName()、getAuthor()、getCharCount()、和getCreateDateTime(){。HPSF的JavaDoc文详细说明?jin)所有这些方法?br />  
  八、文摘要信?/b>
  
  遗憾的是Qƈ非所有的属性都保存在摘要信息属性集之中。许多(但不是全部)(j)OLE 2文gq有另一个属性集Q称为“文摘要信息”,对应的流是\005DocumentSummaryInformation。这个属性集保存的属性包括文的cd、PowerPointqȝ的多媒体剪辑数量Q等{?br />  
  要访问文摘要信息属性集Q程序的处理q程也和上例怼Q只是注册的目标应该Ҏ(gu)\005DocumentSummaryInformation有时Q你可能惌同时注册到摘要信息和文摘要信息q两个流。其余的处理方式和前面的例子差不多,你应该把包含文摘要信息的流传递给PropertySetFactory.create()Q但q次工厂Ҏ(gu)返回一个DocumentSummaryInformation对象Q而不是前面例子中的SummaryInformation对象Q?br />  
  如果同时注册C(jin)两个,注意(g)查返回值的具体cdQ或者用Java的instanceof操作W,或者用专用的isSummaryInformation()和isDocumentSummaryInformation()Ҏ(gu)。记住,create()Ҏ(gu)q回的L一个PropertySet对象Q因此你L可以对create()q回对象调用isSummaryInformation()和isDocumentSummaryInformation()Ҏ(gu)QPropertySetcM所以要提供q两个方法,是因为属性集可能是自定义的?br />  
  如果你想要处理自定义的属性集Q或者要从标准的属性集d用户定义的属性,必须使用一个更一般化的APIQ前面已l提刎ͼq个API要复杂得多,本文不再讨论Q请参见HPSF的HOW-TO文和POI的文?br />  
  l束语:(x)本文探讨?jin)HSSF的应用以?qing)如何输出到Excel文gQ另外还涉及(qing)?jin)HPSF以及(qing)如何d属性集文摘要信息。POI是一个功能非常强大的目Q许多主题本文尚未涉?qing),例如如何用HSSF SerializerXML文转换成Excel格式{,q一切仍有待(zhn)去研究?jin)?br />  
  ?ji)、附?/b>
  
  实例Q利用Servlet创徏和返回一个工作簿?br />  
  package org.apache.poi.hssf.usermodel.examples;
  
  import java.io.*;
  import java.net.*;
  import javax.servlet.*;
  import javax.servlet.http.*;
  import org.apache.poi.hssf.usermodel.*;
  
  public class HSSFCreate extends HttpServlet {
  public void init(ServletConfig config)
  throws ServletException {
  super.init(config);
  }
  
  public void destroy() {
  }
  
  /** 处理HTTP GET 和POSTh
  * @param requestQ请?br />  * @param responseQ应{?br />  */
  protected void processRequest(HttpServletRequest request,
  HttpServletResponse response)
  throws ServletException, IOException {
  
  response.setContentType("application/vnd.ms-excel");
  HSSFWorkbook wb = new HSSFWorkbook();
  HSSFSheet sheet = wb.createSheet("new sheet");
  
  // 创徏一个新的行Q添加几个单元格?br />  // 行号?开始计?br />  HSSFRow row   = sheet.createRow((short)0);
  // 创徏一个单元格Q设|单元格的?br />  HSSFCell cell  = row.createCell((short)0);
  cell.setCellValue(1);
  
  row.createCell((short)1).setCellValue(1.2);
  row.createCell((short)2).setCellValue("一个字W串?);
  row.createCell((short)3).setCellValue(true);
  // 写入输出l果
  OutputStream out = response.getOutputStream();
  wb.write(out);
  out.close();
  }
  
  /** 处理HTTP GETh
  * @param requestQ请?br />  * @param responseQ应{?br />  */
  protected void doGet(HttpServletRequest request,
  HttpServletResponse response)
  throws ServletException, IOException {
  processRequest(request, response);
  }
  
  /** 处理HTTP POSTh
  * @param requestQ请?br />  * @param responseQ应{?br />  */
  protected void doPost(HttpServletRequest request,
  HttpServletResponse response)
  throws ServletException, IOException {
  processRequest(request, response);
  }
  
  /** q回关于Servlet的简单说?br />  */
  public String getServletInfo() {
  return "CZQ在Servlet中用HSSF创徏Excel工作?;
  }
  }


Hally 2006-10-25 16:03 发表评论
]]>
JOB 用法结 (?http://www.tkk7.com/hallywang/archive/2006/10/10/74312.htmlHallyHallyTue, 10 Oct 2006 08:03:00 GMThttp://www.tkk7.com/hallywang/archive/2006/10/10/74312.htmlhttp://www.tkk7.com/hallywang/comments/74312.htmlhttp://www.tkk7.com/hallywang/archive/2006/10/10/74312.html#Feedback0http://www.tkk7.com/hallywang/comments/commentRss/74312.htmlhttp://www.tkk7.com/hallywang/services/trackbacks/74312.htmlJOB 用法结


一、设|初始化参数 job_queue_processes

sql> alter system set job_queue_processes=n;Qn>0Q?/b>
job_queue_processes最大gؓ(f)1000

查看job queue 后台q程
sql>select name,description from v$bgprocess;

二,dbms_job package 用法介绍
包含以下子过E:(x)

Broken()q程?br />change()q程?br />Interval()q程?br />Isubmit()q程?br />Next_Date()q程?br />Remove()q程?br />Run()q程?br />Submit()q程?br />User_Export()q程?br />What()q程?br />
1?br />Broken()q程更新一个已提交的工作的状态,典型地是用来把一个已破工作标Cؓ(f)未破工作?br />q个q程有三个参敎ͼ(x)job 、broken与next_date?br />
PROCEDURE Broken (job       IN binary_integer,
                  Broken    IN boolean,
                  next_date IN date :=SYSDATE)

job参数是工作号Q它在问题中唯一标识工作?br />broken参数指示此工作是否将标记为破——TRUE说明此工作将标记为破Q而FLASE说明此工作将标记为未破?br />next_date参数指示在什么时候此工作再ơ运行。此参数~省gؓ(f)当前日期和时间?br />job如果׃某种原因未能成功之行Qoracle重?6ơ后Q还未能成功执行Q将被标Cؓ(f)broken
重新启动状态ؓ(f)broken的jobQ有如下两种方式;
a、利用dbms_job.run()立即执行该job
   sql>begin
   sql>dbms_job.run(:jobno) 该jobno为submitq程提交时返回的job number
   sql>end;
   sql>/
b、利用dbms_job.broken()重新broken标记为false
   sql>begin
   sql>dbms_job.broken (:job,false,next_date)
   sql>end;
   sql>/
2?br />Change()q程用来改变指定工作的设|?br />q个q程有四个参敎ͼ(x)job、what 、next_date与interval?br />
PROCEDURE Change (job        I(yng)N binary_integer,
                  What       IN varchar2,
                  next_date  I(yng)N date,
                  interval   I(yng)N varchar2)

此job参数是一个整数|它唯一标识此工作?br />What参数是由此工作运行的一块PL/SQL代码块?br />next_date参数指示何时此工作将被执行?br />interval参数指示一个工作重执行的频度?br />
3?br />Interval()q程用来昑ּ地设|重执行一个工作之间的旉间隔数?br />q个q程有两个参敎ͼ(x)job与interval?br />
PROCEDURE Interval (job      I(yng)N binary_integer,
                    I(yng)nterval IN varchar2)

job参数标识一个特定的工作。interval参数指示一个工作重执行的频度?br />


4?br />ISubmit()q程用来用特定的工作h交一个工作?br />q个q程有五个参敎ͼ(x)job、what、next_date、interval与no_parse?br />
PROCEDURE ISubmit (job       IN binary_ineger,
                   What      I(yng)N varchar2,
                   next_date IN date,
                   interval  I(yng)N varchar2,
                   no_parse  I(yng)N booean:=FALSE)

q个q程与Submit()q程的唯一区别在于此job参数作ؓ(f)IN型参C递且包括一?br />由开发者提供的工作受如果提供的工作号已被用,生一个错误?br />

5?br />Next_Date()q程用来昑ּ地设定一个工作的执行旉。这个过E接收两个参敎ͼ(x)job与next_date?br />
PROCEDURE Next_Date(job         I(yng)N binary_ineger,
                    next_date   I(yng)N date)

job标识一个已存在的工作。next_date参数指示?jin)此工作应被执行的日期与旉?br />


6?br />Remove()q程来删除一个已计划q行的工作。这个过E接收一个参敎ͼ(x)

PROCEDURE Remove(job IN  binary_ineger);

job参数唯一地标识一个工作。这个参数的值是׃ؓ(f)此工作调用Submit()q程q回的job参数的倹{?br />已正在运行的工作不能p用过E序删除?br />


7?br />Run()q程用来立即执行一个指定的工作。这个过E只接收一个参敎ͼ(x)

PROCEDURE Run(job IN binary_ineger)

job参数标识被立即执行的工作?br />


8?br />使用Submit()q程Q工作被正常地计划好?br />q个q程有五个参敎ͼ(x)job、what、next_date、interval与no_parse?br />
PROCEDURE Submit ( job       OUT binary_ineger,
                   What      I(yng)N  varchar2,
                   next_date IN  date,
                   interval  I(yng)N  varchar2,
                   no_parse  I(yng)N  booean:=FALSE)

job参数是由Submit()q程q回的binary_ineger。这个值用来唯一标识一个工作?br />what参数是将被执行的PL/SQL代码块?br />next_date参数指识何时运行这个工作?br />interval参数何时q个工作被重执行?br />no_parse参数指示此工作在提交时或执行时是否应q行语法分析——TRUE
指示此PL/SQL代码在它W一ơ执行时应进行语法分析,
而FALSE指示本PL/SQL代码应立卌行语法分析?br />


9?br />User_Export()q程q回一个命令,此命令用来安排一个存在的工作以便此工作能重新提交?br />此程序有两个参数Qjob与my_call?br />
PROCEDURE User_Export(job        I(yng)N binary_ineger,
                      my_call    IN OUT varchar2)

job参数标识一个安排了(jin)的工作。my_call参数包含在它的当前状态重新提交此工作所需?br />的正文?br />


10?br />What()q程应许在工作执行时重新讄此正在运行的命o(h)。这个过E接收两个参敎ͼ(x)job与what?br />
PROCEDURE What (job  I(yng)N binary_ineger,
                What IN OUT varchar2)

job参数标识一个存在的工作。what参数指示被执行的新的PL/SQL代码?br />

三、查看相关job信息
1、相兌?br />dba_jobs
all_jobs
user_jobs
dba_jobs_running 包含正在q行job相关信息

2、查看相关信?br />
SQL>SELECT JOB, NEXT_DATE, NEXT_SEC, FAILURES, BROKEN
SQL>FROM DBA_JOBS;

JOB NEXT_DATE NEXT_SEC FAILURES B
------- --------- -------- -------- -
9125 01-JUN-01 00:00:00 4 N
14144 24-OCT-01 16:35:35 0 N
9127 01-JUN-01 00:00:00 16 Y
3 rows selected.

正在q行的JOB相关信息

SELECT SID, r.JOB, LOG_USER, r.THIS_DATE, r.THIS_SEC
FROM DBA_JOBS_RUNNING r, DBA_JOBS j
WHERE r.JOB = j.JOB;

SID JOB LOG_USER THIS_DATE THIS_SEC
----- ---------- ------------- --------- --------
12 14144 HR 24-OCT-94 17:21:24
25 8536 QS 24-OCT-94 16:45:12
2 rows selected.
  
JOB QUEUE LOCK相关信息

SELECT SID, TYPE, ID1, ID2
FROM V$LOCK
WHERE TYPE = 'JQ';

SID TY ID1 ID2
--------- -- --------- ---------
12 JQ 0 14144
1 row selected.

四、简单例?br />
一个简单例子:(x)

创徏试?br />SQL> create table TEST(a date);

表已创徏?br />
创徏一个自定义q程
SQL> create or replace procedure MYPROC as
  2  begin
  3  insert into TEST values(sysdate);
  4  end;
  5  /

q程已创建?br />
创徏JOB
SQL> variable job1 number;
SQL>
SQL> begin
  2  dbms_job.submit(:job1,'MYPROC;',sysdate,'sysdate+1/1440');  --每天1440分钟Q即一分钟q行testq程一?br />  3  end;
  4  /

PL/SQL q程已成功完成?br />
q行JOB
SQL> begin
  2  dbms_job.run(:job1);
  3  end;
  4  /

PL/SQL q程已成功完成?br />
SQL> select to_char(a,'yyyy/mm/dd hh24:mi:ss') 旉 from TEST;


-------------------
2001/01/07 23:51:21
2001/01/07 23:52:22
2001/01/07 23:53:24

删除JOB
SQL> begin
  2  dbms_job.remove(:job1);
  3  end;
  4  /

PL/SQL q程已成功完成?br />五、相x意事?br />
1、执行dbms_job包相兌E如remove、Change、brokenӞ登陆的用戯同徏立该JOB的用户一?br />
2、当执行dbms_job.changeq程Ӟ如果参数what,next_date,intervalgؓ(f)nullQ则表示原参数g?br />?br />BEGIN
DBMS_JOB.CHANGE(14144, NULL, NULL, 'SYSDATE + 3');
END;
/

3、如果利用database link来提交jobQ则该link必须包含合适的用户名和密码?br />
4、执行job的用户必d有作业过E中所涉及(qing)对象的相应权限?br />
5、数据库在restricted mode下,不能执行job



Hally 2006-10-10 16:03 发表评论
]]>
oracle dba 职责 【{?/title><link>http://www.tkk7.com/hallywang/archive/2006/10/09/74027.html</link><dc:creator>Hally</dc:creator><author>Hally</author><pubDate>Mon, 09 Oct 2006 03:52:00 GMT</pubDate><guid>http://www.tkk7.com/hallywang/archive/2006/10/09/74027.html</guid><wfw:comment>http://www.tkk7.com/hallywang/comments/74027.html</wfw:comment><comments>http://www.tkk7.com/hallywang/archive/2006/10/09/74027.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.tkk7.com/hallywang/comments/commentRss/74027.html</wfw:commentRss><trackback:ping>http://www.tkk7.com/hallywang/services/trackbacks/74027.html</trackback:ping><description><![CDATA[ <font color="#333333">转自Q?a >http://www.linuxmine.com/49842.html</a> <br /><br />ORACLE数据库管理员应按如下方式对ORACLE数据库系l做定期监控Q?<br />  (1). 每天对ORACLE数据库的q行状?日志文g,备䆾情况,数据 库的I间使用情况,pȝ资源的用情况进行检?发现q解?问题?<br />  (2). 每周Ҏ(gu)据库对象的空间扩展情?数据的增长情况进行监?Ҏ(gu)据库做健h?Ҏ(gu)据库对象的状态做(g)查?<br />  (3). 每月对表和烦(ch)引等q行Analyze,(g)查表I间片,L数据?性能调整的机?q行数据库性能调整,提出下一步空间管理计划。对ORACLE数据库状态进行一ơ全面检查?每天的工?<br />  (1).认所有的INSTANCE状态正常登陆到所有数据库或例E?(g)ORACLE后台q程: <br />  $ps ?ef|grep ora <br />  (2). (g)查文件系l的使用Q剩余空_(d)(j)。如果文件系l的剩余I间于20%Q需删除不用的文件以释放I间?<br />  $df ?k <br />  (3). (g)查日志文件和trace文g记录alert和trace文g中的错误。连接到每个需理的系l?<br />  使用’telnet?<br />  Ҏ(gu)个数据库,cd 到bdump目录,通常?ORACLE_BASE/<SID>/bdump <br />  使用 Unix ‘tail’命令来查看alert_<SID>.log文g <br />  如果发现M新的ORA- 错误,记录q解?<br />  (4). (g)查数据库当日备䆾的有效性?<br />  对RMAN备䆾方式: <br />  (g)查第三方备䆾工具的备份日志以定备䆾是否成功 <br />  对EXPORT备䆾方式: <br />  (g)查exp日志文g以确定备份是否成?<br />  对其他备份方? <br />  (g)查相应的日志文g <br />  (5). (g)查数据文件的状态记录状态不是“online”的数据文gQƈ做恢复?<br />  Select file_name from dba_data_files where status=’OFFLINE?<br />  (6). (g)查表I间的用情?<br />  SELECT tablespace_name, max_m, count_blocks free_blk_cnt, sum_free_m,to_char(100*sum_free_m/sum_m, '99.99') || '%' AS pct_free <br />  FROM ( SELECT tablespace_name,sum(bytes)/1024/1024 AS sum_m FROM dba_data_files GROUP BY tablespace_name), <br />  ( SELECT tablespace_name AS fs_ts_name, max(bytes)/1024/1024 AS max_m, count(blocks) AS count_blocks, sum(bytes/1024/1024) AS sum_free_m FROM dba_free_space GROUP BY tablespace_name ) <br />  WHERE tablespace_name = fs_ts_name <br />  (7). (g)查剩余表I间 <br />  SELECT tablespace_name, sum ( blocks ) as free_blk , <br />  trunc ( sum ( bytes ) /(1024*1024) ) as free_m, <br />  max ( bytes ) / (1024) as big_chunk_k, count (*) as num_chunks <br />  FROM dba_free_space GROUP BY tablespace_name; <br />  (8). 监控数据库性能 <br />  q行bstat/estat生成pȝ报告 <br />  或者用statspack攉l计数据 <br />  (9). (g)查数据库性能Q记录数据库的cpu使用、IO、buffer命中率等{?<br />  使用vmstat,iostat,glance,top{命?<br />  (10). 日常出现问题的处理?<br />  每周的工?<br />  (1). 控数据库对象的空间扩展情?<br />  Ҏ(gu)本周每天的检查情冉|到空间扩展很快的数据库对?q取相 <br />  应的措施 <br />  -- 删除历史数据 <br />  --- 扩表I间 <br />  alter tablespace <name> add datafile ?lt;file>?size <size> <br />  --- 调整数据对象的存储参?<br />  next extent <br />  pct_increase <br />  (2). 监控数据量的增长情况 <br />  Ҏ(gu)本周每天的检查情冉|到记录数量增长很快的数据库对?q <br />  取相应的措施 <br />  -- 删除历史数据 <br />  --- 扩表I间 <br />  alter tablespace <name> add datafile ?lt;file>?size <size> <br />  (3). pȝ健康(g)?<br />  (g)查以下内? <br />  init<sid>.ora <br />  controlfile <br />  redo log file <br />  archiving <br />  sort area size <br />  tablespace(system,temporary,tablespace fragment) <br />  datafiles(autoextend,location) <br />  object(number of extent,next extent,index) <br />  rollback segment <br />  logging &tracing(alert.log,max_dump_file_size,sqlnet) <br />  (4). (g)查无效的数据库对?<br />  SELECT owner, object_name, object_type FROM dba_objects <br />  WHERE status=’INVALID’?<br />  (5). (g)查不起作用的U束 <br />  SELECT owner, constraint_name, table_name, <br />  constraint_type, status <br />  FROM dba_constraints <br />  WHERE status = 'DISABLED?AND constraint_type = 'P' <br />  (6). (g)查无效的trigger <br />  SELECT owner, trigger_name, table_name, status <br />  FROM dba_triggers <br />  WHERE status = 'DISABLED?<br />  每月的工?<br />  (1). Analyze Tables/Indexes/Cluster <br />  analyze table <name> estimate statistics sample 50 percent; <br />  (2). (g)查表I间片 <br />  Ҏ(gu)本月每周的检查分析数据库片情况,扑ֈ相应的解x?<br />  (3). L数据库性能调整的机?<br />  比较每天Ҏ(gu)据库性能的监控报?定是否有必要对数据库性能q?行调?<br />  (4). 数据库性能调整 <br />  如有必要,q行性能调整 <br />  (5). 提出下一步空间管理计?<br />  Ҏ(gu)每周的监?提出I间理的改q方?br />  <br />  <b>Oracle DBA 日常理</b><br />  目的Q这文有很详l的资料记录着对一个甚x多的ORACLE 数据库每天的Q每月的Q?每年的运行的状态的l果?qing)检查的l果Q在文的附录中你将?x)看到所有检查,修改的SQL 和PL/SQL 代码?<br />  目录 <br />  1.日常l护E序 <br />  AQ?(g)查已L(fng)所有实?<br />  BQ?查找一些新的警告日?<br />  CQ?(g)查DBSNMP 是否在运?<br />  DQ?(g)查数据库备䆾是否正确 <br />  EQ?(g)查备份到带中的文g是否正确 <br />  FQ?(g)查数据库的性能是否正常合理Q是否有_的空间和资源 <br />  GQ?文日志复制到备䆾的数据库?<br />  HQ?要常看DBA 用户手册 <br />  2.晚间l护E序 <br />  AQ收集VOLUMETRIC 的数?<br />  3.每周l护工作 <br />  AQ?查找那些破坏规则的OBJECT <br />  BQ?查找是否有违反安全策略的问题 <br />  CQ?查看错误地方的SQL*NET 日志 <br />  DQ?所有的警告日志存 <br />  EQ?l常讉K供应商的主页 <br />  4.月维护程?<br />  AQ?查看Ҏ(gu)据库?x)生危害的增长速度 <br />  BQ?回顾以前数据库优化性能的调?<br />  CQ?查看I/O 的屏颈问?<br />  DQ?回顾FRAGMENTATION <br />  EQ?来的执行计?<br />  FQ?查看调整点和l护 <br />  5.附录 <br />  AQ?月维护过E?<br />  BQ?晚间l护q程 <br />  CQ?周维护过E?<br />  <br />  <b>一Q日l护q程 </b><br />  AQ查看所有的实例是否已v定数据库是可用的,把每个实例写入日志ƈ且运行日报告或是q行试 文g。当然有一些操作我们是希望它能自动q行的?可选择执行Q用ORACLE 理器中的‘PROBE’事件来查看 <br />  BQ查找新的警告日志文?<br />  1. 联接每一个操作管理系l?<br />  2. 使用‘TELNET’或是可比较E序 <br />  3. Ҏ(gu)一个管理实例,l常的执?ORACLE_BASE/<SID>/bdump ?作,q其能回退到控制数据库的SID?<br />  4. 在提CZQ用UNIX 中的‘TAIL’命令查看alert_<SID>.logQ或?用其他方式检查文件中最q时期的警告日志 <br />  5. 如果以前出现q的一些ORA_ERRORS 又出玎ͼ它记录到数据库 恢复日志中ƈ且仔l的研究它们Q这个数据库恢复日志在〈F(tun)ILE〉中 <br />  CQ查看DBSNMP 的运行情?(g)查每个被理机器的‘DBSNMP’进Eƈ它们记录到日志中?在UNIX 中,在命令行中,键入ps ?ef | grep dbsnmp,回看到2 ?DBSNMP q程在运行。如果没有,重启DBSNMP?<br />  DQ查数据库备份是否成?<br />  EQ检查备份的带文是否成功 <br />  FQ检查对合理的性能来说是否有够的资源 <br />  1. (g)查在表空间中有没有剩余空间。对每一个实例来_(d)(g)查在表空间中是否存在有剩余空间来满当天 的预期的需要。当数据库中已有的数据是E_的,数据日增长的q_ C是可以计出来,最的剩余I间臛_要能满每天数据的增 ѝ?<br />  AQ?q行‘FREE.SQL’来(g)查表I间的剩余空间?<br />  BQ?q行‘SPACE.SQL’来(g)查表I间中的剩余I间癑ֈ?<br />  2. (g)查回滚段回滚D늚状态一般是在线的,除了(jin)一些ؓ(f)复杂工作准备的专?D,它一般状态是ȝ的?<br />  a) 每个数据库都有一个回滚段名字的列表?<br />  b) 你可以用V$ROLLSTAT 来查询在U或是离U的回滚D늚现在?? <br />  c) 对于所有回滚段的存储参数及(qing)名字Q?可用DBA_ROLLBACK_SEGS 来查询。但是它不如V$ROLLSTAT 准确?<br />  3. 识别Z些过分的增长查看数据库中出资源或是增长速度q大的段Q这些段的存储参 数需要调整?<br />  aQ?攉日数据大的信息Q?可以用‘ANALYZE5PCT.SQL’。如果你攉的是每晚的信息, 则可跌q一步?<br />  bQ?(g)查当前的范围Q可用‘NR.EXTENTS.SQL’?<br />  cQ?查询当前表的大小信息?<br />  dQ?查询当前索引大小的信息?<br />  eQ?查询增长势?<br />  4. 定I间的范围。如果范围空间对象的NEXT_EXTENT 比表I间所能提供的最大范围还要大Q那么这媄(jing)响数据库的运行。如果我们找C(jin)q个目标Q可以用‘ALTER TABLESPACE COALESCE’调查它的位|,或加另外 的数据文件?<br />  AQ运行‘SPACEBOUND.SQL’。如果都是正常的Q将不返回Q何行?<br />  5. 回顾CPUQ内存,|络Q硬件资源论点的q程 <br />  AQ检查CPU的利用情况,q到x:\web\phase2\default.htm =>system metrics=>CPU 利用,CPU 的最大限度ؓ(f)400Q当CPU 的占用保持在350 以上</font> <img src ="http://www.tkk7.com/hallywang/aggbug/74027.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.tkk7.com/hallywang/" target="_blank">Hally</a> 2006-10-09 11:52 <a href="http://www.tkk7.com/hallywang/archive/2006/10/09/74027.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>tar命o(h)详解http://www.tkk7.com/hallywang/archive/2006/05/09/45240.htmlHallyHallyTue, 09 May 2006 08:49:00 GMThttp://www.tkk7.com/hallywang/archive/2006/05/09/45240.htmlhttp://www.tkk7.com/hallywang/comments/45240.htmlhttp://www.tkk7.com/hallywang/archive/2006/05/09/45240.html#Feedback0http://www.tkk7.com/hallywang/comments/commentRss/45240.htmlhttp://www.tkk7.com/hallywang/services/trackbacks/45240.html

tar 
格式Q tar 选项 文g目录列表 
功能Q 对文g目录q行打包备䆾 
选项Q?br />-c 建立新的归文g
-r 向归文件末追加文?br />-x 从归文件中解出文g
-O 文件解开到标准输?br />-v 处理q程中输出相关信?br />-f Ҏ(gu)通文件操?br />-z 调用gzip来压~归文Ӟ?x联用时调用gzip完成解压~?br />-Z 调用compress来压~归文Ӟ?x联用时调用compress完成解压~?br />实例1Q 目的:(x)用tar打包一个目录下的文?br />命o(h)Q#tar -cvf /mnt/lgx/a1.doc
l果Q生一个以.tar为扩展名的打包文件?br />实例2Q 目的:(x)用tar解开打包文g
命o(h)Q#tar -xvf /mnt/lgx/a1.doc.tar
附加说明Q在通常情况下,tar打包与gzipQ压~)(j)l常联合使用Q效果更好。方法是Q?br />首先用tar打包Q如Q#tar -cvf /mnt/lgx/a1.doc Q生a1.doc.tar文gQ?br />然后用gzip压羃a1.doc.tar文gQ如Q#gzip /mnt/lgx/a1.doc.tar Q生a1.doc.tar.gz文gQ?br />实例3Q 目的:(x)解压a1.doc.tar.gz文g
Ҏ(gu)1Q?br />Qgzip -dc /mnt/lgx/a1.doc.tar.gz Q生a1.doc.tar文gQ?br />Qtar -xvf /mnt/lgx/a1.doc.tar Q生a1.doc文gQ?br />q两ơ命令也可用管道功能,把两个命令合二ؓ(f)一Q?br />Qgzip -dc /mnt/lgx/a1.doc.tar.gz | tar -xvf
Ҏ(gu)2Q用tar提供的自动调用gzip解压~功?br />Qtar -xzvf /mnt/lgx/a1.doc.tar.gz
l过tar打包后,也可用compress命o(h)压羃Q注Qgzip比compress压羃更加有效Q,产生一个以.tar.Z的文Ӟ在解包时Q可先用“uncompress 文g名”格式解压,然后用“tar -xvf 文g名”解包。也可直接调用“tar -Zxvf 文g名”解包?br />

 
Posted by bd4rfk 2006-3-27 11:21:00

丑և个例子:(x)

例一Q将整个/etc目录下的文g全部打包成ؓ(f)/tmp/etc.tar
tar -cvf /tmp/etc.tar /etc  #仅打包,不压~?br />tar -zcvf /tmp/etc.tar.gz /etc  #打包后,以gzip压羃
tar -jcvf /tmp/etc.tar.bz2 /etc  #打包后,以bzip2压羃

例二Q查阅上q?tmp/etc.tar.gz文g内有哪些文g
tar -ztvf /tmp/etc.tar.gz

例三Q将/tmp/etc.tar.gz文g解压~到/usr/local/src?br />cd /usr/local/src   #先将工作目录变换?usr/local/src?br />tar -zxvf /tmp/etc.tar.gz
 
例四Q只?tmp/etc.tar.gz内的etc/passwd解压?tmp?br />cd /tmp
tar -zxvf /tmp/etc.tar.gz etc/passwd

例五Q将/etc内的所有文件备份下来,q且保存其权限!
tar -zxvpf /tmp/etc.tar.gz /etc

例六Q在/home当中Q比2005/06/01新的文g才备?br />tar -N '2005/06/01' -zcvf home.tar.gz /home

例七Q备?home?etcQ但不要/home/dmtsai
tar --exclude /home/dmtsai -zcvf myfile.tar.gz /home/* /etc

例八Q将/etc打包后直接解开?tmp底下Q而不产生文gQ?br />cd /tmp
tar -cvf - /etc | tar -xvf -



Hally 2006-05-09 16:49 发表评论
]]>
在J2ME开发中解析XML [转]http://www.tkk7.com/hallywang/archive/2006/04/24/42798.htmlHallyHallyMon, 24 Apr 2006 03:16:00 GMThttp://www.tkk7.com/hallywang/archive/2006/04/24/42798.htmlhttp://www.tkk7.com/hallywang/comments/42798.htmlhttp://www.tkk7.com/hallywang/archive/2006/04/24/42798.html#Feedback0http://www.tkk7.com/hallywang/comments/commentRss/42798.htmlhttp://www.tkk7.com/hallywang/services/trackbacks/42798.html 在J2ME开发中解析XML www.52RD.com 2005q?2?2日 我爱研发| mingjava 目前,XML已经q泛应用于数据交换领域,xml是基于纯文本的,h优秀的跨q_Ҏ(gu)。本文将讲述如何在J2ME中解析XMLq行数据传输?

    XML写法比较单,而且非常便于人来阅读。但是必d客户端和服务器端有XML的解析器才可以正帔R信Q由于初期的Ud信息讑֤内存和处理器上的不Q所以在MIDP1.0中ƈ没有提供对XML的支持。随着内存和处理器的提高,对XML的支持成Z(jin)可能。在JSR182中提供了(jin)XML的解析器Q但是这q不是标准MIDP中的API需要特定的实现才可以支持。幸q的是有W三方的API对解析xml提供?jin)支持,比较有名的是kxml和nanoxml?/p>

    使用XML之前Q你必须考虑好是不是必须用它来传输数据,因ؓ(f)解析xml是比较耗费资源的,其是在CPU和内存的资源都很宝贵的条件下。如果我们能使用DataInputStream和DataOutputStream传输的话尽量不要用XML。XML的解析器有两U,一U是认性的Q他在解析之前会(x)对xml的文进行有效性的验证Q确保这是应用程序需要的。另一U则是非认性的Q他不做验证工作直接q行解析Q无疑这L(fng)速度?x)快。kxml和nanoxml都是q样的解析器。它们也存在差别Qkxml是增量解析器他会(x)一点一点的解析Q这样在解析大的文的时候会(x)效率比较高。nanoxml是一步解析器Q一ơ就把文解析完Q如果文很大的话,q无疑会(x)耗费很大的内存。要使用kxml你可以从http://www.kxml.org 下蝲得到,?a >http://nanoxml.sourceforge.net 你可以下载nanoxml?/p>

    要用kxmlQ你必须首先得到一个XmlParser实例Q它用Reader作ؓ(f)构造器的参敎ͼ(x)
try {
    Reader    r = .....;
    XmlParser parser = new XmlParser( r );
}
catch( java.io.IOException e ){
    // handle exception....
}

如果你的xml文存储在String内的话你可以使用ByteArrayInputStream和InputStreamReaderQ?br />String    xml = "<a>some xml</a>";
ByteArrayInputStream bin =
            new ByteArrayInputStream( xml.getBytes() );
XmlParser parser = new XmlParser( new InputStreamReader( bin ) );
当从|上接收数据的时候可以这P(x)
HttpConnection    conn = .....;
InputStreamReader doc =
         new InputStreamReader( conn.openInputStream() );
XmlParser parser = new XmlParser( doc );
得到parser实例后我们就可以调用readҎ(gu)q行解析?jin),readҎ(gu)?x)返回一个ParseEvent,通过判断他的cd我们可以解析xml?jin)?br />try {
    boolean keepParsing = true;
       
    while( keepParsing ){
        ParseEvent event = parser.read();
 
        switch( event.getType() ){
            case Xml.START_TAG:
                ..... // handle start of an XML tag
                break;
            case Xml.END_TAG:
                ..... // handle end of an XML tag
                break;
            case Xml.TEXT:
                ..... // handle text within a tag
                break;
            case Xml.WHITESPACE:
                ..... // handle whitespace
                break;
            case Xml.COMMENT:
                ..... // handle comment
                break;
            case Xml.PROCESSING_INSTRUCTION:
                ..... // handle XML PI
                break;
            case Xml.DOCTYPE:
                ..... // handle XML doctype
                break;
            case Xml.END_DOCUMENT:
                ..... // end of document;
                keepParsing = false;
                break;
        }
    }
}
catch( java.io.IOException e ){
}

如果想用nanoxmlQ那么你首先要创Z个kXMLElement实例Q然后调用parseFromReader、parseString或者parseCharArray。由于他是一步解析器Q那么它?x)把整个文解析完后生成一个Object tree。每个节炚w是一个kXMLElement的实例,通过调用getChildren{方法可以在q棵?wi)上D?br />HttpConnection    conn = .....;
InputStreamReader doc =
         new InputStreamReader( conn.openInputStream() );
kXMLElement       root = new kXMLElement();

try {
    root.parseFromReader( doc );
}
catch( kXMLParseException pe ){
}
catch( IOException ie ){
}

下面是一个J2ME的应用程序简单演CZ(jin)如何解析xml。如果有旉可以写写复杂的测试程序。你可以从如下地址下蝲源代码:(x)XMLTest. 里面包括?jin)kxml和nanoxml的源代码Q如果想得到最新的源代码请参考他们的官方|站Q在本站提供?jin)kxml?a >在线API
package com.ericgiguere.techtips;

import java.io.*;
import java.util.*;
import javax.microedition.lcdui.*;
import javax.microedition.midlet.*;
import nanoxml.*;
import org.kxml.*;
import org.kxml.parser.*;

/**
 * Simple MIDlet that demonstrates how an XML document can be
 * parsed using kXML or NanoXML.
 */

public class XMLTest extends MIDlet {

    // Our XML document -- normally this would be something you
    // download.
   
    private static String xmlDocument =
        "<list><item>apple</item>" +
              "<item>orange</item>" +
              "<item>pear</item></list>";
             
    private Display display;
    private Command exitCommand = new Command( "Exit",
                                               Command.EXIT, 1 );
                                              
    public XMLTest(){
    }
   
    protected void destroyApp( boolean unconditional )
                       throws MIDletStateChangeException {
        exitMIDlet();
    }
   
    protected void pauseApp(){
    }
   
    protected void startApp() throws MIDletStateChangeException {
        if( display == null ){ // first time called...
            initMIDlet();
        }
    }
   
    private void initMIDlet(){
        display = Display.getDisplay( this );
       
        String [] items;
       
        //items = parseUsingNanoXML( xmlDocument );
        items = parseUsingkXML( xmlDocument );
       
        display.setCurrent( new ItemList( items ) );
    }
   
    public void exitMIDlet(){
        notifyDestroyed();
    }
   
    // Parses a document using NanoXML, looking for
    // "item" nodes and returning their content as an
    // array of strings.
   
    private String[] parseUsingNanoXML( String xml ){
        kXMLElement root = new kXMLElement();
        try {
            root.parseString( xml );
           
            Vector list = root.getChildren();
            Vector items = new Vector();
           
            for( int i = 0; i < list.size(); ++i ){
                kXMLElement node =
                     (kXMLElement) list.elementAt( i );
                String      tag = node.getTagName();
               
                if( tag == null ) continue;
                if( !tag.equals( "item" ) ) continue;
               
                items.addElement( node.getContents() );
            }
           
            String[] tmp = new String[ items.size() ];
            items.copyInto( tmp );
            return tmp;
        }
        catch( kXMLParseException ke ){
            return new String[]{ ke.toString() };
        }
    }
   
    // Parses a document using kXML, looking for "item"
    // nodes and returning their content as an
    // array of strings.
   
    private String[] parseUsingkXML( String xml ){
        try {
            ByteArrayInputStream bin =
                            new ByteArrayInputStream(
                                     xml.getBytes() );
            InputStreamReader in = new InputStreamReader( bin );
            XmlParser parser = new XmlParser( in );
            Vector    items = new Vector();
           
            parsekXMLItems( parser, items );
           
            String[] tmp = new String[ items.size() ];
            items.copyInto( tmp );
            return tmp;
        }
        catch( IOException e ){
            return new String[]{ e.toString() };
        }
    }
   
    private void parsekXMLItems( XmlParser parser, Vector items )
                                     throws IOException {
        boolean inItem = false;
       
        while( true ){
            ParseEvent event = parser.read();
            switch( event.getType() ){
                case Xml.START_TAG:
                    if( event.getName().equals( "item" ) ){
                        inItem = true;
                    }
                    break;
                case Xml.END_TAG:
                    if( event.getName().equals( "item" ) ){
                        inItem = false;
                    }
                    break;
                case Xml.TEXT:
                    if( inItem ){
                        items.addElement( event.getText() );
                    }
                    break;
                case Xml.END_DOCUMENT:
                    return;
            }
        }
    }
   
    // Simple List UI component for displaying the list of
    // items parsed from the XML document.
   
    class ItemList extends List implements CommandListener {
   
        ItemList( String[] list ){
            super( "Items", IMPLICIT, list, null );
            addCommand( exitCommand );
            setCommandListener( this );
        }
       
        public void commandAction( Command c, Displayable d ){
            if( c == exitCommand ){
                exitMIDlet();
            }
        }
    }
}



Hally 2006-04-24 11:16 发表评论
]]>
推荐一个spring的教E?转了(jin)介过?http://www.tkk7.com/hallywang/archive/2006/04/03/38834.htmlHallyHallyMon, 03 Apr 2006 02:11:00 GMThttp://www.tkk7.com/hallywang/archive/2006/04/03/38834.htmlhttp://www.tkk7.com/hallywang/comments/38834.htmlhttp://www.tkk7.com/hallywang/archive/2006/04/03/38834.html#Feedback0http://www.tkk7.com/hallywang/comments/commentRss/38834.htmlhttp://www.tkk7.com/hallywang/services/trackbacks/38834.html

W? 章 简?/h2>

1.1. 概览

Spring包含许多功能和特性,q被很好地组l在下图所C的七个模块中。本节将依次介绍每个模块.

Spring框架概览

Core 包是框架的最基础部分Q?q提供依赖注入(Dependency InjectionQ特性来使你可管理Bean容器功能?q里的基概念是BeanFactoryQ它提供Factory模式来消除对E序性单例的需要, q允怽从程序逻辑中分d依赖关系的配|和描述?

构徏于Beans包上Context?/em>Q提供了(jin)一U框架式的Bean讉K方式Q?有些象JNDI注册。Context包的Ҏ(gu)得自Beans包,q添加了(jin)文本消息的发送,通过比如资源Ԍ 事g传播Q资源装载的方式和Context的透明创徏Q如通过Servlet容器?

DAO?/em> 提供?jin)JDBC的抽象层Q它可消除冗长的JDBC~码和解析数据库厂商Ҏ(gu)的错误代码?该包也提供了(jin)一U方法实现编E性和声明性事务管理,不仅仅是针对实现特定接口的类Q?而且?span class="emphasis">所有的POJO?

ORM?/em> 为流行的关系Q对象映APIs提供?jin)集成层Q包括JDOQHibernate和iBatis?通过ORM包,你可与所有Spring提供的其他特性相l合来用这些对?关系映射Q?如前Ҏ(gu)到的单声明性事务管理?

Spring?span class="emphasis">AOP?/em>提供?span class="emphasis">AOP联盟兼容的面向方面编E实玎ͼ允许你定义, 如方法拦截器和切点,来干净地给从逻辑上说应该被分ȝ功能实现代码解耦?使用源码U的元数据功能,你可各U行Z息合q到你的代码中,有点?Net的attribute?

Spring?span class="emphasis">Web?/em>提供?jin)基本的面向Web的综合特性,如Multipart功能Q?使用Servlet监听器的Context的初始化和面向Web的Applicatin Context?当与WebWork或Struts一起用SpringӞq个包Spring可与其他框架l合?

Spring?span class="emphasis">Web MVC包提供了(jin)面向Web应用的Model-View-Controller实现?Spring的MVC实现不仅仅是一U实玎ͼ它提供了(jin)一Udomain model代码和web form的清晰分, q你可使用Spring框架的所有其他特性,如校?

1.2. 使用场景

利用U木方式来描qC在各U场合用Spring的情况, 从Applet一直到完整的用Spring的事务管理功能和W(xu)eb框架的企业应用?

典型的完整Spring Web应用

一个典型的使用大部分SpringҎ(gu)的Web应用。?tt class="literal">TransactionProxyFactoryBeansQ?Web应用是完全事务性的Q就像用EJB提供的U容器管理的事务一P 所有的你的自定义业务逻辑可以通过单的POJO来实玎ͼq过Spring的Dependency Injection容器q行理。其他的服务Q如发送email和校验,独立于Web层, 使你能够军_在哪里执行校验规则?Spring的ORM支持包含?jin)HibernateQJDO和iBatis。如使用HibernateDaoSupportQ?你可复用已经存在的Hibernate映射。从Controller无缝整合web层和领域模型Q?消除?tt class="literal">ActionForms的需要和其他转换HTTP参数为领域模型的cR?

使用?jin)第三方框架的Spring中间?

有时Q现有情况不允许你彻底地转换CU不同的框架。Spring没有 你用它的全?它不是一U?span class="emphasis">全有全无 的解x案。现有的使用WebWork,Struts,Tapestry或其他的UI框架的前端程序可极佳?与基于Spring的中间层q行集成Q你可使用Spring提供的事务处理特性?你唯一要做的事是?tt class="literal">ApplicationContext来挂接你的业务逻辑?通过WebApplicationContext来集成你的Struts前端E序?

q程使用场景

当你需要通过WebService来访问你的现有代码时Q?你可使用Spring?tt class="literal">Hessian-,Burlap-, Rmi- 或?JaxRpcProxyFactorycR?使得H然l现有应用增加远E访问时不再那么困难?

EJBs - 装现有的POJO

Spring也ؓ(f)EJB提供?jin)访问层和抽象层Q?使你可复用已存在的POJOq将他们包装在Stateless SessionBean中, 以便在可能需要声明式安全(EJB中的安全理,译者注)的可升的可定w的Web应用中用?



Hally 2006-04-03 10:11 发表评论
]]>
[转]使用spring更好的处理struts动作http://www.tkk7.com/hallywang/archive/2006/03/10/34656.htmlHallyHallyFri, 10 Mar 2006 06:09:00 GMThttp://www.tkk7.com/hallywang/archive/2006/03/10/34656.htmlhttp://www.tkk7.com/hallywang/comments/34656.htmlhttp://www.tkk7.com/hallywang/archive/2006/03/10/34656.html#Feedback0http://www.tkk7.com/hallywang/comments/commentRss/34656.htmlhttp://www.tkk7.com/hallywang/services/trackbacks/34656.htmlGeorge Franciscus , 负责? Nexcel

(zhn)肯定已l听说过控制反{ (IOC) 设计模式Q因为很长一D|间以来一直在传关于它的信息。如果?zhn)在Q何功能中使用q?Spring 框架Q那么?zhn)q道其原理的作用。在本文中,我利用这一原理把一?Struts 应用E序注入 Spring 框架Q?zhn)亲w体?x)?IOC 模式的强大?/P>

一?Struts 应用E序整合q?Spring 框架h多方面的优点。首先,Spring 是ؓ(f)解决一些关?JEE 的真实世界问题而设计的Q比如复杂性、低性能和可试性,{等。第二,Spring 框架包含一?AOP 实现Q允许?zhn)面向方面技术应用于面向对象的代码。第三,一些h可能?x)?Spring 框架只有处理 Struts ?Struts 处理自己好。但是这是观炚w题,我演CZU将 Struts 应用E序整合?Spring 框架的方法后Q具体由(zhn)自己决定用哪一U?/P>

我所演示的方法都是执行v来相对简单的Q但是它们却h明显不同的优炏V我为每一U方法创Z(jin)一个独立而可用的例子Q这h可以完全理解每U方法?/P>

Z?Spring q么?jin)不P

Spring 的创立?Rod Johnson 以一U批判的眼光看待 Java? 企业软g开发,q且提议很多企业N都能够通过战略C?IOC 模式Q也UC依赖注入Q来解决。当 Rod 和一个具有奉献精的开放源码开发者团队将q个理论应用于实跉|Q结果就产生?Spring 框架。简a之,Spring 是一个轻型的容器Q利用它可以使用一个外?XML 配置文g方便地将对象q接在一赗每个对象都可以通过昄一?JavaBean 属性收C个到依赖对象的引用,留给(zhn)的单Q务就只是在一?XML 配置文g中把它们q接好?/P>
IOC ?Spring

IOC 是一U应用E序逻辑外在化的设计模式Q所以它是被注入而不是被写入客户Z码中。将 IOC 与接口编E应用结合,像 Spring 框架那样Q生了(jin)一U架构,q种架构能够减少客户机对特定实现逻辑的依赖?/P>

依赖注入是一个强大的Ҏ(gu),但是 Spring 框架能够提供更多Ҏ(gu)。Spring 支持可插拔的事务理器,可以l?zhn)的事务处理提供更q泛的选择范围。它集成?jin)领先的持久性框Ӟq且提供一个一致的异常层次l构。Spring q提供了(jin)一U用面向方面代码代替正常的面向对象代码的简单机制?/P>

Spring AOP 允许(zhn)?I>拦截?/I> 在一个或多个执行点上拦截应用E序逻辑。加强应用程序在拦截器中的日志记录逻辑?x)生一个更可读的、实用的代码基础Q所以拦截器q泛用于日志记录。?zhn)很快׃?x)看到Qؓ(f)?jin)处理横切关注点QSpring AOP 发布?jin)它自己的拦截器Q?zhn)也可以编写(zhn)自己的拦截器?/P>

整合 Struts ?Spring

?Struts 怼QSpring 可以作ؓ(f)一?MVC 实现。这两种框架都具有自q优点和缺点,管大部分h同意 Struts ?MVC 斚w仍然是最好的。很多开发团队已l学?x)在旉紧迫的时候利?Struts 作ؓ(f)构造高品质软g的基。Struts h如此大的推动力,以至于开发团队宁愿整?Spring 框架的特性,而不愿意转换?Spring MVC。没必要q行转换Ҏ(gu)来说是一个好消息。Spring 架构允许(zhn)将 Struts 作ؓ(f) Web 框架q接到基?Spring 的业务和持久层。最后的l果是现在一切条仉具备?jin)?/P>

在接下来的小H门中,(zhn)将?x)?jin)解到三种?Struts MVC 整合?Spring 框架的方法。我揭C每U方法的~陷q且Ҏ(gu)它们的优炏V?一旦?zhn)了(jin)解到所有三U方法的作用Q我会(x)向?zhn)展示一个o(h)人兴奋的应用E序Q这个程序用的是这三种Ҏ(gu)中我最喜欢的一U?/P>

三个窍?/FONT>

接下来的每种整合技术(或者窍门)(j)都有自己的优点和特点。我偏爱其中的一U,但是我知道这三种都能够加深?zhn)?Struts ?Spring 的理解。在处理各种不同情况的时候,q将l?zhn)提供一个广阔的选择范围。方法如下:(x)

  • 使用 Spring ?ActionSupport cL?Structs
  • 使用 Spring ?DelegatingRequestProcessor 覆盖 Struts ?RequestProcessor
  • ?Struts Action 理委托l?Spring 框架

装蝲应用E序环境

无论(zhn)用哪U技术,都需要?Spring ?ContextLoaderPlugin ?Struts ?ActionServlet 装蝲 Spring 应用E序环境。就像添加Q何其他插件一P单地向?zhn)?struts-config.xml 文gd该插Ӟ如下所C:(x)


<plug-in className=
  "org.springframework.web.struts.ContextLoaderPlugIn">
    <set-property property=
      "contextConfigLocation" value="/WEB-INF/beans.xml"/>
 </plug-in>

H门 1. 使用 Spring ?ActionSupport

手动创徏一?Spring 环境是一U整?Struts ?Spring 的最直观的方式。ؓ(f)?jin)它变得更单,Spring 提供?jin)一些帮助。ؓ(f)?jin)方便地获?Spring 环境Q?CODE>org.springframework.web.struts.ActionSupport cL供了(jin)一?getWebApplicationContext() Ҏ(gu)。?zhn)所做的只是?Spring ?ActionSupport 而不?Struts Action cL展?zhn)的动作,如清?1 所C:(x)


清单 1. 使用 ActionSupport 整合 Struts

package ca.nexcel.books.actions;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.struts.action.ActionError;
import org.apache.struts.action.ActionErrors;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;
import org.apache.struts.action.DynaActionForm;
import org.springframework.context.ApplicationContext;
import org.springframework.web.struts.ActionSupport;

import ca.nexcel.books.beans.Book;
import ca.nexcel.books.business.BookService;

public class SearchSubmit extends ActionSupport {   |(1)


  public ActionForward execute(
    ActionMapping mapping,
    ActionForm form,
    HttpServletRequest request,
    HttpServletResponse response)
    throws IOException, ServletException {

    DynaActionForm searchForm = (DynaActionForm) form;
    String isbn = (String) searchForm.get("isbn");
		
    //the old fashion way
    //BookService bookService = new BookServiceImpl();
		
    ApplicationContext ctx = 
      getWebApplicationContext();    |(2)
    BookService bookService = 
      (BookService) ctx.getBean("bookService");   |(3)
        
  Book book = bookService.read(isbn.trim());

    if (null == book) {
      ActionErrors errors = new ActionErrors();
      errors.add(ActionErrors.GLOBAL_ERROR,new ActionError
        ("message.notfound"));
      saveErrors(request, errors);
      return mapping.findForward("failure") ;
  }

    request.setAttribute("book", book);
    return mapping.findForward("success");
  }
}

让我们快速思考一下这里到底发生了(jin)什么。在 (1) 处,我通过?Spring ?ActionSupport c而不?Struts ?Action c进行扩展,创徏?jin)一个新?Action。在 (2) 处,我?getWebApplicationContext() Ҏ(gu)获得一?ApplicationContext。ؓ(f)?jin)获得业务服务,我用?(2) 处获得的环境?(3) 处查找一?Spring bean?/P>

q种技术很单ƈ且易于理解。不q的是,它将 Struts 动作?Spring 框架耦合在一赗如果?zhn)x换掉 SpringQ那么?zhn)必须重写代码。ƈ且,׃ Struts 动作不在 Spring 的控制之下,所以它不能获得 Spring AOP 的优ѝ当使用多重独立?Spring 环境Ӟq种技术可能有用,但是在大多数情况下,q种Ҏ(gu)不如另外两种Ҏ(gu)合适?/P>

H门 2. 覆盖 RequestProcessor

?Spring ?Struts 动作中分L一个更巧妙的设计选择。分ȝ一U方法是使用 org.springframework.web.struts.DelegatingRequestProcessor cL覆盖 Struts ?RequestProcessor 处理E序Q如清单 2 所C:(x)


清单 2. 通过 Spring ?DelegatingRequestProcessor q行整合

<?xml version="1.0" encoding="ISO-8859-1" ?>

<!DOCTYPE struts-config PUBLIC
          "-//Apache Software Foundation//DTD Struts Configuration 1.1//EN"
          "http://jakarta.apache.org/struts/dtds/struts-config_1_1.dtd">

<struts-config>
 <form-beans>
    <form-bean name="searchForm" 
      type="org.apache.struts.validator.DynaValidatorForm">
               <form-property name="isbn"    type="java.lang.String"/>
    </form-bean>
  
  </form-beans>

 <global-forwards type="org.apache.struts.action.ActionForward">
     <forward   name="welcome"                path="/welcome.do"/>
     <forward   name="searchEntry"            path="/searchEntry.do"/>
     <forward   name="searchSubmit"           path="/searchSubmit.do"/>
 </global-forwards>

 <action-mappings>
    <action    path="/welcome" forward="/WEB-INF/pages/welcome.htm"/>
    <action    path="/searchEntry" forward="/WEB-INF/pages/search.jsp"/>
    <action    path="/searchSubmit" 
               type="ca.nexcel.books.actions.SearchSubmit"
               input="/searchEntry.do"
               validate="true"
               name="searchForm">
              <forward name="success" path="/WEB-INF/pages/detail.jsp"/>
              <forward name="failure" path="/WEB-INF/pages/search.jsp"/>
    </action>  

 </action-mappings>

 <message-resources parameter="ApplicationResources"/>

 <controller processorClass="org.springframework.web.struts.
   DelegatingRequestProcessor"/> |(1)

 <plug-in className="org.apache.struts.validator.ValidatorPlugIn">
    <set-property property="pathnames" 
      value="/WEB-INF/validator-rules.xml,/WEB-INF/validation.xml"/>
 </plug-in>


 <plug-in className="org.springframework.web.struts.ContextLoaderPlugIn">
    <set-property property="csntextConfigLocation" value="/WEB-INF/beans.xml"/>
 </plug-in>
 
</struts-config>

我利用了(jin) <controller> 标记来用 DelegatingRequestProcessor 覆盖默认?Struts RequestProcessor。下一步是在我?Spring 配置文g中注册该动作Q如清单 3 所C:(x)


清单 3. ?Spring 配置文g中注册一个动?/B>

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" 
  "http://www.springframework.org/dtd/spring-beans.dtd">

<beans>
  <bean id="bookService" class="ca.nexcel.books.business.BookServiceImpl"/>

  <bean name="/searchSubmit" 
    class="ca.nexcel.books.actions.SearchSubmit"> |(1)
     <property name="bookService">
        <ref bean="bookService"/>
     </property>
  </bean>
</beans>

注意Q在 (1) 处,我用名U属性注册了(jin)一?beanQ以匚w struts-config 动作映射名称?CODE>SearchSubmit 动作揭示?jin)一?JavaBean 属性,允许 Spring 在运行时填充属性,如清?4 所C:(x)


清单 4. h JavaBean 属性的 Struts 动作

package ca.nexcel.books.actions;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.struts.action.Action;
import org.apache.struts.action.ActionError;
import org.apache.struts.action.ActionErrors;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;
import org.apache.struts.action.DynaActionForm;

import ca.nexcel.books.beans.Book;
import ca.nexcel.books.business.BookService;

public class SearchSubmit extends Action {
	
  private BookService bookService;
  public BookService getBookService() {
    return bookService;
  }

  public void setBookService(BookService bookService) { | (1)
    this.bookService = bookService; 
  } 

  public ActionForward execute(
    ActionMapping mapping,
    ActionForm form,
    HttpServletRequest request,
    HttpServletResponse response)
    throws IOException, ServletException {

    DynaActionForm searchForm = (DynaActionForm) form;
    String isbn = (String) searchForm.get("isbn");
		
  Book book = getBookService().read(isbn.trim());  |(2)

    if (null == book) {
      ActionErrors errors = new ActionErrors();
      errors.add(ActionErrors.GLOBAL_ERROR,new ActionError("message.notfound"));
      saveErrors(request, errors);
      return mapping.findForward("failure") ;
  }

      request.setAttribute("book", book);
      return mapping.findForward("success");
  }

}

在清?4 中,(zhn)可以了(jin)解到如何创徏 Struts 动作。在 (1) 处,我创Z(jin)一?JavaBean 属性?CODE>DelegatingRequestProcessor自动地配|这U属性。这U设计 Struts 动作q不知道它正?Spring 理Qƈ且(zhn)能够利?Sping 的动作管理框架的所有优炏V由于?zhn)?Struts 动作注意不到 Spring 的存在,所以?zhn)不需要重写?zhn)?Struts 代码可以用其他控制反转容器来替换?Spring?/P>

DelegatingRequestProcessor Ҏ(gu)的确比第一U方法好Q但是仍然存在一些问题。如果?zhn)使用一个不同的 RequestProcessorQ则需要手动整?Spring ?DelegatingRequestProcessor。添加的代码?x)造成l护的麻?ch)ƈ且将来?x)降低(zhn)的应用E序的灵zL。此外,q有q一些用一pd命o(h)来代?Struts RequestProcessor 的传闅R?q种改变会(x)对这U解x法的使用寿命造成负面的媄(jing)响?/P>

H门 3. 动作管理委托给 Spring

一个更好的解决Ҏ(gu)是将 Strut 动作理委托l?Spring。?zhn)可以通过?struts-config 动作映射中注册一个代理来实现。代理负责在 Spring 环境中查?Struts 动作。由于动作在 Spring 的控制之下,所以它可以填充动作?JavaBean 属性,qؓ(f)应用诸如 Spring ?AOP 拦截器之cȝҎ(gu)带来了(jin)可能?

清单 5 中的 Action cM清单 4 中的相同。但?struts-config 有一些不同:(x)


清单 5. Spring 整合的委托方?/B>

<?xml version="1.0" encoding="ISO-8859-1" ?>

<!DOCTYPE struts-config PUBLIC
          "-//Apache Software Foundation//DTD Struts Configuration 1.1//EN"
          "http://jakarta.apache.org/struts/dtds/struts-config_1_1.dtd">

<struts-config>
 <form-beans>
    <form-bean name="searchForm" 
      type="org.apache.struts.validator.DynaValidatorForm">
               <form-property name="isbn"    type="java.lang.String"/>
    </form-bean>
  
  </form-beans>

 <global-forwards type="org.apache.struts.action.ActionForward">
     <forward   name="welcome"                path="/welcome.do"/>
     <forward   name="searchEntry"            path="/searchEntry.do"/>
     <forward   name="searchSubmit"           path="/searchSubmit.do"/>
 </global-forwards>

 <action-mappings>
    <action    path="/welcome" forward="/WEB-INF/pages/welcome.htm"/>
    <action    path="/searchEntry" forward="/WEB-INF/pages/search.jsp"/>
    <action    path="/searchSubmit" 
             type="org.springframework.web.struts.DelegatingActionProxy" |(1)
             input="/searchEntry.do"
             validate="true"
             name="searchForm">
             <forward name="success" path="/WEB-INF/pages/detail.jsp"/>
             <forward name="failure" path="/WEB-INF/pages/search.jsp"/>
    </action>  

 </action-mappings>

 <message-resources parameter="ApplicationResources"/>


 <plug-in className="org.apache.struts.validator.ValidatorPlugIn">
    <set-property 
    property="pathnames" 
    value="/WEB-INF/validator-rules.xml,/WEB-INF/validation.xml"/>
 </plug-in>


 <plug-in 
    className="org.springframework.web.struts.ContextLoaderPlugIn">
    <set-property property="contextConfigLocation" value="/WEB-INF/beans.xml"/>
 </plug-in>

 
</struts-config>

清单 5 是一个典型的 struts-config.xml 文gQ只有一个小的差别。它注册 Spring 代理cȝ名称Q而不是声明动作的cdQ如Q?Q处所C。DelegatingActionProxy cM用动作映名U查?Spring 环境中的动作。这是我们使用 ContextLoaderPlugIn 声明的环境?/P>

一?Struts 动作注册Z?Spring bean 是非常直观的Q如清单 6 所C。我利用动作映射使用 <bean> 标记的名U属性(在这个例子中?"/searchSubmit"Q简单地创徏?jin)一?bean。这个动作的 JavaBean 属性像M Spring bean 一栯填充Q?


清单 6. ?Spring 环境中注册一?Struts 动作

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" 
 "http://www.springframework.org/dtd/spring-beans.dtd">

<beans>
  <bean id="bookService" class="ca.nexcel.books.business.BookServiceImpl"/>

  <bean name="/searchSubmit"   
        class="ca.nexcel.books.actions.SearchSubmit">
     <property name="bookService">
        <ref bean="bookService"/>
     </property>
  </bean>

</beans>


动作委托的优?/FONT>

动作委托解决Ҏ(gu)是这三种Ҏ(gu)中最好的。Struts 动作不了(jin)?SpringQ不对代码作M改变可用于?Spring 应用E序中?CODE>RequestProcessor 的改变不?x)?jing)响它Qƈ且它可以利用 Spring AOP Ҏ(gu)的优点?

动作委托的优点不止如此。一旦让 Spring 控制(zhn)的 Struts 动作Q?zhn)可以?Spring l动作补充更强的zd。例如,没有 Spring 的话Q所有的 Struts 动作都必LU程安全的。如果?zhn)讄?<bean> 标记?singleton 属性ؓ(f)“false”,那么不管用何U方法,(zhn)的应用E序都将在每一个请求上有一个新生成的动作对象。?zhn)可能不需要这U特性,但是把它攑֜(zhn)的工具׃也很好。?zhn)也可以利?Spring 的生命周期方法。例如,当实例化 Struts 动作Ӟ<bean> 标记?init-method 属性被用于q行一个方法。类似地Q在从容器中删除 bean 之前Qdestroy-method 属性执行一个方法。这些方法是理昂贵对象的好办法Q它们以一U与 Servlet 生命周期相同的方式进行管理?/P>

拦截 Struts

前面提到q,通过?Struts 动作委托l?Spring 框架而整?Struts ?Spring 的一个主要的优点是:(x)(zhn)可以将 Spring ?AOP 拦截器应用于(zhn)的 Struts 动作。通过?Spring 拦截器应用于 Struts 动作Q?zhn)可以用最的代h(hun)处理横切x炏V?/P>

虽然 Spring 提供很多内置拦截器,但是我将向?zhn)展示如何创徏自己的拦截器q把它应用于一?Struts 动作。ؓ(f)?jin)用拦截器Q?zhn)需要做三g事:(x)

  1. 创徏拦截器?
  2. 注册拦截器?
  3. 声明在何处拦截代码?/LI>

q看h非常单的几句话却非常强大。例如,在清?7 中,我ؓ(f) Struts 动作创徏?jin)一个日志记录拦截器?q个拦截器在每个Ҏ(gu)调用之前打印一句话Q?/P>
清单 7. 一个简单的日志记录拦截?/B>

package ca.nexcel.books.interceptors;

import org.springframework.aop.MethodBeforeAdvice;

import java.lang.reflect.Method;

public class LoggingInterceptor implements MethodBeforeAdvice {

   public void before(Method method, Object[] objects, Object o) throws Throwable {
        System.out.println("logging before!");
    }
}

q个拦截器非常简单?CODE>before() Ҏ(gu)在拦截点中每个方法之前运行。在本例中,它打印出一句话Q其实它可以做?zhn)惛_的Q何事。下一步就是在 Spring 配置文g中注册这个拦截器Q如清单 8 所C:(x)


清单 8. ?Spring 配置文g中注册拦截器

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" 
  "http://www.springframework.org/dtd/spring-beans.dtd">

<beans>
  <bean id="bookService" class="ca.nexcel.books.business.BookServiceImpl"/>

  <bean name="/searchSubmit" 
        class="ca.nexcel.books.actions.SearchSubmit">
     <property name="bookService">
        <ref bean="bookService"/>
     </property>
  </bean>

  <!--  Interceptors --> 
  <bean name="logger"    
    class="ca.nexcel.books.interceptors.LoggingInterceptor"/> |(1)

  <!-- AutoProxies -->
  <bean name="loggingAutoProxy" 
        class="org.springframework.aop.framework.autoproxy.
          BeanNameAutoProxyCreator"> |(2)
    <property name="beanNames">
          <value>/searchSubmit</valuesgt; |(3)
    </property>
    <property name="interceptorNames">
        <list>
          <value>logger</value> |(4)
        </list>
    </property>
   </bean>

</beans>

(zhn)可能已l注意到?jin),清?8 扩展?清单 6 中所C的应用E序以包含一个拦截器。具体细节如下:(x)

  • ?(1) 处,我注册了(jin)q个拦截器?
  • ?(2) 处,我创Z(jin)一?bean 名称自动代理Q它描述如何应用拦截器。还有其他的Ҏ(gu)定义拦截点,但是q种Ҏ(gu)常见而简ѝ?
  • ?(3) 处,我将 Struts 动作注册为将被拦截的 bean。如果?zhn)惌拦截其他?Struts 动作Q则只需要在 "beanNames" 下面创徏附加?<value> 标记?
  • ?(4) 处,当拦截发生时Q我执行?jin)?(1) 处创建的拦截?bean 的名U。这里列出的所有拦截器都应用于“beanNames”?/LI>

是q样。就像这个例子所展示的,?zhn)?Struts 动作|于 Spring 框架的控制之下,为处理?zhn)?Struts 应用E序提供?jin)一pd全新的选择。在本例中,使用动作委托可以L地利?Spring 拦截器提?Struts 应用E序中的日志记录能力?/P>

l束?/FONT>

在本文中Q?zhn)已经学?fn)?jin)?Struts 动作整合?Spring 框架中的三种H门。?Spring ?ActionSupport 来整?StrutsQ第一U窍门中是q样做的Q简单而快P但是?x)?Struts 动作?Spring 框架耦合在一赗如果?zhn)需要将应用E序ULC个不同的框架Q则需要重写代码。第二种解决Ҏ(gu)通过委托 RequestProcessor 巧妙地解开代码的耦合Q但是它的可扩展性不强,q且?Struts ?RequestProcessor 变成一pd命o(h)Ӟq种Ҏ(gu)持l不?jin)很长时间。第三种Ҏ(gu)是这三种Ҏ(gu)中最好的Q将 Struts 动作委托l?Spring 框架可以使代码解耦,从而(zhn)可以在(zhn)的 Struts 应用E序中利?Spring 的特性(比如日志记录拦截器)(j)?/P>

参考资?

学习(fn)

关于作?/FONT>

George Franciscus ?Java 公司的一名顾问和 Struts 斚w的权威。他?Manning 出版?Struts Recipes ?Struts in Action 的合著者?George 通过 nexcel.ca 提供有关技术和理斚w的咨询服务?/P>



Hally 2006-03-10 14:09 发表评论
]]>
վ֩ģ壺 ó˾þAvѸ| ѹۿƵ| 91µַ| 91ɫƷ| һƵ߲| ŷպ| һëƬѿ| Ļ| ޾Ʒ㶮վ| ޳avƬ߿Ƭ| bbbѹۿƵ| 99þѹۿ| ŷëƬAƵ޷| þ޾ƷĻ| aר߹ۿɫ | ʮ˽վ߹ۿ| ޹ۺ| ޾Ʒ91| һػaƬ| þùƵ| ɫ͵ר| ޾ƷŮһ| þþþѾƷ| ձɫַ| jlzzjlzzjzjzjz| Ұ߹ۿƵ| ձѹۿվ| Ƶ߹ۿ| ŮˮƵwww| ȫAëƬѿվ| ɫ| ޾ƷƵѹۿ| 쿴Ƭˬ_Ѳ| ޳˾Ʒþ| ƷѴƬһ| ҹһëƬƵ| ޾ƷߵӰ| Ƶ߹ۿ | žAV뾫ƷëƬ| ԭ1769þѲ| ޻Ƭֻѹۿ|