精华帖 (0) :: 良好帖 (0) :: 新手帖 (9) :: 隐藏帖 (0)
|
|
---|---|
作者 | 正文 |
发表时间:2010-04-10
最后修改:2010-04-10
人们非常喜爱 Ajax 应用程序,以至于他们十分乐于使用 Ajax 应用程序而不想使用等效的桌面程序。但惟一的问题是出现在网络无法访问的时候怎么办。这是必须要用脱机功能的场景。Apache Derby 是支持 Ajax 应用程序实现脱机访问的优秀选择。了解如何使用 Apache Derby 作为本地数据库,该数据库可以实现 Ajax 应用程序的脱机使用。
Apache Derby Apache Derby 是任何一个 Java 应用程序都可以使用的嵌入式数据库。它是非常有用的工具,因此绑定在 Java Platform, Standard Edition (Java SE) V6 中。虽然嵌入式数据库的应用不计其数,但是许多人都不知道用 Derby 可以实现的一些客户端功能。我们将通过构建一个简单的地址本应用程序研究其中一些应用。我们将从利用 Apache Derby 的 Java Applet 开始,最终实现一个使用 Derby 作为缓存的基于 Ajax 的应用程序。
数据访问 对于一篇有关数据库技术的文章,应当首先从数据库代码开始讨论。首先,让我们定义用于存储联系人的简单的表模式,如下所示:
您可以设想更复杂的联系人模式,如添加多个电话号码、地址等。但是,对于我们的应用程序来说,使用目前的这种模式刚刚好。当然,存在一个与 Contact 表相对应的 Java 类。在本例中,我们将遵循 Active Record 模式并用能够执行所有数据库操作的类封装数据库行。其代码如下所示: public class Contact { private Integer id; private String firstName; private String lastName; private String email; public static List<Contact> getContacts(String clause){ if (clause == null) clause = ""; String sql = SELECT_SQL + clause; Connection conn = DbManager.getConnection(); List<Contact> contacts = new ArrayList<Contact>(); try { ResultSet cursor = conn.createStatement().executeQuery(sql); while (cursor.next()){ Contact c = new Contact(); c.setId(cursor.getInt(1)); c.setFirstName(cursor.getString(2)); c.setLastName(cursor.getString(3)); c.setEmail(cursor.getString(4)); contacts.add(c); } } catch (SQLException e) { e.printStackTrace(); } return contacts; } public static List<Contact> getAllContacts(){ return Contact.getContacts(null); } public static Contact getContact(String clause){ List<Contact> results = Contact.getContacts(clause); if (results == null || results.size() != 1){ return null; } else return results.get(0); } public void save(){ if (id == null) insert(); else update(); } public void delete(){ Connection conn = DbManager.getConnection(); String sql = "delete from Contact where id=?"; try{ PreparedStatement ps = conn.prepareStatement(sql); ps.setInt(1, id); ps.executeUpdate(); System.out.println("Deleted contact id="+id); } catch (SQLException e){ e.printStackTrace(); } } private void insert() { Connection conn = DbManager.getConnection(); try { PreparedStatement ps = conn.prepareStatement(INSERT_SQL, PreparedStatement.RETURN_GENERATED_KEYS); ps.setString(1, firstName); ps.setString(2, lastName); ps.setString(3, email); ps.executeUpdate(); ResultSet autoRs = ps.getGeneratedKeys(); if (autoRs.next()){ id = autoRs.getInt(1); } System.out.println("Contact saved new id = " + id); } catch (SQLException e) { e.printStackTrace(); } } private void update(){ Connection conn = DbManager.getConnection(); try{ PreparedStatement ps = conn.prepareStatement(UPDATE_SQL); ps.setString(1, firstName); ps.setString(2, lastName); ps.setString(3, email); ps.setInt(4, id); ps.executeUpdate(); System.out.println("Contact updated with id="+id); } catch (SQLException e){ e.printStackTrace(); } }
该类将完成很多任务,但是所有内容都非常简单。它有与数据库列对应的字段及用于每个字段的常用存取器(getter 和 setter)。它拥有执行所有创建/更新/删除(CReate Update Delete,CRUD)操作及其附带 SQL 查询的方法。例如,查询联系人的方法是静态方法,因此可以执行类似
package org.developerworks.addressbook; import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; public class DbManager { static { try { Class.forName("org.apache.derby.jdbc.EmbeddedDriver"); } catch (ClassNotFoundException e) { e.printStackTrace(); } } public static Connection getConnection(){ try { Connection conn = DriverManager.getConnection("jdbc:derby:contacts;create=true"); return conn; } catch (SQLException e) { e.printStackTrace(); } return null; } } 这是所有特定于 Derby 的代码所在的位置。实际上,并不是特别特定于 Derby。我们使用的是嵌入式数据库,但是我们处理它的方式和通过 JDBC 访问的其他数据库一样。我们将在类的静态初始化器中把
Applet UI 首先使用一个非常简单的 Applet,该 Applet 将使用数据访问代码。 public class AddressBookApplet extends JApplet { private static final long serialVersionUID = 1L; private static final String[] columns = { "First Name", "Last Name", "Email", "Id"}; public AddressBookApplet() { this.setLayout(new GridLayout(1,0)); JPanel panel = buildUi(); this.add(panel); } public Contact addContact(String firstName, String lastName, String email) { Contact c = new Contact(); c.setFirstName(firstName); c.setLastName(lastName); c.setEmail(email); c.save(); return c; } public void deleteContact(Integer id){ Contact c= new Contact(); c.setId(id); c.delete(); } public Object[][] loadContacts() { List<Contact> book = Contact.getAllContacts(); Object[][] contacts = new Object[book.size()][4]; int cnt = 0; for (Contact contact : book){ contacts[cnt++] = contact.toArray(); } return contacts; } private JPanel buildUi() { JPanel panel = new JPanel(); panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS)); final DefaultTableModel dataModel = createDataModel(); final JTable table = createTable(dataModel); //Lots of Swing/UI Code omitted for brevity } private JTable createTable(final DefaultTableModel dataModel) { final JTable table = new JTable(dataModel); table.setPreferredScrollableViewportSize(new Dimension(500, 70)); table.setFillsViewportHeight(true); return table; } private DefaultTableModel createDataModel() { Object[][] contacts = loadContacts(); final DefaultTableModel dataModel = new DefaultTableModel(contacts, columns); return dataModel; } }
这段代码大部分是构建 UI 的典型 Swing 代码。所有 UI 代码都是在位于类底部的私有方法中完成的。buildUi 方法处理 Swing 组件的创建,但是为了简短起见而省略了大部分内容。更有趣的是三个公共方法(除了构造函数之外):addContact、deleteContact 和 loadContacts。这三个方法实质上都是先前开发的数据访问代码的包装器。实际上,我们不需要将 Applet 用于最终应用程序的 UI,但是它提供了测试代码的简单方法。如果使用的是 Eclipse,则只需在 Applet 类上右键单击并选择 Run As > Java Applet。
安全性 我们将为 Applet 中使用的 JAR 设置签名。如果这里继续遵循计划,有一件事好到令人难以置信。Derby 将给我们提供嵌入到客户机中的持久数据库(所有内容都存储在客户机中)。它有几分像 HTTP Cookie,但是众所周知,那些 Cookie 在每个域中不可以超过 4 KB。客户机中的 Derby 数据库的限制是什么?答案是要么很多,要么很少。 默认情况下,Applet 无法访问本地文件系统,因此 Derby 无法在客户机中存储任何数据。那么使用 Derby 是做白日梦么?幸运的是,它不是。关键是您必须给 Applet 设置数字签名。有签名的 Applet 将获得本地文件系统的访问权,这样如果数据来自有签名的 Applet,则 Derby 可以持久存储这些数据。我们只需给 Applet 设置签名。 $ keytool -genkey -alias sigs -keystore sigstore -keypass password -storepass password What is your first and last name? [Unknown]: Michael What is the name of your organizational unit? [Unknown]: developerWorks What is the name of your organization? [Unknown]: IBM What is the name of your City or Locality? [Unknown]: San Jose What is the name of your State or Province? [Unknown]: CA What is the two-letter country code for this unit? [Unknown]: US Is CN=Michael, OU=developerWorks, O=IBM, L=San Jose, ST=CA, C=US correct? [no]: yes $ jarsigner -keystore sigstore -storepass password -keypass password -signedjar addrbook.jar derby.jar sigs Warning: The signer certificate will expire within six months.
正如您所见,我们使用两个 JDK 工具给 Applet(技术上是包含 Applet 的 JAR)设置签名。首先,使用 keytool 创建用于保存生成的加密密钥的密钥库。还可以使用它执行创建 SSL 证书之类的任务。在拥有密钥后,结合使用该密钥与 jarsigner 工具来给 JAR 设置签名。注意,我们包括了 Derby JAR,以及包含自定义代码的 addrbook JAR。最终获得了一个自签名 Applet 的示例。这对于开发来说没问题,但是通常不适用于任何面向用户的代码。在这种情况下,您将需要来自受信任提供商(如 VeriSign)的密钥/证书。关键原因是因为需要在客户机中存储数据,我们需要执行这些附加步骤才能符合 Java 语言的客户端安全模型。牢记这些安全事项并且拥有一颗可以正常工作的 Applet 后,我们现在已经准备好从 JavaScript 使用 Applet。 声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |
发表时间:2010-04-19
图片怎么没了?
|
|
返回顶楼 | |
发表时间:2010-04-19
你没听说过HTML5么
|
|
返回顶楼 | |
发表时间:2010-04-19
就是用derby进行本地数据存储?
我觉得关键技术是,本地数据库和服务器数据的同步,这像个C/S程序。 |
|
返回顶楼 | |
发表时间:2010-09-02
http://www.ibm.com/developerworks/cn/opensource/os-ad-offline-ajax/
|
|
返回顶楼 | |
浏览 2769 次