GWT RPC 无法正常工作
Posted
技术标签:
【中文标题】GWT RPC 无法正常工作【英文标题】:GWT RPC doesn't work properly 【发布时间】:2012-05-21 11:06:27 【问题描述】:我正在我的 GWT 项目中制作 RPC,它正在运行,但我想使用的数据不知何故消失了。我使用本地主机作为服务器。我在服务器包中有两个类: 防御:
package org.elsys.salvation.server;
import org.elsys.salvation.client.Defence;
import org.elsys.salvation.client.FunctionalityManager;
public class Defences
private ArrayList<Defence> netDefences;
private ArrayList<Defence> hardDefences;
private ArrayList<Defence> softDefences;
public Defences(FunctionalityManager fm)
netDefences = fm.getNetDefences();
hardDefences = fm.getHardDefences();
softDefences = fm.getSoftDefences();
public ArrayList<Defence> getNetDefences()
return netDefences;
public ArrayList<Defence> getHardDefences()
return hardDefences;
public ArrayList<Defence> getSoftDefences()
return softDefences;
和 DefenceServiceImpl.java :
package org.elsys.salvation.server;
import java.util.ArrayList;
import org.elsys.salvation.client.DefenceService;
import org.elsys.salvation.client.FunctionalityManager;
import com.google.gwt.user.server.rpc.RemoteServiceServlet;
public class DefenceServiceImpl extends RemoteServiceServlet implements DefenceService
private Defences defences;
@Override
public void saveDefences(FunctionalityManager fm)
defences = new Defences(fm);
@Override
public void getHardDefences(FunctionalityManager fm)
fm.setHardDefences(defences.getHardDefences());
@Override
public void getNetDefences(FunctionalityManager fm)
fm.setNetDefences(defences.getNetDefences());
@Override
public void getSoftDefences(FunctionalityManager fm)
fm.setSoftDefences(defences.getSoftDefences());
下面是 DefenceService 接口:
package org.elsys.salvation.client;
import com.google.gwt.user.client.rpc.RemoteService;
import com.google.gwt.user.client.rpc.RemoteServiceRelativePath;
@RemoteServiceRelativePath("defences")
public interface DefenceService extends RemoteService
void saveDefences(FunctionalityManager fm);
void getHardDefences(FunctionalityManager fm);
void getNetDefences(FunctionalityManager fm);
void getSoftDefences(FunctionalityManager fm);
和 DefenceServiceAsync:
package org.elsys.salvation.client;
import com.google.gwt.user.client.rpc.AsyncCallback;
public interface DefenceServiceAsync
void saveDefences(FunctionalityManager fm, AsyncCallback<Void> callback);
void getHardDefences(FunctionalityManager fm, AsyncCallback<Void> callback);
void getNetDefences(FunctionalityManager fm, AsyncCallback<Void> callback);
void getSoftDefences(FunctionalityManager fm, AsyncCallback<Void> callback);
这是我调用 saveDefences 方法的代码:
private void addDiploma()
final AsyncCallback<Void> callback = new AsyncCallback<Void>()
public void onFailure(Throwable caught)
@Override
public void onSuccess(Void result)
SC.say("Submited");
;
some code...
Button submitButton = new Button("Submit");
submitButton.addClickHandler(new ClickHandler()
public void onClick(ClickEvent event)
FM.getDiploma(projectNameTextBox, diplomantsNameTextBox,
diplomaLeadersListBox, reviewersListBox,
specialtiesComboBox, typeComboBox);
FM.generateDefences();
defenceSvc.saveDefences(FM,callback);
RootPanel.get("mainDiv").clear();
showDefences();
);
some more code...
这是FM和defenceSvc的定义:
public FunctionalityManager FM = new FunctionalityManager();
private DefenceServiceAsync defenceSvc = GWT.create(DefenceService.class);
这是我想将保存的数据返回客户端的地方:
protected void showDefence()
FunctionalityManager funcM = new FunctionalityManager();
final AsyncCallback<Void> callback = new AsyncCallback<Void>()
public void onFailure(Throwable caught)
@Override
public void onSuccess(Void result)
// TODO Auto-generated method stub
;
defenceSvc.getHardDefences(funcM, callback);
defenceSvc.getNetDefences(funcM, callback);
defenceSvc.getSoftDefences(funcM, callback);
final ListGrid DiplomaGrid = new ListGrid();
DiplomaGrid.setWidth(500);
DiplomaGrid.setHeight(224);
DiplomaGrid.setShowAllRecords(true);
DiplomaGrid.setCanEdit(true);
DiplomaGrid.setEditEvent(ListGridEditEvent.CLICK);
DiplomaGrid.setModalEditing(true);
DiplomaData dd= new DiplomaData(funcM);
ListGridField nameField = new ListGridField("name", "Project Name");
ListGridField diplomantsField = new ListGridField("diplomants", "Diplomants");
ListGridField leaderField = new ListGridField("leader", "Leader");
ListGridField reviewerField = new ListGridField("reviewer", "Reviewer");
ListGridField typeField = new ListGridField("type", "Type");
ListGridField dateField = new ListGridField("date", "Date");
DiplomaGrid.setFields(new ListGridField[] nameField, diplomantsField, leaderField,reviewerField, typeField, dateField);
DiplomaGrid.setData(dd.getRecords());
RootPanel.get("mainDiv").add(DiplomaGrid);
web.xml:
<servlet>
<servlet-name>defenceServiceImpl</servlet-name>
<servlet-class>org.elsys.salvation.server.DefenceServiceImpl</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>defenceServiceImpl</servlet-name>
<url-pattern>/salvation/defences</url-pattern>
</servlet-mapping>
当我在开发模式下运行它时,它正在运行,但是当我调用 showDefence() 方法时,我无法检索服务器数据上的序列化。谁能告诉我问题出在哪里?
【问题讨论】:
根本看不到它是如何工作的,因为Defences
类没有空构造函数(而且它也没有实现 Serializabl 接口或 IsSerializable 接口)
【参考方案1】:
在服务器端,您正在修改 FM,但不要将其发送回客户端:那是行不通的。客户端和服务器之间的对象传递是通过复制(序列化→反序列化),因此在服务器上进行更改只会影响服务器端的副本。您无法更新将其发送到服务器的对象;您正在发送它的副本,然后服务器必须发回应用了更改的另一个副本。
换句话说,对于您的代码,将方法的返回类型从 void
更改为 FM,让服务器返回 FM 传递的参数,然后在客户端,在 onSuccess
方法中,更新您的带有结果的 singleton 对象(在来自setHardDefences
的回调中,将 FM 的 hardDefences
设置为服务器返回的 FM 中的 hardDefences
;对于其他 防御)。
【讨论】:
我做了修改(我想是的):final FunctionalityManager funcM = new FunctionalityManager(); final AsyncCallback<FunctionalityManager> callback = new AsyncCallback<FunctionalityManager>() public void onFailure(Throwable caught) @Override public void onSuccess(FunctionalityManager result) funcM.setHardDefences(result.getHardDefences()); funcM.setNetDefences(result.getNetDefences()); funcM.setSoftDefences(result.getSoftDefences()); ; defenceSvc.getDefences(funcM, callback);
但还是不行。
这里是 DefenceServiceImpl 中的代码:@Override public void saveDefences(FunctionalityManager fm) defences = new Defences(fm); @Override public FunctionalityManager getDefences(FunctionalityManager fm) fm.setHardDefences(defences.getHardDefences()); fm.setNetDefences(defences.getNetDefences()); fm.setSoftDefences(defences.getSoftDefences()); return fm;
您正在并行启动 3 个请求(setHardDefences
、setNetDefences
和 setSoftDefences
),但是使用上面的代码,一个结果将覆盖前一个:您需要为每个方法使用不同的回调:setHardDefences
的那个只会更新其onSuccess
中的hardDefences
等。
还是不行。也许问题出在 saveDefences() 方法上,我没有在服务器端保存任何东西?
从技术上讲,您并没有保存任何东西(一旦您有 2 个并发客户端,您可能会遇到问题),但它应该可以工作。如果您愿意,请尝试将该字段设置为 static
,但最好是调试您的代码(您知道:断点等)【参考方案2】:
我刚刚尝试过类似的事情。我想使用假数据来测试 UI,因为我还没有真实数据。我替换了一个包含静态数据成员的 Singleton 类。一个成员是一个有时被写入的列表。
写入操作无效。
使用 Debug 遍历它,似乎每个到服务器的 RPC 每次都在实例化类。我跟踪了单例的 getInstance 和每个 RPC 的类被实例化。
Singleton 类的单元测试可以正常工作,但这是本地的,而不是服务器上的。
我相信这是有道理的,因为在 Google 服务器上,您可能有多个应用程序实例正在运行。由于每个都有自己的 Singleton,因此无需保留它。
基于此,我建议每次调用 RPC 时都实例化 DefenceServiceImpl,因此它始终是一个新类,即您可以保存数据。
【讨论】:
以上是关于GWT RPC 无法正常工作的主要内容,如果未能解决你的问题,请参考以下文章
GWT rpc 在本地机器没有互联网连接的情况下无法工作,但在互联网上它可以工作