Как перенаправить на страницу входа после истечения сеанса в вызове GWT RPC - PullRequest
13 голосов
/ 07 сентября 2010

Я использую GWT и RPC в своем приложении. после истечения сеанса, когда я выполняю вызов RPC, из-за моего фильтра входа в систему запрос перенаправляет на login.jsp, но моя проблема в том, что клиент не показывает мне login.jsp, а поднял onFailure RPC.

Это значит, что я должен обработать все события onFailure моего rpc для перенаправления на страницу входа в систему? !!!!

Спасибо

Ответы [ 7 ]

21 голосов
/ 09 сентября 2010

Я согласен с pathed , что вы должны сделать перенаправление в ваших AsyncCallback s. Однако вам не нужно явно использовать ваши собственные MyAsyncCallback обратные вызовы вместо стандартного GWT AsyncCallback. Это важно, например, когда у вас уже есть много кода, который использует стандартные обратные вызовы.

Когда вы вызываете GWT.create(MyService.class), GWT создает прокси для вашего MyServiceAsync интерфейса службы. Этот прокси-сервер отвечает за связь с сервером и , вызывая ваши обратные вызовы при получении данных с сервера. Прокси генерируются с использованием механизма генерации кода GWT , и по умолчанию GWT использует класс ServiceInterfaceProxyGenerator для генерации этих прокси.

Вы можете расширить этот генератор по умолчанию (ServiceInterfaceProxyGenerator класс) , чтобы автоматически использовать ваши пользовательские 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)
5 голосов
/ 07 сентября 2010

Да, вы должны обрабатывать тайм-аут сеанса в onFailure (по моему мнению).Но есть простые способы сделать это.

  1. Реализация собственного асинхронного обратного вызова.

    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);
    

    }

  2. Использованиенекоторая библиотека, такая как gwt-dispatcher, где все вызовы rpc проходят через один и тот же serviceasync и дают вам одно место для обработки onFailures.

2 голосов
/ 14 мая 2013

Почему у вас нет таймера GWT (http://google -web-toolkit.googlecode.com / svn / javadoc / 2.4 / com / google / gwt / user / client / Timer.html ) вместо этого выполняется проверка, активен ли сеанс / истек ли он, а затем либо предлагает пользователю продлить сеанс, либо перейти на страницу выхода из системы. Почему вы делаете это только на вызовах RPC?

2 голосов
/ 09 ноября 2012

Я немного исправил версию 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

1 голос
/ 15 января 2013

Клиент: Все обратные вызовы расширяют абстрактный обратный вызов, где вы реализуете 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);
  }
}
0 голосов
/ 05 декабря 2018

Вы получите 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{...
    }
    }

0 голосов
/ 18 апреля 2011

Я использовал следующее с 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);
    }

}
...