Подтвердить что ты не робот

Как перенаправить на страницу входа после окончания сеанса в вызове GWT RPC

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

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

Спасибо

4b9b3361

Ответ 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{...
    }
    }