gpt4 book ai didi

java - 序列化策略更改时,GWT 客户端未收到 IncompatibleRemoteServiceException

转载 作者:行者123 更新时间:2023-12-04 05:58:21 27 4
gpt4 key购买 nike

部署新版本的应用程序并更改模型时
类(例如添加/删除字段)。
运行旧版本的客户端获取
com.google.gwt.user.client.rpc.SerializationException 与 RPC
使用旧客户端代码制作,这是预期的行为。
因此,我们希望在客户端看到 IncompatibleRemoteServiceException。
但是我们得到了 StatusCodeException。

StatusCodeException 是 500 错误,我们无法自定义客户端
很容易出现副作用(我们不想假设每个
StatusCodeException 或 500 错误是新版本)。我们能做什么
在这里做错了吗?

注意:在服务器端(日志),我们显然会得到 SerializationExcepion,因为旧客户端的序列化策略对新服务器不再有效。那么为什么不抛出 IncompatibleRemoteServiceException 呢?

谢谢。

最佳答案

这是我面对这个问题的解决方案:

先扩展RemoteServiceServlet (您的所有服务 servlet 都将从这个新类扩展,记住这是服务器代码)。这是那里的相关代码:

@Override
protected SerializationPolicy doGetSerializationPolicy(
HttpServletRequest request, String moduleBaseURL, String strongName) {
SerializationPolicy sp = super.doGetSerializationPolicy(request,
moduleBaseURL, strongName);
if(sp == null) { //no policy found, probably wrong client version
throw new InvalidPolicyException();
}
return sp;
}


@Override
protected void doUnexpectedFailure(Throwable e) {
if(e instanceof InvalidPolicyException) {
sendError(); //send message to reload client (wrong client version)
return; //that's it
}
super.doUnexpectedFailure(e);
}

私有(private)方法 sendError()基本上是来自 GWT 500 错误代码的自定义副本(对于丑陋的 Google 缩进感到抱歉)
private void sendError() {
ServletContext servletContext = getServletContext();
HttpServletResponse response = getThreadLocalResponse();
try {
response.setContentType("text/plain");
response.setStatus(HttpServletResponse.SC_CONFLICT);
try {
response.getOutputStream().write("wrong client version".getBytes("UTF-8"));
} catch (IllegalStateException e) {
// Handle the (unexpected) case where getWriter() was previously used
response.getWriter().write("wrong client version");
}
} catch (IOException ex) {
servletContext.log(
"sendError failed while sending the previous custom failure to the client", ex);
}
}

我用了 HttpServletResponse.SC_CONFLICT (409) 但您可能可以使用巧妙的错误代码。写的信息并不重要。

然后在您的自定义 RpcRequestBuilder (这是客户端代码)
public class CustomRequestBuilder extends RpcRequestBuilder {

private class RequestCallbackWrapper implements RequestCallback {

private RequestCallback callback;

RequestCallbackWrapper(RequestCallback aCallback) {
this.callback = aCallback;
}

@Override
public void onResponseReceived(Request request, Response response) {
if(response.getStatusCode() == 409) { //wrong client version
Navigator.closeEveryPopUp();
Navigator.showUncloseablePopUp("Login again!",
new ClickHandler() {

@Override
public void onClick(ClickEvent event) {
//reload your $#%^ client!!!
Window.Location.reload();
}
});
} else {
//(...)irrelevant security code here(...)
callback.onResponseReceived(request, response);
}

}

@Override
public void onError(Request request, Throwable exception) {
callback.onError(request, exception);
}

}

@Override
protected void doFinish(RequestBuilder rb) {
//(...)more irrelevant security code here(...)
super.doFinish(rb);
rb.setCallback(new RequestCallbackWrapper(rb.getCallback()));
}
}

我们使用多个弹出窗口,这是 Navigator 类的原因之一;当然在那里使用你自己的风格来警告用户。

编辑 : 这里发生了什么?

直到 GWT 1.3.3 IsSerializable是唯一可用于将类标记为 GWT RPC 可序列化的接口(interface)。下一版本接受 Java 标准 Serializable接口(interface)用于相同的目的,但为实现此接口(interface)的对象添加了安全策略的要求。默认情况下,GWT 为每个编译生成一个具有唯一哈希名称的策略。一个旧客户端尝试传输标记为 Serializable 的对象将在服务器端抛出一个序列化策略异常,该异常将在客户端作为通用运行时错误接收。 IsSerializable只要签名保持不变,旧客户端仍然可以使用新服务。这意味着 此问题的另一种解决方案是将通过 GWT RPC 的每个对象标记为 IsSerializable .但是如果出于某种原因您需要您的对象不被引用到 GWT 接口(interface),这对于旧客户端连接来说是一个很好的解决方案。

查看 GWT's guide有关 1.3.3 回退的更多详细信息。

关于java - 序列化策略更改时,GWT 客户端未收到 IncompatibleRemoteServiceException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9232987/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com