一、 定義服務
GWT過程調用大部分在兩個類進行。在伺服器端,定義一個 RemoteServiceServlet子類 RegisterActionImpl.java(遠端服務實作類)。在這個類中,将操作資料庫并将值傳回給客戶機。在用戶端,定義一個實作 AsyncCallback接口的類 Register.java(用戶端實作類),在這個類中,定義伺服器操作完成時客戶機頁面如何處理資料(或異常)。除了這兩個類之外,必須編寫一些綁定代碼使 GWT-Ext 可以将用戶端類和伺服器端類綁定在一起 , 綁定代碼包含 RegisterAction.java(遠端接口)和 RegisterActionAsync.java(遠端異步接口)兩個不同的接口外加一些用戶端代碼以及一兩個設定。
a. 在 gwtext項目上點選右鍵,選擇 New—Other—Remote Service,建立名為 RegisterAction的遠端服務接口。
b. 把 PostgreSQL資料庫的 JDBC包 postgresql-8.2-505.jdbc3.jar加入到項目中(其他資料庫,加入相應的 JDBC包)。
c. 遠端服務的實作類,在 RegisterActionImpl.java中加入如下代碼:
Java代碼 複制代碼
1.
5. public class RegisterActionImpl extends RemoteServiceServlet implements RegisterAction {
6.
7. private static final long serialVersionUID = 1L;
8.
9. public void saveData(Map formData) {
10. Connection conn=null;
11. try {
12. Class.forName("org.postgresql.Driver");
13. String connString="jdbc:postgresql://127.0.0.1:5432/gwtext";
14. conn=DriverManager.getConnection(connString,"julycn","julycn");
15. StringBuffer sqlQuery=new StringBuffer("insert into person (username,password,email,phone) ");
16. sqlQuery.append("values(?,?,?,?)");
17. PreparedStatement stmt=conn.prepareStatement(sqlQuery.toString());
18. stmt.setString(1, URLDecoder.decode(formData.get("username").toString(),"UTF-8"));
19. stmt.setString(2, URLDecoder.decode(formData.get("password").toString(),"UTF-8"));
20. stmt.setString(3, URLDecoder.decode(formData.get("email").toString(),"UTF-8"));
21. stmt.setString(4, URLDecoder.decode(formData.get("phone").toString(),"UTF-8"));
22. stmt.execute();
23. } catch (Exception e) {
24. e.printStackTrace();
25. }finally{
26. if(conn!=null){
27. try {
28. conn.close();
29. } catch (SQLException e) {
30. e.printStackTrace();
31. }
32. }
33. }
34.
35. }
36. }
public class RegisterActionImpl extends RemoteServiceServlet implements RegisterAction {
private static final long serialVersionUID = 1L;
public void saveData(Map formData) {
Connection conn=null;
try {
Class.forName("org.postgresql.Driver");
String connString="jdbc:postgresql://127.0.0.1:5432/gwtext";
conn=DriverManager.getConnection(connString,"julycn","julycn");
StringBuffer sqlQuery=new StringBuffer("insert into person (username,password,email,phone) ");
sqlQuery.append("values(?,?,?,?)");
PreparedStatement stmt=conn.prepareStatement(sqlQuery.toString());
stmt.setString(1, URLDecoder.decode(formData.get("username").toString(),"UTF-8"));
stmt.setString(2, URLDecoder.decode(formData.get("password").toString(),"UTF-8"));
stmt.setString(3, URLDecoder.decode(formData.get("email").toString(),"UTF-8"));
stmt.setString(4, URLDecoder.decode(formData.get("phone").toString(),"UTF-8"));
stmt.execute();
} catch (Exception e) {
e.printStackTrace();
}finally{
if(conn!=null){
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
}
d. GWT-Ext遠端服務的要求很簡單,它必須擴充 RemoteServiceServlet并實作一個接口。
二、 綁定代碼
a. 要使新程式可用于用戶端應用程式,必須定義兩個接口。
b. 定義一個遠端接口類 RegisterAction.java,代碼如下
Java代碼 複制代碼
1.
5. public interface RegisterAction extends RemoteService {
6.
7. public static final String SERVICE_URI = "/RegisterAction";
8.
9. public static class Util {
10.
11. public static RegisterActionAsync getInstance() {
12.
13. RegisterActionAsync instance = (RegisterActionAsync) GWT
14. .create(RegisterAction.class);
15. ServiceDefTarget target = (ServiceDefTarget) instance;
16. target.setServiceEntryPoint(GWT.getModuleBaseURL() + SERVICE_URI);
17. return instance;
18. }
19. }
20.
21. public void saveData(Map formData);
22. }
public interface RegisterAction extends RemoteService {
public static final String SERVICE_URI = "/RegisterAction";
public static class Util {
public static RegisterActionAsync getInstance() {
RegisterActionAsync instance = (RegisterActionAsync) GWT
.create(RegisterAction.class);
ServiceDefTarget target = (ServiceDefTarget) instance;
target.setServiceEntryPoint(GWT.getModuleBaseURL() + SERVICE_URI);
return instance;
}
}
public void saveData(Map formData);
}
c. 在這裡完成的所有操作是獲得用于實際的具體類中方法的同一個簽名。這裡的主要限制是接口必須擴充 com.google.gwt.user.client.rpc.RemoteService;。此外,參數和傳回值必須屬于 GWT 可以序列化的類型 (見備注 )。
d. 定義遠端異步接口 RegisterActionAsync.java ,代碼如下:
Java代碼 複制代碼
1.
5. public interface RegisterActionAsync {
6.
7. public void saveData(Map formData, AsyncCallback callback);
8. }
public interface RegisterActionAsync {
public void saveData(Map formData, AsyncCallback callback);
}
e. 遠端異步類的服務接口是從上面描述的遠端服務類中派生出來的。兩個類必須位于同一個包中,并且該包必須對 GWT-EXT 客戶機代碼可見。遠端異步類中的類名必須是遠端服務接口的名稱且末尾附加字元串 Async。對于遠端服務接口中的每個方法,遠端異步類必須有一個傳回類型更改為 void 的比對方法和一個 AsyncCallback 類型的附加參數。用戶端代碼将使用 AsyncCallback 作用于伺服器響應上。
f. 注冊伺服器代碼,将下面的一行加入到 Register.gwt.xml中
Java代碼 複制代碼
1. <servlet class="com.gwtext.julycn.server.RegisterActionImpl" path="/RegisterAction" />
<servlet class="com.gwtext.julycn.server.RegisterActionImpl" path="/RegisterAction" />
三、 執行用戶端調用
a. 完成伺服器端操作以後,現在應該讓客戶機執行過程調用了。在這裡基本的想法是慎重地告訴 GWT 系統正在調用的是哪個遠端服務。然後将 AsyncCallback 對象發送出去;最後, GWT 将其送回,您可對結果進行操作。修改模型檔案 Register.java,代碼如下:
Java代碼 複制代碼
1.
5. public class Register implements EntryPoint,AsyncCallback {
6. public void onModuleLoad() {
7. createComponents();
8. }
9.
10. private void createComponents() {
11. final FormPanel frm = new FormPanel();
12. frm.setDraggable(true);
13. frm.setWidth(300);
14. frm.setTitle("使用者注冊");
15. frm.setPaddings(25);
16.
17. TextField txtUsername = new TextField("使用者名", "username");
18. TextField txtPassword = new TextField("密碼", "password");
19. TextField txtEmail = new TextField("郵箱", "email");
20. TextField txtPhone = new TextField("電話", "phone");
21.
22. txtUsername.setRegex("^[a-zA-Z]*$");
23. txtUsername.setRegexText("使用者名必須為字母!");
24. txtUsername.setAllowBlank(false);
25.
26. txtPassword.setPassword(true);
27. txtPassword.setRegex("^[a-zA-Z]*$");
28. txtPassword.setRegexText("密碼必須為字母!");
29. txtPassword.setAllowBlank(false);
30.
31. txtEmail.setVtype(VType.EMAIL);
32. txtEmail.setVtypeText("請輸入合法的郵箱位址!");
33. txtEmail.setAllowBlank(false);
34.
35. txtPhone.setRegex("^\\d*$");
36. txtPhone.setRegexText("電話必須為數字!");
37. txtPhone.setAllowBlank(false);
38.
39. frm.add(txtUsername);
40. frm.add(txtPassword);
41. frm.add(txtEmail);
42. frm.add(txtPhone);
43.
44. Panel buttonPanel = new Panel();
45. buttonPanel.setLayout(new HorizontalLayout(10));
46.
47. final AsyncCallback callback=this;
48.
49. Button btnSave = new Button("儲存");
50. btnSave.addListener(new ButtonListenerAdapter() {
51. public void onClick(Button button, EventObject e) {
52. if (frm.getForm().isValid()) {
53. RegisterActionAsync action=RegisterAction.Util.getInstance();
54. Map formData=getFormDataAsMap(frm.getForm());
55. action.saveData(formData, callback);
56. } else {
57. MessageBox.alert("錯誤","請驗證輸入的資訊是否正确!");
58. }
59. }
60. });
61.
62. Button btnClear = new Button("取消");
63. btnClear.addListener(new ButtonListenerAdapter() {
64. public void onClick(Button button, EventObject e) {
65. MessageBox.alert("取消", "注冊資訊儲存失敗!");
66. }
67. });
68.
69. buttonPanel.add(btnSave);
70. buttonPanel.add(btnClear);
71.
72. frm.add(buttonPanel);
73.
74. RootPanel.get().add(frm);
75. }
76.
77. public Map getFormDataAsMap(Form form){
78.
79. String formValues=form.getValues();
80. Map formData=new HashMap();
81. String[] nameValuePairs=formValues.split("&");
82.
83. for(int i=0;i<nameValuePairs.length;++i){
84. String[] oneItem=nameValuePairs[i].split("=");
85. formData.put(oneItem[0], oneItem[1]);
86. }
87.
88. return formData;
89. }
90.
91. public void onFailure(Throwable caught) {
92. MessageBox.alert("失敗","資料儲存失敗!");
93. }
94.
95. public void onSuccess(Object result) {
96. MessageBox.alert("成功","資料儲存成功!");
97. }
98. }
public class Register implements EntryPoint,AsyncCallback {
public void onModuleLoad() {
createComponents();
}
private void createComponents() {
final FormPanel frm = new FormPanel();
frm.setDraggable(true);
frm.setWidth(300);
frm.setTitle("使用者注冊");
frm.setPaddings(25);
TextField txtUsername = new TextField("使用者名", "username");
TextField txtPassword = new TextField("密碼", "password");
TextField txtEmail = new TextField("郵箱", "email");
TextField txtPhone = new TextField("電話", "phone");
txtUsername.setRegex("^[a-zA-Z]*$");
txtUsername.setRegexText("使用者名必須為字母!");
txtUsername.setAllowBlank(false);
txtPassword.setPassword(true);
txtPassword.setRegex("^[a-zA-Z]*$");
txtPassword.setRegexText("密碼必須為字母!");
txtPassword.setAllowBlank(false);
txtEmail.setVtype(VType.EMAIL);
txtEmail.setVtypeText("請輸入合法的郵箱位址!");
txtEmail.setAllowBlank(false);
txtPhone.setRegex("^\\d*$");
txtPhone.setRegexText("電話必須為數字!");
txtPhone.setAllowBlank(false);
frm.add(txtUsername);
frm.add(txtPassword);
frm.add(txtEmail);
frm.add(txtPhone);
Panel buttonPanel = new Panel();
buttonPanel.setLayout(new HorizontalLayout(10));
final AsyncCallback callback=this;
Button btnSave = new Button("儲存");
btnSave.addListener(new ButtonListenerAdapter() {
public void onClick(Button button, EventObject e) {
if (frm.getForm().isValid()) {
RegisterActionAsync action=RegisterAction.Util.getInstance();
Map formData=getFormDataAsMap(frm.getForm());
action.saveData(formData, callback);
} else {
MessageBox.alert("錯誤","請驗證輸入的資訊是否正确!");
}
}
});
Button btnClear = new Button("取消");
btnClear.addListener(new ButtonListenerAdapter() {
public void onClick(Button button, EventObject e) {
MessageBox.alert("取消", "注冊資訊儲存失敗!");
}
});
buttonPanel.add(btnSave);
buttonPanel.add(btnClear);
frm.add(buttonPanel);
RootPanel.get().add(frm);
}
public Map getFormDataAsMap(Form form){
String formValues=form.getValues();
Map formData=new HashMap();
String[] nameValuePairs=formValues.split("&");
for(int i=0;i<nameValuePairs.length;++i){
String[] oneItem=nameValuePairs[i].split("=");
formData.put(oneItem[0], oneItem[1]);
}
return formData;
}
public void onFailure(Throwable caught) {
MessageBox.alert("失敗","資料儲存失敗!");
}
public void onSuccess(Object result) {
MessageBox.alert("成功","資料儲存成功!");
}
}
b. AsyncCallback 接口定義了兩個方法: onSuccess(Object result) 和 onFailure(Throwable caught)。必須定義一個可以實作這兩個方法的類。當執行遠端調用時,模型類的執行個體并将其傳遞給異步服務方法。最後,伺服器端資源完成,然後調用代碼中兩個方法之一。成功方法的參數是接口和實作中的調用的傳回值。
c. 運作一下,看看效果吧! ^o^
備注:
怎樣的字段才是可序列化字段?首先,該字段可屬于一個實作了 com.google.gwt.user.client.rpc.IsSerializable 的類型,或者具有一個實作了 IsSerializable 的超類。或者,該字段可以是基本類型之一,其中包括 Java 原語,所有原語包裝類, Date 和 String 。序列化類型的數組或集合也是序列化的。但是,如果要将一個 Collection 或 List 序列化, GWT 希望您用一個指定實際類型的 Javadoc 注釋對其評注,以便編譯器可以使其最優化。