数据库编辑器应用开发全解析
立即解锁
发布时间: 2025-08-18 01:15:15 阅读量: 2 订阅数: 8 

GWT实战:构建高效Web应用
### 数据库编辑器应用开发全解析
#### 1. 应用架构概述
数据库编辑器应用契合传统的 Web 应用架构。它包含客户端的 GWT 应用、服务端的 PHP 脚本、Ruby on Rails 应用、Java servlet 以及数据库实现。客户端与服务端之间通过 Action/REST/RPC 接口进行 XML/JSON/GWT - RPC 数据交互。
#### 2. 模型设计
应用的模型在传统 Web 应用和数据库编辑器之间共享,因为它们需要在共享数据库上操作相同的数据。模型中的实体有两个:
- **User**:代表使用 Web 应用的用户。
- **Story**:代表用户提交的故事。
实体关系如下:
- **Posted by**:每个故事由一个用户发布。
- **Digs**:每个故事可以有多个用户进行点赞(投票)。
以下是相关 Java 类的实现:
**Story 类**
```java
public class Story extends BaseObject {
private String title;
private String url;
private String description;
private String user_id;
/**
* @gwt.typeArgs <com.gwtapps.databaseeditor.client.model.User>
*/
private List digs;
public String getDescription() { return description; }
public void setDescription(String description) {
this.description = description;
}
public List getDigs() { return digs; }
public void setDigs(List digs) { this.digs = digs; }
public String getTitle() { return title; }
public void setTitle(String title) { this.title = title; }
public String getUrl() { return url; }
public void setUrl(String url) { this.url = url; }
public String getUser_id() { return user_id; }
public void setUser_id(String user_id) { this.user_id = user_id; }
}
```
**BaseObject 类**
```java
public class BaseObject implements Serializable {
protected String id;
public String getId() { return id; }
public void setId(String id) { this.id = id; }
}
```
**User 类**
```java
public class User extends BaseObject {
private String name;
private String email;
private String password;
public String getEmail() { return email; }
public void setEmail(String email) { this.email = email; }
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public String getPassword() { return password; }
public void setPassword(String password) { this.password = password; }
}
```
数据库使用的 SQL 架构如下:
```sql
DROP TABLE IF EXISTS 'stories';
CREATE TABLE 'stories' (
'id' int(11) NOT NULL auto_increment,
'title' varchar(255) default NULL,
'url' varchar(255) default NULL,
'description' varchar(255) default NULL,
'user_id' int(11) default NULL,
PRIMARY KEY ('id')
);
DROP TABLE IF EXISTS 'user_dug';
CREATE TABLE 'user_dug' (
'user_id' int(11) default NULL,
'story_id' int(11) default NULL
);
DROP TABLE IF EXISTS 'users';
CREATE TABLE 'users' (
'id' int(11) NOT NULL auto_increment,
'name' varchar(255) default NULL,
'email' varchar(255) default NULL,
'password' varchar(255) default NULL,
PRIMARY KEY (`id`)
);
```
表格展示实体和表的对应关系:
| 实体类 | 表名 | 关系说明 |
| ---- | ---- | ---- |
| User | users | 存储用户信息,id 为自增主键 |
| Story | stories | 存储故事信息,user_id 为外键关联用户 |
| - | user_dug | 连接表,实现用户和故事的多对多点赞关系 |
mermaid 流程图展示实体关系:
```mermaid
erDiagram
User ||--o{ Story : "Posted by"
User ||--o{ user_dug : "点赞"
Story ||--o{ user_dug : "被点赞"
```
#### 3. 异步数据访问对象的使用
为了将实体对象与获取实体的代码分离,我们创建数据访问对象(DAOs)。这样做有两个好处:一是可以在其他地方重用实体而不耦合数据访问代码;二是可以轻松切换数据访问方法。
`ObjectDAO` 接口有六个方法,用于对服务器数据执行管理任务:
1. **getById( String id, ObjectListener handler )**:根据对象的 ID 向服务器请求对象,结果通过 `ObjectListener` 接口返回。
2. **getAll( CollectionListener handler )**:向服务器请求该类型的所有对象,结果返回给 `CollectionListener` 处理程序。
3. **getAllFrom( BaseObject object, String member, Collection Listener handler )**:向服务器请求对象指定字段上的所有对象。
4. **save( BaseObject object )**:将对象发送到服务器,如果对象尚未保存,则创建新对象;否则,更新现有对象。
5. **delete( BaseObject object )**:从服务器删除指定对象。
6. **addTo( BaseObject object, String string, BaseObject objectToAdd)**:将一个对象添加到另一个对象的指定成员中。
`ObjectFactory` 接口用于获取 DAO 实例,并设置监听器:
```java
public interface ObjectFactory {
ObjectDAO getUserDAO();
ObjectDAO getStoryDAO();
void setListener( ObjectFactoryListener listener );
}
```
`ObjectFactoryListener` 接口用于接收事件,辅助视图实现:
```java
public interface ObjectFactoryListener {
void onRefresh();
void onError(String error);
void onLoadingStart();
void onLoadingFinish();
}
```
#### 4. 双面板编辑器界面构建
应用的界面采用双面板设计,左面板通常以分层视图列出类别或文件夹,右面板显示所选项目的详细视图。
**使用 Tree 和 SplitPanel 小部件**
`DatabaseEditorView` 类构建了双面板视图:
```java
public class DatabaseEditor implements EntryPoint{
public void onModuleLoad(){
//create view
DatabaseEditorView view = new DatabaseEditorView();
RootPanel.get("databaseEditorView").add( view );
}
}
public class DatabaseEditorView extends Composite
implements TreeListener, ObjectFactoryListener{
//widgets
private HorizontalSplitPanel mainPanel = new HorizontalSplitPanel();
private Tree treeList = new Tree();
private LoadingPanel loading = new LoadingPanel(new Label("loading..."));
//tree items
private UsersTreeItem userItems = new UsersTreeItem(this);
private StoriesTreeItem storyItems = new StoriesTreeItem(this);
//object factory
private ObjectFactory objectFactory;
public DatabaseEditorView(){
initWidget( mainPanel );
setStyleName("databaseEditorView");
RoundedPanel rounded = new RoundedPanel( "#f0f4f8" );
rounded.setWidget(treeList);
rounded.setWidth("100%");
mainPanel.add( rounded );
mainPanel.setSplitPosition("250px");
treeList.addItem( storyItems );
treeList.addItem( userItems );
treeList.addTreeListener(this);
RootPanel.get().add( loading);
}
}
```
**扩展和动态加载树项**
应用使用 `BaseTreeItem` 和 `DynamicTreeItem` 两个抽象基类来提供树项之间共享的功能。
`BaseTreeItem` 类:
```java
public class BaseTreeItem extends TreeItem {
private final DatabaseEditorView view;
public BaseTreeItem(String html, DatabaseEditorView view) {
super(html);
this.view = view;
}
public Data
```
0
0
复制全文
