Как перенаправить на страницу входа после окончания сеанса в вызове GWT RPC
Я использую GWT и RPC в своем приложении. после окончания сеанса, когда я делаю вызов RPC, из-за моего фильтра входа в запрос запрос перенаправляется на login.jsp, но моя проблема заключается в том, что клиент не показывает мне login.jsp, а RPC onFailure повышается.
Это означает, что я должен обрабатывать все события rpc onFailure для перенаправления на страницу входа?!!!!
Спасибо
Ответы
Ответ 1
Я согласен с pathed, что вы должны перенаправить в свои AsyncCallback
s. Однако вам не нужно явно использовать ваши пользовательские обратные вызовы MyAsyncCallback
вместо стандартного GWT AsyncCallback
. Это важно, например, когда у вас уже есть много кода, который использует стандартные обратные вызовы.
При вызове GWT.create(MyService.class)
GWT создает прокси для вашего сервисного интерфейса MyServiceAsync
. Этот прокси отвечает за связь с сервером и вызывает ваши обратные вызовы, когда он получает данные с сервера. Прокси генерируются с помощью механизма генераторов кода GWT, и по умолчанию GWT использует класс ServiceInterfaceProxyGenerator
для создания этих прокси.
Вы можете расширить этот генератор по умолчанию (ServiceInterfaceProxyGenerator
class) , чтобы автоматически использовать ваши пользовательские MyAsyncCallbacks во всех вызовах обратных вызовов. Мы недавно сделали именно это в проекте. Ниже приведен исходный код, который мы использовали.
Код для MyAsyncCallback
, он идентичен тому, который представлен pathed:
package my.package.client;
import com.google.gwt.user.client.rpc.AsyncCallback;
public class MyAsyncCallback<T> implements AsyncCallback<T> {
private final AsyncCallback<T> asyncCallback;
public MyAsyncCallback(AsyncCallback<T> asyncCallback) {
this.asyncCallback = asyncCallback;
}
@Override
public void onFailure(Throwable caught) {
if (caught instanceof SessionTimeoutException) {
// redirect
return;
}
asyncCallback.onFailure(caught);
}
@Override
public void onSuccess(T result) {
asyncCallback.onSuccess(result);
}
}
Код для генератора кода GWT (MyRpcRemoteProxyGenerator
):
package my.package.server;
import com.google.gwt.core.ext.typeinfo.JClassType;
import com.google.gwt.user.rebind.rpc.ProxyCreator;
import com.google.gwt.user.rebind.rpc.ServiceInterfaceProxyGenerator;
public class MyRpcRemoteProxyGenerator extends ServiceInterfaceProxyGenerator {
@Override
protected ProxyCreator createProxyCreator(JClassType remoteService) {
return new MyProxyCreator(remoteService);
}
}
И вспомогательный класс генератора (MyProxyCreator
):
package my.package.server;
import java.util.Map;
import com.google.gwt.core.ext.typeinfo.JClassType;
import com.google.gwt.core.ext.typeinfo.JMethod;
import com.google.gwt.user.rebind.SourceWriter;
import com.google.gwt.user.rebind.rpc.ProxyCreator;
import com.google.gwt.user.rebind.rpc.SerializableTypeOracle;
public class MyProxyCreator extends ProxyCreator {
private final String methodStrTemplate = "@Override\n"
+ "protected <T> com.google.gwt.http.client.Request doInvoke(ResponseReader responseReader, "
+ "String methodName, int invocationCount, String requestData, "
+ "com.google.gwt.user.client.rpc.AsyncCallback<T> callback) {\n"
+ "${method-body}" + "}\n";
public MyProxyCreator(JClassType serviceIntf) {
super(serviceIntf);
}
@Override
protected void generateProxyMethods(SourceWriter w,
SerializableTypeOracle serializableTypeOracle,
Map<JMethod, JMethod> syncMethToAsyncMethMap) {
// generate standard proxy methods
super.generateProxyMethods(w, serializableTypeOracle,
syncMethToAsyncMethMap);
// generate additional method
overrideDoInvokeMethod(w);
}
private void overrideDoInvokeMethod(SourceWriter w) {
StringBuilder methodBody = new StringBuilder();
methodBody
.append("final com.google.gwt.user.client.rpc.AsyncCallback newAsyncCallback = new my.package.client.MyAsyncCallback(callback);\n");
methodBody
.append("return super.doInvoke(responseReader, methodName, invocationCount, requestData, newAsyncCallback);\n");
String methodStr = methodStrTemplate.replace("${method-body}",
methodBody);
w.print(methodStr);
}
}
Наконец, вам нужно зарегистрировать новый генератор кода, который будет использоваться для создания прокси для асинхронных сервисов. Это можно сделать, добавив это в свой конфигурационный файл GWT (файл gwt.xml):
<generate-with
class="my.package.server.MyRpcRemoteProxyGenerator">
<when-type-assignable class="com.google.gwt.user.client.rpc.RemoteService" />
</generate-with>
В начале это может показаться очень сложным решением:), но у него есть свои сильные стороны:
- Вы все еще можете использовать стандартный GWT
AsyncCallback
s
- Вы можете перенаправить перенаправление, когда время сеанса отключено глобально для вашего приложения.
- Вы можете легко включать и отключать его (добавив или удалив
generate-with
в ваших конфигурационных файлах GWT)
Ответ 2
Да, вы должны обрабатывать тайм-аут сеанса в onFailure (на мой взгляд). Но есть простые способы сделать это.
-
Внедрите свой собственный асинхронный обратный вызов.
public abstract class MyAsyncCallback<T> implements AsyncCallback<T> {
@Override
public void onFailure(Throwable arg0) {
if arg0 is SessionTimeout
redirect to loginpage
else
failure(Throwable ar0)
}
@Override
public void onSuccess(T arg0) {
success(arg0);
}
public abstract void success(T arg0);
public abstract void failure(Throwable arg0);
}
-
Используйте некоторую библиотеку, такую как gwt-dispatcher, где все rpc-вызовы проходят через один и тот же serviceasync и дают вам одно место для обработки onFailures.
Ответ 3
Я немного исправил версию MyProxyCreator @Piotr, добавленную к GWT 2.5
package my.package.server;
import java.util.Map;
import com.google.gwt.core.ext.typeinfo.JClassType;
import com.google.gwt.core.ext.typeinfo.JMethod;
import com.google.gwt.core.ext.typeinfo.TypeOracle;
import com.google.gwt.user.rebind.SourceWriter;
import com.google.gwt.user.rebind.rpc.ProxyCreator;
import com.google.gwt.user.rebind.rpc.SerializableTypeOracle;
public class MyProxyCreator extends ProxyCreator {
private final String methodStrTemplate = "@Override\n"
+ "protected <T> com.google.gwt.http.client.Request doInvoke(ResponseReader responseReader, "
+ "String methodName, RpcStatsContext statsContext, String requestData, "
+ "com.google.gwt.user.client.rpc.AsyncCallback<T> callback) {\n"
+ "${method-body}" + "}\n";
public MyProxyCreator(JClassType serviceIntf) {
super(serviceIntf);
}
@Override
protected void generateProxyMethods(SourceWriter w, SerializableTypeOracle serializableTypeOracle, TypeOracle typeOracle, Map<JMethod, JMethod> syncMethToAsyncMethMap) {
// generate standard proxy methods
super.generateProxyMethods(w, serializableTypeOracle, typeOracle, syncMethToAsyncMethMap);
// generate additional method
overrideDoInvokeMethod(w);
}
private void overrideDoInvokeMethod(SourceWriter w) {
StringBuilder methodBody = new StringBuilder();
methodBody.append("final com.google.gwt.user.client.rpc.AsyncCallback newAsyncCallback = new my.package.client.MyAsyncCallback(callback);\n");
methodBody.append("return super.doInvoke(responseReader, methodName, statsContext, requestData, newAsyncCallback);\n");
String methodStr = methodStrTemplate.replace("${method-body}",methodBody);
w.print(methodStr);
}
}
Он изменил знаки методов для generateProxyMethods и doInvoke.
С наилучшими пожеланиями.
iVieL
Ответ 4
Почему у вас нет таймера GWT (http://google-web-toolkit.googlecode.com/svn/javadoc/2.4/com/google/gwt/user/client/Timer.html), который проверяет, активен ли сеанс/истек, а затем либо предложите пользователю продлить сеанс или перейти на страницу выхода. Почему вы делаете это только по вызовам RPC?
Ответ 5
Клиент:. Все обратные вызовы расширяют абстрактный обратный вызов, когда вы реализуете onFailur()
public abstract class AbstrCallback<T> implements AsyncCallback<T> {
@Override
public void onFailure(Throwable caught) {
//SessionData Expired Redirect
if (caught.getMessage().equals("500 " + YourConfig.ERROR_MESSAGE_NOT_LOGGED_IN)) {
Window.Location.assign(ConfigStatic.LOGIN_PAGE);
}
// else{}: Other Error, if you want you could log it on the client
}
}
Сервер:. Все ваши ServiceImplementations расширяют AbstractServicesImpl, где у вас есть доступ к вашим SessionData. Переопределите onBeforeRequestDeserialized (String serializedRequest) и проверьте там SessionData. Если срок действия SessionData истекает, то пишите сообщение с пространственной ошибкой клиенту. Это сообщение об ошибке получает checkt в вашем AbstrCallback и перенаправляется на страницу входа.
public abstract class AbstractServicesImpl extends RemoteServiceServlet {
protected ServerSessionData sessionData;
@Override
protected void onBeforeRequestDeserialized(String serializedRequest) {
sessionData = getYourSessionDataHere()
if (this.sessionData == null){
// Write error to the client, just copy paste
this.getThreadLocalResponse().reset();
ServletContext servletContext = this.getServletContext();
HttpServletResponse response = this.getThreadLocalResponse();
try {
response.setContentType("text/plain");
response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
try {
response.getOutputStream().write(
ConfigStatic.ERROR_MESSAGE_NOT_LOGGED_IN.getBytes("UTF-8"));
response.flushBuffer();
} catch (IllegalStateException e) {
// Handle the (unexpected) case where getWriter() was previously used
response.getWriter().write(YourConfig.ERROR_MESSAGE_NOT_LOGGED_IN);
response.flushBuffer();
}
} catch (IOException ex) {
servletContext.log(
"respondWithUnexpectedFailure failed while sending the previous failure to the client",
ex);
}
//Throw Exception to stop the execution of the Servlet
throw new NullPointerException();
}
}
}
В дополнение вы также можете переопределить doUnexpectedFailure (Throwable t), чтобы избежать регистрации сброшенного исключения NullPointerException.
@Override
protected void doUnexpectedFailure(Throwable t) {
if (this.sessionData != null) {
super.doUnexpectedFailure(t);
}
}
Ответ 6
Я использовал следующее с GWT 2.2 для обработки нового метода doInvoke:
public class MyProxyCreator extends ProxyCreator {
private final String methodStrTemplate = "@Override\n"
+ "protected <T> com.google.gwt.http.client.Request doInvoke(ResponseReader responseReader, "
+ "String methodName, com.google.gwt.user.client.rpc.impl.RpcStatsContext statsContext, String requestData, "
+ "com.google.gwt.user.client.rpc.AsyncCallback<T> callback) {\n"
+ "${method-body}" + "}\n";
public MyProxyCreator(JClassType serviceIntf) {
super(serviceIntf);
}
@Override
protected void generateProxyMethods(SourceWriter w,
SerializableTypeOracle serializableTypeOracle,
TypeOracle typeOracle,
Map<JMethod, JMethod> syncMethToAsyncMethMap) {
// generate standard proxy methods
super.generateProxyMethods(w, serializableTypeOracle, typeOracle, syncMethToAsyncMethMap);
// generate additional method
overrideDoInvokeMethod(w);
}
private void overrideDoInvokeMethod(SourceWriter w) {
StringBuilder methodBody = new StringBuilder();
methodBody
.append("final com.google.gwt.user.client.rpc.AsyncCallback newAsyncCallback = new com.mydomain.client.MyAsyncCallback(callback);\n");
methodBody
.append("return super.doInvoke(responseReader, methodName, statsContext, requestData, newAsyncCallback);\n");
String methodStr = methodStrTemplate.replace("${method-body}", methodBody);
w.print(methodStr);
}
}
Ответ 7
Вы получите com.google.gwt.user.client.rpc.InvocationException, когда метод службы не вызывается из-за окончания сеанса. Вы можете проверить это в методе onFailure и просто перенаправить пользователя на страницу входа.
public void onFailure(Throwable caught) {
if (caught instanceof InvocationException) {
SC.warn("Your session has expired, Please login again.",
value -> com.google.gwt.user.client.Window.Location.replace("/login.jsp"));
}else{...
}
}