设为首页 收藏本站
查看: 742|回复: 0

[经验分享] 用 Apache Derby 构建脱机 Ajax

[复制链接]

尚未签到

发表于 2017-1-7 06:21:21 | 显示全部楼层 |阅读模式
  人们非常喜爱 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 查询的方法。例如,查询联系人的方法是静态方法,因此可以执行类似 Contact.getAllContacts() 的操作。保存和删除操作是实例方法,因此对个别联系人调用这些方法。此处没有显示查询,因为查询是标准的 SQL。该类还有常用的 getter 和 setter,但是为了简短起见并未显示。该类将用 Derby 构造基本的客户端存储。首先,我们将使用它作为 Applet UI 的一部分,但是稍后该 Applet 将把它用于 JavaScript。注意,对于每个方法,我们将调用实用程序类 DbManager 以获得连接。

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 访问的其他数据库一样。我们将在类的静态初始化器中把 EmbeddedDriver 用于驱动程序类。另外对于 getConnection 方法,我们将添加额外的参数 create=true 来告诉 Derby 在数据库尚不存在时创建数据库。注意,不需要像使用 JDBC 那样用到用户名或密码 — 这是使用嵌入式数据库的优点之一。您看到了所有的数据访问代码。它看起来非常类似于在任何一个应用程序中都可以看到的数据库代码;而数据库刚好是嵌入式 Derby 数据库。您可以设想为应用程序创建其他模型,这样可以存储专用于应用程序的数据,但是位于客户端。让我们查看一个利用清单 2 中所示的数据访问代码的简单应用程序。
  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。
  
下载完整代码

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-324791-1-1.html 上篇帖子: Apache中 RewriteRule 规则参数介绍 下篇帖子: 用Apache AXIS 开发 Web Services
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表