10

我正在为我的客户端应用程序使用 GWT。但是,我不确定如何处理会话管理。GWT 应用程序驻留在一个页面上,所有服务器调用都通过 AJAX 完成。如果服务器上的会话过期。假设用户没有关闭浏览器,并使用 RPC 向服务器发送一些请求,我的服务器如何通知应用程序会话已过期并且客户端部分应该再次显示登录屏幕?我的示例代码:

ContactDataServiceAsync contactDataService = GWT
                .create(ContactDataService.class);
        ((ServiceDefTarget) contactDataService).setServiceEntryPoint(GWT
                .getModuleBaseURL()
                + "contactDatas");

        contactDataService.getContact(2,
                new AsyncCallback<ContactData>() {
                    public void onFailure(Throwable caught) {
                                      //code to show error if problem in connection or redirect  to login page

                    }

                    public void onSuccess(ContactData result) {
                        displayContact(result);
                    }
                });

如果会话过期,它只需要显示登录屏幕,否则它想使用 Window.alert() 显示一些错误。

如何做到这一点以及服务器端和客户端所需的所有代码是什么?

4

3 回答 3

6

如果用户已注销,您可以让服务器向客户端抛出 AuthenticationException。
这将在回调 onFailure 方法中捕获,然后可以将用户重定向到登录页面。

编辑:
AuthenticationException 当然不是标准异常,我只是举个例子。最好坚持标准例外。

要尝试捕获特定异常,可以使用 instanceof 运算符

    public void onFailure(Throwable e) {
                  if(e instanceof AuthenticationException) {
                        redirecttoLogin();
                  }
                  else {
                    showError(),
               }
            }
于 2009-05-29T09:04:57.693 回答
1

这并不直接适用于那些使用 RPC 的人,但对于那些不使用 RPC 的人,你应该从服务器发送一个 HTTP 401。然后您可以在 RequestBuilder 回调中检查该状态代码。

于 2009-06-11T04:33:15.047 回答
0

客户端:所有回调都扩展了一个抽象回调,您可以在其中实现 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 已过期,则向客户端写入一条特定的错误消息。此错误消息在您的 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);
  }
}
于 2013-01-15T13:19:53.757 回答