??xml version="1.0" encoding="utf-8" standalone="yes"?> 关于q一版本的更C息请参见q里?/p> 我们需要用的有三U类型的数据。在开始之前,我们需要有个方法来获得对单元格的访问。这一节的其他辅助性方法也用此ҎQ定义如下:
首先Q我们将要接触到文本cd的数据,比如说Javalobby文章的标题。对于这U数据,辅助性方法需要电子表对象、列位置、行位置以及数据本n作ؓ参数?
其次Q对于数字类型的数据Q比如说“Reply”列的数据Q辅助性方法要求传递doublecd的参敎ͼ
最后,管Calc的公式是普通的字符Ԍ我们可以使用OpenOffice.org的API所包含的单元格样式属性来为单元格讄预定义的“Result”样式Q这主要是针Ҏ们汇d复L的计公式来q行讄Q?
下面的代码将在随后被使用Q?
在ARGB颜色I间中,0xFF9933代表色。如果行数是偶数Q那么电子表、行C及橙色会被作为参C递给ҎQ?
如果用户需要看?#8220;Most Replies”或?#8220;Least Replies”Q我们将使用以下代码q行讄Q?
以下的方法需要电子表、列数、行C及颜色g为参敎ͼ
本文译自NetBeans.org中的文章,其中的代码也都经q译者测试。未完待l!Q! 上一节描q的Ҏ帮助我们从服务管理器中获取了com.sun.star.frame.Desktop服务。Desktop可以Ҏl定的URL来加载新的或者已l存在的lg。ؓ了提供这L服务QDesktop实现了com.sun.star.frame.XcomponentLoader接口Q这个接口只有一个方法根据给定的URL加蝲和实例化对应的组件。要构徏一个新的电子表格文档组Ӟ可以使用“private:factory/scalc”q样的URL。关于更详细的信息请参考OpenOffice.org开发指南《第8?nbsp; 电子表格》中?.2.1 “电子表格文档的徏立和加蝲”?/p>
下面q个Ҏ由用户界面所调用Q在调用之前用户需要将必要的参C递给上面代码中描q的ҎQ?
接着Q我们需要获取电子表格文档对象:
下一个定义的ҎQgetXSpreadsheet( )Q定义如下,q个Ҏ帮助我们_定位要与哪个电子表格文档q行交互。默认情况下QCalc应用E序在启动的时候就已经建立好了三个电子表。这三个电子表的名称分别?#8220;Sheet1”?#8220;Sheet2”?#8220;Sheet3”Q这三个电子表会随着您启动Calc应用E序而打开。如果您字W串“Sheet1”传递给getXSpreadsheet( )ҎQ那么接下来您所做的改动都将?#8220;Sheet1”电子表中q行。然而,您或许想要给自定义的电子表v一个不同于默认命名方式的名字。比如说Q您电子表命名?#8220;Javalobby Article
Analyzer”。如果您这个名字作为参C递给getXSpreadsheet( )ҎQ一个以此字W串命名的电子表被构徏?
然而,默认情况下,?#8220;Sheet1”的电子表仍然是当前电子表Q所谓当前电子表是在应用程序启动时呈现在用户面前的那个电子表。无论您是否新徏电子表,默认的三个电子表始终都是存在的。假如您惛_您自己定义的电子表设为当前状态,您可以有两种选择。一U是使用在getXSpreadsheet( )Ҏ之后定义的getXActiveSpreadsheet(
)ҎQ另外您可以直接默认的三个电子表删除掉Q就如下面的getXSpreadsheet( )Ҏ中的一P而一旦这三个电子表被删除之后也就只剩下您自定义的那个电子表了Q所剩的最后一个电子表也就理所当然地成为当前电子表了?
接下来的Ҏ是如何将电子表设为当前电子表Q?
本文译自NetBeans.org中的文章,其中的代码也都经q译者测试。未完待l!Q! 许多商业应用E序允许用户在应用程序中生成Z某些数据的报表。电子表格特别适合用于生成q样的报表。电子表g仅可以将数据l格式化以后以结构化的Ş式展现给用户Q而且为用h供了快速且高效的数据处理功能。正如上面所说的QOpenOffice.org的API提供了大量的cdҎ以方便开发者将OpenOffice.org电子表格的功能集成到他们自己的应用程序中。在应用E序中,单击某个按钮可以启动OpenOffice.orgq将应用E序生成的数据以自定义电子表格的形式展现出来?
新手可能p个开发领域很自然地提Z个问题:“一旦开发者正地安装了所有需要的软g后,一个应用程序如何启动OpenOffice.org的新实例以及如何获取q接呢?”。这个问题得C需要的回答之后Q开发者还可能提出Q?#8220;现在用户应用E序已经获取了OpenOffice.org的连接,那么应用E序应该如何这些数据嵌入到电子表格中呢Q?#8221;。在q篇文章中,我们首先着重满不熟悉OpenOffice.org的API的开发者的两个基本的需求。我们将向开发者展C如何获取到OpenOffice.org的连接,如何应用程序的数据转化为电子表格Ş式的数据。接着我们讨Z些其他的主题Q这些主题包括以~程方式构徏和析构电子表根{设|电子表格的单元格的背景颜色以及单元D框的格式化。然而,q里需要注意的是我们只xOpenOffice.org本n的集成,Z代码的可L我们忽略了诸如错误处理之类的问题。在q篇文章的结,您将对OpenOffice.org的API处理电子表格和如何在您自q应用E序中利用它们的相关知识有所了解?
q篇文章涉及的应用程序是ZSwing的应用程序,它通过使用OpenOfiice.org的API来访问OpenOffice.org的各U功能。当Ӟ您也可以使用C++或者COM/DCOM技术来q接OpenOffice.org。此cd用程序的代码q不一定必d于Swing来编写。这L应用E序可以使用C++、Java servlet、Java Server Page、JavaScript、VBScript、Delphi以及Visual Basic来编写。这文章中使用的基于Swing的应用程序将使用NetBeans IDE来构建,q且使用NetBeans Platform作ؓ起始炏V尽Q何集成开发工具都可以被用来构建如此简单的应用E序Q但是用NetBeansq行开发具有两优ѝ首先,在NetBeans中我们可以充分发挥GUI构徏器(即MatisseQ的功能来构建用L面,GUI构徏器可以帮助我们快速徏立应用程序界面的原型。其ơ,我们的应用E序ZNetBeans Platform意味着我们不需要再重头开始,而且我们可以通过其提供的模块框架来增强应用程序的可扩展性。这个应用程序将生成如下图所C的不需要Q何后期处理的电子表格文档Q?
电子表格中的数据来自于JTablelg。在现实情况下,q些数据往往来源于数据库中。在上面q及的应用程序中Q我们将把数据硬~码在程序代码中Q这主要是因为数据的来源问题已经出本篇文章的范围了。无论数据是否是来自于数据库Q当用户已经完成了数据的处理后,应用E序把JTable中的数据转换生成电子表格来呈现。除了数据之外,上面的图q展CZ以下几个元素Q这些元素将在下面的章节中述及:
q篇文章被分Z部分Q这三部分按序描述了开发的q程Q?
在开始之前,请先认以下的Y件已l安装好了:
注意Q这文章中展现的应用场景ƈ不需要用OpenOffice.org SDK。如果我们要使用SDK中的idlc或者javamaker{工P那么q个时候才需要SDK?
当我们用OpenOffice.org的API工作Ӟ我们可能会重复地执行某些d。比如说Q我们设|电子表D头的颜色Q但是同时我们也需要设|其他各行的颜色。实际上Q我们经怺替地讄各行的颜Ԍq样可以使得电子表格中的行更Ҏ分L。如果某文章的回复数比较高Q我们会对应的行设|ؓ不同的颜Ԍl色Q,而回复数比较低的行也被设|ؓ不同的颜ԌU色Q。行的颜色的讄需要编写用OpenOffice.org的API中的很多Ҏ的几行代码,而ؓ了避免重复编写相同的代码Q我们将q些代码l织C个辅助性方法当中去Q在需要进行设|的时候,我们只需要将颜色作ؓ参数传递就可以了。这可以使我们的代码易读性更好,更容易维护。下面我们将更详l地讨论q些辅助性方法?
误住,以下q及的辅助性方法可以用于Q何应用程序,q些辅助性方法ƈ不依赖于本篇文章里述及的应用E序。换句话_您可以充分地利用q些辅助性方法,在需要的时候不需要对代码q行M修改可以将q些代码_脓到应用程序的Java文g中用。您也可以在您的代码中引用这些代码,像q篇文章中做的一栗?
OpenOffice.org的Java API有自qҎ来引导OpenOffice.org。所?#8220;引导”OpenOffice.orgQ我们的意思是加蝲OpenOffice.org的启动程序。这通过Ljuh.jar文g所在的位置Q然后在q个位置或者上一U目录查找sofficeQ?exeQ来实现。这需要将juh.jar文g|于pȝ变量CLASSPATH所描述的目录中Q这h章构建的应用E序可以访问到q个文g。然而,q里需要将juh.jar文g随同应用E序一起分发,q种情况下,q种引导机制׃奏效了?
Z解决q个问题Q有两种可能的方法。首先,可以保Java随时都可以查扑ֈsofficeQ?exeQ,q可以通过包含可执行文g的目录加入到Windows的PATHpȝ变量中(在Mac、Unix和Linux中就是LD_LIBRARY_PATHpȝ变量Q。这U方法需要用戯行一些操作,而我们ƈ不希望这样做?
因此Q我们更們于推荐第二种ҎQ这U方法需要与讉K修饰W协同工作。在Sun的JDK中,ClassLoaderpȝcLURLClassLoadercȝ实例。这个类有一个私有方法addURLQ这个方法在Javapȝ开始的时候将被调用,从而将JAR文g以及其他相关资源d到系l环境中。通过反射机制Q我们获取一个URLClassLoader的实例,后使得addURLҎ辑ֈ可访问状态,然后再将包含可执行文件的目录d到URLClassLoader的URL栈中。这虽然昑־很晦涩,但是q种Ҏ很奏效?
但是Q它真的那么奏效吗?与系l类的访问修饰周旋L一件冒险的事情。addURLҎ被声明ؓprotected型的Q自然有其理由。另外,谁能保证使用的一定是Sun的JDK呢?或者Sun可能在随后的版本中忽略这个方法?然而,Java规范对上q这些事情ƈ没有作出明确的声明,因此别的JDK在默认情况下q不是将ClassLoadercȝcd配置为URLClassLoader。正是这个原因,我们使用“loader instanceof URLClassLoader”q样的检查代码来保事情是如预期那样的。这也是我们在用h有用Sun的JDK的情况下保应用E序没有M异常情况而需付出的代仗?
关于q程中构建对象的更详l的信息请参考OpenOffice.org的开发指南《第6?nbsp; Office开发》?
另一中方法就是用远E连接。在q程q接中,服务器名U和端口号作为参C递给q程q接ҎQ然后这个方法启动OpenOffice.orgq返回Desktop对象Q这个对象是利用OpenOffice.org工作的v炏V而且在远E连接的情况下,您可以让用户选择服务器和端口Q或者您可以在代码中使用pȝ讄来提供服务器和端口,q都看您的选择?
本文译自NetBeans.org中的文章,其中的代码也都经q译者测试。未完待l!Q!
throws Exception
{
return xSpreadsheet.getCellByPosition(x, y);
}
xSpreadsheet, int x, int y, String value) throws Exception
{
//We first identify the cell we need to work with,
//using the incoming x and y values:
XCell xCell = getXCellByPosition(xSpreadsheet, x, y);
//Next, since we're working with text, we define
//a text object and a cursor object and insert the received content into the cell:
XText xText = (com.sun.star.text.XText)UnoRuntime.queryInterface(com.sun.
star.text.XText.class, xCell);
XTextCursor xTextCursor = xText.createTextCursor();
xText.insertString(xTextCursor, value, false);
}
xSpreadsheet, int x, int y, double value) throws Exception
{
//First we get the cell identified by the received x and y values:
XCell xCell = getXCellByPosition(xSpreadsheet, x, y);
//Then we add the received value to the identified cell:
xCell.setValue(value);
}
xSpreadsheet, int x, int y, String formula) throws Exception
{
//We get the cell defined by the incoming x and y values"
XCell xCell = getXCellByPosition(xSpreadsheet, x, y);
//We add a Calc formula to the cell, as received by the helper method:
xCell.setFormula(formula);
//We attach a property set to our cell, so that we can define a property:
XPropertySet xCellProps = (XPropertySet)UnoRuntime.
queryInterface(XPropertySet.class, xCell);
//We set the style of the cell, using a predefined "Result" style,
//which comes out of the box with the OpenOffic.org API:
xCellProps.setPropertyValue("CellStyle", "Result");
} 3.4 颜色的?/h3>
{
oooHelper.setColorRow(xSpreadsheet, position, 0xFF9933);
}
xSpreadsheet, int row, int color) throws Exception
{
//First we get the range of cells we want to deal with,
//which is the whole spreadsheet:
XCellRange xCellRange = (XCellRange)UnoRuntime.queryInterface
( XCellRange.class, xSpreadsheet );
//Next, we narrow down our selection further,
//going from column 0/current row to column 3/current row,
//which is a whole row from left to right:
XCellRange xSelectedCells = xCellRange.getCellRangeByPosition(0, row, 3, row);
//Next, we create a property set and assign it to our selected range:
XPropertySet xCellProps =
(XPropertySet)UnoRuntime.queryInterface(XPropertySet.class,xSelectedCells);
//This line sets the color to white, which basically
//refreshes the row color before we add our new row color:
xCellProps.setPropertyValue("CellBackColor", new Integer(16777215));
//This line sets the color to whatever is received,
//in this case orange:
xCellProps.setPropertyValue("CellBackColor", new Integer(color));
}
throws Exception
{
//First, we select the entire received spreadsheet:
XCellRange xCellRange = (XCellRange)UnoRuntime.queryInterface( XCellRange.class,
xSpreadsheet );
//From the received spreadsheet, we select a single cell,
//defined by the row and column received:
XCellRange xSelectedCells = xCellRange.getCellRangeByPosition(column,
row, column, row);
//We define a property set, an object to contain the cell's properties:
XPropertySet xCellProps = (XPropertySet)UnoRuntime.queryInterface
(XPropertySet.class, xSelectedCells);
//This line sets the color to white, to refresh the cell:
xCellProps.setPropertyValue("CellBackColor", new Integer(16777215));
//This line sets the background color of the cell to whatever is received:
xCellProps.setPropertyValue("CellBackColor", new Integer(color));
}
throws Exception
{
XComponentLoader xComponentLoader =
(XComponentLoader)UnoRuntime.queryInterface(XComponentLoader.class, desktop);
PropertyValue[] pPropValues;
pPropValues = new PropertyValue[0];
return xComponentLoader.loadComponentFromURL(templateURL, "_blank",0, pPropValues);
}
oooHelper.getSpreadsheetComponent(desktop, "private:factory/scalc");
throws Exception
{
return(XSpreadsheetDocument)UnoRuntime.queryInterface
(XSpreadsheetDocument.class, xSpreadsheetComponent);
}
throws Exception
{
XSpreadsheets xSpreadsheets = xSpreadsheetDocument.getSheets();
//See section 2.5.2 of the OpenOffice.org API:
xSpreadsheets.insertNewByName(name, (short)0);
Object sheet = xSpreadsheets.getByName(name);
xSpreadsheets.removeByName("Sheet1");
xSpreadsheets.removeByName("Sheet2");
xSpreadsheets.removeByName("Sheet3");
return (XSpreadsheet)UnoRuntime.queryInterface(XSpreadsheet.class, sheet);
}
XSpreadsheet xSpreadsheet) throws Exception
{
XModel xSpreadsheetModel = (XModel)UnoRuntime.queryInterface(XModel.class,
xSpreadsheetComponent);
XController xSpreadsheetController = xSpreadsheetModel.getCurrentController();
XSpreadsheetView xSpreadsheetView = (XSpreadsheetView)UnoRuntime.
queryInterface(XSpreadsheetView.class, xSpreadsheetController);
xSpreadsheetView.setActiveSheet(xSpreadsheet);
return xSpreadsheet;
}
2.pȝ需?/h3>
3.背景知识Q简化重复的~码工作
3.1 使用引导E序
{
//Get the executable from the incoming String:
String ooBaseDirectory = pathToExecutable.replaceAll("soffice(.exe){0,1}$","");
System.out.println("Your ooBaseDir is: " + ooBaseDirectory);
ClassLoader loader = ClassLoader.getSystemClassLoader();
if (loader instanceof URLClassLoader){
URLClassLoader cl = (URLClassLoader)loader;
Class sysclass = URLClassLoader.class;
try {
Method method = sysclass.getDeclaredMethod
("addURL", new Class[]{URL.class});
method.setAccessible(true);
method.invoke(cl, new Object[]{new File(ooBaseDirectory).toURL()});
} catch (Throwable t) {
t.printStackTrace();
throw new IOException("Error, could not add URL to system classloader");
}
} else {
System.out.println("Error occured, URLClassLoader expected but " +
loader.getClass() + " received. Could not continue.");
}
//Get the office component context:
XComponentContext xContext = Bootstrap.bootstrap();
//Get the office service manager:
XMultiComponentFactory xServiceManager = xContext.getServiceManager();
//Create the desktop, which is the root frame of the
//hierarchy of frames that contain viewable components:
Object desktop = xServiceManager.createInstanceWithContext
("com.sun.star.frame.Desktop", xContext );
return desktop;
}
标注现在已经很流行了Q许多h选择它作为XML的替代来q行元数据编E。标注中不应该包含配|信息,而iBATIS通过XML来进行的工作也不光是配置?/p>
那么什么是配置Q什么又不是呢?目前QiBATIS的XML文g包含了三斚wQ?/p>
当您把环境设|改变后Q您同时也需要更攚w|,例如数据库连接配|、事务管理配|等{。当您将应用分发C同的数据库,而且也用了一些专有的SQL语句后,配置中可能还要包含SQL方言的一些配|信息。在iBATIS 3.0中我们可以将q些信息包含q去Q因此,您需要针对多U方aq行~码Q当然这是手工的Q,为它们命名,q将它们配置到适当的位|。配|信息不应该被包含在Java源文件中?/p>
元数据信息包括诸如结果映、参数映和~存模型之类的信息。这些信息控制iBATIS如何映射您的数据以及q些映射的具体表现?/p>
~码包括SQL以及动态的SQL语句?/p>
那么标注应该承担什么样的职责呢Q?/p>
一般情况下Q只有元数据信息比较适合使用标注来描q。配|应该通过属性文件或者XML文g来实现。编码也只能通过Java文g或者XML文g来实现。更q一步看Q标注只能用来描q相对较单的元数据信息。有Ӟ标注Q特别是在Java中)也会使事情变得更加复杂,使代码更加晦涩难懂?/p>
因ؓ上面的原因,所以我推荐只将标注作ؓU定配置的替代配|。这是_使用q种配置方式可以辑ֈ一定的效果Q但是也仅仅限于此?/p>
再一ơ强调,C#的Attribute在某些方面要ZJava的标注:
下面q个例子展示了如何用Java中的标注来完成配|:
下面q个例子要更加复杂一些,像这U用了如此多的标注的情况就应该考虑使用XML文g来进行配|。这U情况下Q我惌标注能够提供一切功能,即XML中实现的功能通过标注也能完成。然而,我们q是您在面对复杂的情冉|使用XML来进行配|。或许某些h不是特别在意使用XML配置Q所以我们ؓ他们提供了标注配|方式?/p>
Clinton_q一Ҏ与我们以前所坚持的原则不相符合的。认识我的h都知道我基本上算是一个完的人。但是如果我们从最佛_늚角度去考虑Q我们必d解决复杂问题的时候也使用量单的解决Ҏ。当Ӟ那些不太喜欢U定俗成式配|的人可以忽略这U配|方式。但是我怿q是非常有用的,特别是对插入、删除和更新操作来说。用这U配|方式,一些简单的查询也将从中受益?/p>
默认情况下,iBATIS 3.0用约定俗成式的配|方式。Java 5的方法语义中已经包含了生成SQL、进行参数和l果映射_的信息。例如:
q些信息对于生成以下SQL已经_了:
l果cd与方法的q回值类型是一致的。因为方法的q回值类型不是集合类型,所以我们知道正在处?#8220;Select One”语义。表的名U被假定Zl果cd的名UC致。而查询参数就被假定ؓҎ对应的参数。在使用其他的配|方式的时候,我们可以更改默认ID参数的配|。SQL语句中的各数据列假定与方法返回类型的同名属性一一对应Q当然这些配|都是可以更改的?/p>
集合cd也是以同L方式工作Q?/p>
q个例子生以下SQL语句Q?/p>
我们可以这个例子叫?#8220;Select Many”Q因个方法返回了一个集合类型。我们知道Where子句为空Q因个方法没有Q何参数?/p>
如果我们想用参数式查询Q我们可以这h做:
假设只有参数的lastNameQ而其他引用类型都为null|原始cd都被讄为非法无意义的|比如-1Q,我们得C下的SQL语句Q?/p>
或者可以直接按参数来进行:
q将生成以下的SQL语句Q?/p>
因ؓC#支持参数名称的反,所以C#对这U方法提供了更好的支持。Ş式上也变得相Ҏ晎ͼ当然实质是一LQ?/p>
更新操作也以相同的方式操作:
也可以自动接受集合参敎ͼ
生成器相当的灉|Q而且可以为大多数删除甚至更新操作生成一条SQL语句?/p>
iBATIS中最古老的是光|方式。在目开始的时候,XML被认为最好的配置方式。事实上QXML现在q是比较好的配置ҎQ因为它是进行复杂的多行SQL配置的最x式。因此,XML的配|方式将予以保留。但是它不再是默认的配置方式Q而且也不见得是大多数应用的首选?/p>
iBATIS 3.0用多U配|方式。这是说iBATIS可以用多U方式进行配|,而且q些方式可以协同工作。按照实用性排序,有以下四U方法:
我们应该在何处获?#8220;Mapper”的实例呢Q我们仍焉要一个核心类来完成iBATIS的配|和控制。这个核心类的名U尚在争Z中,但是我们不妨先叫它MapperFactory?/p>
通常情况下,MapperFactory负责构徏事务和映类的实例。而MapperFactory本n由某个配置cL构徏?/p>
对于q种方式是不是会使事情变得简?..或许会吧Q至于事务,Clinton是这栯的:“会话的概念应该和事务的进行合q。在iBATIS中,会话和事务很多时候是一致甚x一L。但是它们因Z些h为的架构斚w的原因而被分开了。会话或许能够完成不Q务,但是其中?0%q不适合用会话来解决。同LQ批处理操作也从事务中分d来,因ؓ事务在提供批处理功能是往往会导致o人生厌的try/finally的多重嵌套。因此在我们发现真实的需求之前应该尽量避免这些?#8221;?/p>
iBATIS或者其他第三方库及容器都可以进行事务处理。目前,事务的处理是由SqlMapClient实例中的ThreadLocal实例来处理的。因U处理方法,我们配到了不问题。不是出于技术的原因而是因ؓ代码更加清晰Q我们可以用以下的ҎQ?/p>
批处理操作可以简单地通过启动支持批处理操作的事务来进行:
与现在的事务的APIcMQ我们对事务的隔ȝ别以及其他选项提供支持?/p>
如果W三方的库提供了事务处理的支持,那么受托理的连接对象可以作为参C入:
MQ这LAPI十分的简z,而且易于与诸如Springq样的第三方框架集成。MapperFactory可以被注入到需要事务管理、批处理和隔ȝ别的Spring的DAO对象中。ؓ了进一步进行必要的分离Q我们可以将事务理功能从MapperFactory中分d来,甚至于允许开发者定义自q事务理接口Q同时将事务理的功能绑定到cMQ这h供了更加松耦合的架构)?/p>
随着Java 5的推q,我们有机会来改善用户体验。其中最重要的是借助Java 5可以消除令h生惑的类型{换,可以消除SQL映射Z字符的调用方式。D例来_现在在调用SQL映射的时候是q样的:
问题是很明显的。第一Q上面的两个例子中被映射的语句的名称都是Z字符串的Q而这很容易导致错误。这U方式也不会得到IDE工具、编译器的支持和理?/p>
W二个问题是存在参数和返回值类型安全问题。在W一个例子中Q谁能保证参数的cd一定是IntegerQ而谁又能保证您得到的q回g定是Employeecd呢?q里Q编译器也不会给ZQ何偿错误报告和提C。而只有运行时异常会被抛出?/p>
最后,在集合的例子中问题也是相同的。在q行前,您可能会获得Dogs的集合,而不是Employees?/p>
MQ这U方式虽然比JDBC强,但是也让人倍感隑֏Q还是存在改善的I间?/p>
在Java 5中我们可以充分用范型来规范集合cd。这P我们不需要进行特D的配置可以ؓ集合cd建立一致的API。我们不需要在XML文g中声明类型,不需要通过字符名称来调用被映射的语句,相反Q我们可以充分利用表辑֥且类型安全的接口cd。没有什么新东西需要学习,只是普通的接口可以了?/p>
q就够了QiBATIS来帮我们实现q个接口?/p>
现在我们可以以一U更加简z和安全的方式来调用被映的语句了?/p>
在上面的调用中没有类型{换、没有字W串Q而且参数和返回值的cd是、安全的。额外的代码是针对接口使用XML或者Java的标识进行配|。最多我们只需要配|SQL语句、需要进行重载的参数或者返回值类型?/p>
接口描述了所需要的一切?/p>
而其中最有趣的就是我们可以基于方法名U这LU定来生成SQL映射。以后关于配|的章节中将详细讨论q些l节?/p>
接口l定的方法得诸如Springq样的框架将映射cL入其他类变得ҎQ同时也不需要将事务理的过多细节公开?/p>
iBATIS 开发团队在6?2日发布了其文档的多国语言版本Q包括中、日、韩及其他几个语a的翻译版本。可以到以下链接下蝲q些文档Q?/p>
http://ibatis.apache.org/javadownloads.cgi
http://www.zeroc.com/newsletter/issue24.pdf
目录如下Q?/p>
关于q一版本的更C息请参见q里?/p>
在网上寻了半天,已经有兄弟就Wikcet做了很多工作Q请?a >q里看看?/p>
因ؓ链接地址q是以前保存的,今天试了试好像L出错Q所以烦性就把下载得到的《Wikcet 开发指南》上载来和大家分享共勉吧Q不q,相关权利都属于此文档的译者,大家都只作ؓ学习之用好了,下面是分h件的下蝲地址Q?/p>
Z上面的这些动机,下面是Wicket的目标:
注:本文由Jonathan Locke~写,相关权利由原作者n有?/strong>
JSPh最q侵入性,它允许将Java代码直接嵌入Web面中。但是,上面列示的框Ӟ除了TapestryQ都不同E度地针对HTML代码引入了特D的语法?/p>
因ؓҎ语法改变了单U而简单的HTML标记的实质,而Web设计者对于这一Ҏ十分的熟悉,所以特D语法ƈ不是十分得h心。而且预览、编辑和理解q种包含Ҏ语法的HTML也是十分困难的事情?/p>
Wicketq没引入M新的HTML语法。相反,它通过Wicket命名I间QnamespaceQ的标准兼容方式扩展了HTMLQ这完全兼容XHTML标准。这意味q您可以使用Macromedia Dreamweaver、Microsoft Frontpage、Word、Adobe Go Live以及其他现有的HTML~辑器来~辑您的Web面Qƈ且可以和Wicket的组件协同工作。ؓ了实现这个目标,Wicket始终在Wicket命名I间内用单个id属性(“wicket:id”Q来标识那些需要框架进行特D处理的标签。如果您q不喜欢有Wicket命名I间修饰的标{֒属性展C给您的最l用P通过单的讄可以完全消除它们,从而得到普通的与标准兼容的HTML代码?/p>
HTML中没有特D的语法意味着设计者可以直接模拟页面,而您可以在开发的q程中直接用这些页面。向HTML面中添加Javalg和讄lg的名U属性一L单。然后,您可以直接将q些面交给Web设计人员Q他们可以充满信心地对其q行修改?/p>
与其他的应用框架相比QWicket在各斚w的分M提供更多的支持。Web设计者在对应用程序代码不甚了解的情况下就可以~辑HTMLQ当Ӟ他们不能U除lg名称标签Q而且不能L改变lg嵌套的层ơ,其他的事情都是可以的Q。另一斚wQ编E者只需要关注与HTML混在一LJavalgQ而不需要了解页面的最l陈现是什么样子。通过q种职能清楚的工作方式,每个人都可以工作得更为顺畅?/p>
现存的框架易用性不?/strong>
目前存在的大部分框架工具在对象模型方面做得不够。在一些框架中Q对象模型是通过特定的XML来定义的。这些语法o人生厌,而且q需要特定的工具来编辑这些配|信息。由于这些框架ƈ不是单一的JavacdQ您׃能用包含编辑器、调试器和编译器的IDE工具来编辑它们?/p>
Wicket是化Jؓ的代表。在学习Wicket的过E中不需要了解Q何配|文件。Wicket是lgl构良好的普通的cd。在Wicket中,您的Web应用E序与普通的Swing应用E序cMQ而不是JSP应用E序。如果您熟悉JavaQ特别是如果您熟悉SwingQ,那么您就已经对Wicket有不的了解了?/p>
现存的框架可复用性不?/strong>
Tapestry和JSF虽然有可以重用的lg模型Q但是您发CWicket相比qƈ不是特别Ҏ做到的事情。Wicket从设计之初就十分地注重组件的复用。在Wicket中,从现有的lg扩展~制诸如SignInPanel或者AddressForm的复合组件是十分单的事情。相Ҏ_针对览器的新特性编制新的组件也是十分容易的事情。Wicket的组件可以用JAR格式q行打包Q直接通过库引用的方式可以实现重用——不需要Q何配|文Ӟ
Web~程应该更关注编E乐!
q就是我~写Wicket的个人方面的目标。现存的框架在实现开发的直接性、快h和易性方面真正地吸引我。我希望Wicket在Web应用E序开发的性和乐趣斚w能够q出重要的一步?/p>
注:本文由Jonathan Locke~写,相关权利由原作者n有?/strong>
目前存在的大多数Web框架对于服务端的状态管理都仅仅提供了较q支持?/p>
q就意味着在Web应用E序中存在着很多Ҏ的代码来处理和维护繁复的状态管理机制。虽然Wicketq不允许Ҏ务端的状态完全不考虑Q但是它在状态管理的便性和透明化方面做了很多的工作?/p>
在Wicket中,所有服务端的状态都被纳入了自动的管理。您始终不需要直接用HttpSession对象或者类似的装对象d储状态信息。相反,状态信息已l都与组件关联v来,而在lg后端的数据模型都是传l的Java对象QPOJOQ。Wicket在每个用户会话期内维护着面的映表QMapQ。这个页面映表Q以及每个一面内的组件层ơ)的目的在于得框枉藏了lg以及数据模型讉K的细节。您只需要处理简单而熟悉的Java对象Q而Wicket则处理诸如URL、会话期标识以及GET/POSTh的Q务?/p>
您接着也会发现q种l构良好的服务端状态得解决o人恐惧的“后退按钮问题”变得十分的容易。实际上Q针寚w面内lg数据模型的结构性变化带来的数据q期QWicket提供了通用而且健壮的解x案,q个Ҏ可以有效地对览器缓存页面进行甄别和q期?/p>
最后,Wicket在设计的时候就考虑与诸如JDO和Hibernate的普通Java对象QPOJOQ序列化框架协同工作。这一点得构建数据驱动的Web应用E序昑־非常单?/p>
对于很多应用E序来说Q必d额外服务端状态导致服务器负蝲增加和其带来的好处之间进行权衡,服务端状态管理可以降低开发成本、减维护成本、加快对市场的响应时间以及生产高质量的Y件。这里提出的基本观点是:软g是十分昂c复杂的Q而来自于E-machines和Dell的服务器则相对便宜?/p>
在效率和生性方面,Wicket对JSP的优性则犹如Java语言对C语言一栗您使用Wicket可以实现的功能用JSP也都可以实现。甚至于在内存和CPU消耗方面效率也非常的高。但是用JSP开发应用程序则需要耗费您更多的旉。最后,因ؓ在JSP中进行状态管理时使用了特别的方式Q您可能发现不少的安全问题,也能看到到处y出来的错误。上面提及的大部分框架在q方面仅仅提供了有限的辅助?/p>
注:本文由Jonathan Locke~写,相关权利由原作者承担?/strong>
如果您正在寻求用Java开发Web应用E序Q目前,您有很多的选择。实际上Q存在如此众多的Web应用E序框架昑־有点搞笑。来自于互联|一个博客站点的问题Q您能说出多Java Web应用框架的名字?他们展现的结果如下:
框架Q到处都是框Ӟ参看后面附带的表根{?/p>
Z么要“重新发明轮子”Q?/strong>
从这个角度看Q您对于“另一个Web应用E序框架有多?#8221;q个问题L耿耿于怀Q确实,Z们要“重新发明轮子”呢?对这个古老的谚语的答复是Q因一ơ可以轮子更圆Q?/p>
但是对于高质量的期待q不是构建Wicket框架的唯一动因。甚x很多的观点,认ؓ没有其他的Web工具集填补这一I白Q而Wicket做到了。实际上QWicket与上面提及的众多框架不太一栗?/p>
与Wicket最相近的或许是Tapestry和EchoQ但是这U相似性也很有限。和Tapestry一PWicket使用特定的HTML属性来标识lgQComponentsQ声明,q可以方便用一般的HTML~辑器进行文件编辑。和Echo一PWicket拥有一的lg模型。但是基于Wicket的应用程序和那些ZTapestry和Echo的应用程序不一Pq是因ؓ从Wicket框架中两斚w都可以受益。您获得了一的lg模型和对HTML没有q扰所带来的益处。在很多情况下,q种复合的好处可以带来非帔R要的开发优ѝ?/p>
理解了构建Wicket的动机有助于您理解ؓ什么Wicket会表现的不一栗?/p>
Echo | Cocoon |
Millstone |
OXF |
Struts | SOFIA |
Tapestry |
WebWork |
RIFE |
Spring MVC |
Canyamo | Maverick |
JPublish |
JATO |
Folium |
Jucas |
Verge |
Niggle |
Bishop |
Barracuda |
Action Framework |
Shocks |
TeaServlet |
wingS |
Expresso |
Bento |
jStatemachine |
jZonic |
OpenEmcee |
Turbine |
Scope |
Warfare |
JMAA |
Jaffa |
Jacquard |
Macaw |
Smile |
MyFaces |
Chiba |
JBanana |
Jeenius |
JWarp |
Genie |
Melati |
Dovetail |
Cameleon |
JFormular |
Xoplon |
Japple |
Helma |
Dinamica |
WebOnSwing |
Nacho |
Cassandra |
Baritus |
注:本文由Jonathan Locke~写,相关权利由原作者承担?/strong>
Wicket中的面及其他组仉是支持封装、承和事g触发的Java对象?
易于开?/strong>
因ؓWicket合成了Java和HTMLQ在使用Wicket开发应用的q程中,您可以最大限度地发挥您所掌握的Java知识Q而且可以最大限度地发挥您最喜欢的HTML~辑器在开发过E中的作用?
x点的分离
Wicketq没有将标签Q比如HTML的相x{)与Java代码混合Q而且也没有在标签文g中增MQ何特D的语法。HTML和Java 的领域是不互相干扰的Q它们只是通过Wicket Id来关联,Wikcet Id在HTML中表Cؓ标签的属性,在Java代码中则表现为组件的属性。因为Wicket中的HTML文g是纯_的HTML文gQWicket中的Java代码是纯_的Java代码Q编E者和设计者可以最大程度地独立完成工作Q而不需要依赖于M特定的工兗?
安全
Wicket在默认设|的条g下是安全的。URL不对外公布Q何敏感信息,而且所有组件的路径都是相对于会话周期的Q脱M会话周期q些路径变得无效。如果需要在会话周期间共享信息,则必d一些特D的工作才能辑ֈ。在下一个版本的 Wicket中,有计划将URL加密功能d到框架中M此来支持W合要求更高的安全特性?
透明的且具备伸羃性的集群支持
所有基于Wicket的应用不需要额外的讄可以自动支持集。一旦系l的瓉l评估被发现Q那么Wicket启动页面状态的复制。Wicket的下一个版本将对具备零状态~性的客户端模型提供支持?
昑ּ?#8220;后退按钮”问题支持
Wicket支持可配|的面版本理。当用户提交一个表单,而后使用览器的后退按钮来回C前访问过的页面时QWicket 可以页面对象的状态恢复过来,q且页面以原来的面貌呈现出来。这意味着您只需要花一点功夫就可以构徏出支?#8220; 后退按钮”的应用?
可复用的lg
在Wicket中,构徏可复用的lg十分的简单。您不仅可以使用Java中的关键字extends来从现有的组件承而构建新的组Ӟ而且可以使用Panellg来组l一批组件来构徏可复用的lg单元。简单且灉|的、支持本地化的表单校验在Wikcet中编写和使用校验器也是十分的单。而且校验错误消息的定义和本地化也是十分简单的工作?
cd安全的会话周?/strong>
Wicket消除了手动管理HttpSession属性的需求。页面和lg对象被显式地存储在会话周期中Q您的应用也可以构徏属性类型安全的会话周期的子cR存储在会话周期中的所有对象可以自动地发布到集中?
可自定义的工厂类
Wicket非常h扩展性。许多操作可以通过工厂cL者工厂方法来实现自定义?
可分ȝ模型
Wicket中的模型对象在集系l中的内存和|络占用可以说是轻量U的。当一个模型正在被使用Ӟ它将被装载,主要通过从存储单元来获得数据q激zL型。当q个模型对象已经不再被用时Q时信息可以被重置Q这样就可以消减对象占用的内存数量?
Ҏlg
Wicket的边框组件可以得页面的装饰W合可重用的规则。这对一般的Dl构和布局昑־十分的有用?
对HTML所有的基本Ҏ提供支?/strong>
Wicket支持囑փ标签、链接、表单以及其他一切您在Web应用开发中可以用到的特性?
对属性的可编E操作?/strong>
Wicketlg可以使用~程的方式来修改MHTML标签的属性?
自动的{?/strong>
一旦表单校验完成,模型可以使用Wicket的{换器来完成更新。大部分的{换器都是pȝ自带的,而编写新的{换器也是很简单的事情?
动态的囑փ
Wikcet使得囑փ的用、共享和生成十分的简单。动态图像可以简单地通过实现l制QpaintQ方法来建立?
可分늚ListView
Wicket中的ListView十分的强大。您可以Q何组件嵌入到ListViewlg的行中,甚至ListViewq行循环嵌套也可以?PageableListView支持大型数据列表的分导航?
树Şlg
具备D和结炚w择的树形组件?
本地?/strong>
HTML面、图形和字符串都可以实现本地化?
CZ
Wicket有展C其各项功能的数量巨大的例子?