2010-09-07 51 views
12

Tôi đang sử dụng GWT và RPC trong ứng dụng của mình. sau khi phiên hết hạn khi tôi thực hiện cuộc gọi RPC, vì bộ lọc đăng nhập của tôi yêu cầu chuyển hướng đến login.jsp, nhưng vấn đề của tôi là doen't của khách hàng chỉ cho tôi login.jsp thay vì onFailure của RPC được nâng lên.Cách chuyển hướng đến trang đăng nhập sau khi phiên hết hạn trong GWT RPC gọi

Điều đó có nghĩa là tôi nên xử lý tất cả các sự kiện onFailure của rpc để chuyển hướng đến trang đăng nhập? !!!!

Cảm ơn

Trả lời

21

Tôi đồng ý với pathed mà bạn nên chuyển hướng trong AsyncCallback s. Tuy nhiên, bạn không cần sử dụng rõ ràng các tùy chỉnh gọi lại MyAsyncCallback thay vì tiêu chuẩn GWT AsyncCallback. Điều này là quan trọng ví dụ khi bạn đã có rất nhiều mã sử dụng callbacks tiêu chuẩn.

Khi bạn gọi GWT.create(MyService.class) GWT tạo proxy cho giao diện dịch vụ MyServiceAsync của bạn. Proxy này có trách nhiệm giao tiếp với máy chủ và gọi lại số gọi lại khi nhận dữ liệu từ máy chủ. Proxy được tạo bằng cách sử dụng GWT code generators mechanism và theo mặc định, GWT sử dụng lớp ServiceInterfaceProxyGenerator để tạo các proxy này.

Bạn có thể mở rộng trình tạo mặc định này (ServiceInterfaceProxyGenerator lớp) để tự động sử dụng MyAsyncCallbacks tùy chỉnh của bạn trong tất cả lời gọi lại. Gần đây chúng tôi đã làm chính xác điều đó trong một dự án. Dưới đây là mã nguồn mà chúng tôi đã sử dụng.

Mã cho MyAsyncCallback, nó giống như một trong những trình bày bởi 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); 
    } 

} 

Mã cho máy phát điện mã 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); 
    } 
} 

Và phát lớp helper (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); 
    } 

} 

Cuối cùng, bạn cần đăng ký trình tạo mã mới để sử dụng cho việc tạo proxy cho các dịch vụ không đồng bộ. Điều này được thực hiện bằng cách thêm vào tệp cấu hình GWT của bạn (gwt.tập tin xml):

<generate-with 
    class="my.package.server.MyRpcRemoteProxyGenerator"> 
    <when-type-assignable class="com.google.gwt.user.client.rpc.RemoteService" /> 
</generate-with> 

Lúc đầu nó có vẻ là một giải pháp rất phức tạp :) nhưng nó có ưu điểm của nó:

  • Bạn vẫn có thể sử dụng tiêu chuẩn GWT AsyncCallback s
  • Bạn có thể thực thi chuyển hướng khi hết phiên trên toàn cầu cho ứng dụng của bạn
  • Bạn có thể dễ dàng điều chỉnh và tắt (bằng cách thêm hoặc xóa generate-with trong tệp cấu hình GWT)
+0

Điều này thật thông minh. Tôi nghĩ rằng nó sẽ dumbfound một nhà phát triển mới trên một dự án, như sẽ không có tài liệu tham khảo khó điều hướng thông qua IDE để khám phá cách MyAsyncCallback được gọi thay vì AsyncCallback. Tuy nhiên tôi thực sự thích rằng nó là một điểm cắt duy nhất cho việc áp dụng các sửa chữa hơn là phải luôn luôn sử dụng gọi lại tùy chỉnh vì sợ rằng một lỗi resurface. –

+0

@Piotr là 'SessionTimeoutException' một lớp ngoại lệ tùy chỉnh mà bạn đã viết? Nếu vậy, bạn có muốn chia sẻ nó không? –

+0

@AnishSana Xin lỗi, đã khá lâu rồi. Tôi không có quyền truy cập vào mã này vào lúc này. – Piotr

5

Có, bạn nên xử lý thời gian chờ của phiên trong onFailure (theo ý kiến ​​của tôi). Nhưng có những cách đơn giản để làm điều đó.

  1. Thực hiện cuộc gọi lại không đồng bộ của riêng bạn.

    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. Sử dụng một số thư viện như gwt-dispatcher nơi mà tất cả rpc-cuộc gọi đi qua serviceasync giống nhau và cung cấp cho u một nơi để xử lý onFailures.

+0

Tôi đang sử dụng mẫu MVP nên tôi thấy tốt hơn là kế thừa từ DefaultDispatchAsync và ghi đè thực thi và kiểm tra thời gian thực hiện cuối cùng, Cảm ơn câu trả lời của bạn. – Nav

0

tôi đã sử dụng sau đây với GWT 2.2 để xử lý các phương pháp doInvoke mới:

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

} 
2

tôi đặt một chút sửa chữa lên phiên bản @Piotr MyProxyCreator của, adpated để 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); 
    } 

} 

Nó đã thay đổi các dấu hiệu của phương thức cho generateProxyMethodsdoInvoke.

Trân trọng.

iVieL

1

Chủ đầu tư: Tất cả Callback mở rộng một Tóm tắt Callback trí bạn triển khai 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 
    } 
} 

Server: Tất cả ServiceImplementations của bạn mở rộng AbstractServicesImpl, nơi bạn có quyền truy cập vào SessionData của bạn. Ghi đè onBeforeRequestDeserialized (String serializedRequest) và kiểm tra SessionData ở đó. Nếu SessionData hết hạn thì hãy viết một thông báo lỗi không gian cho máy khách. Thông báo lỗi này đang được kiểm tra trong AbstrCallback của bạn và chuyển hướng đến Trang Đăng nhập.

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

} 

Ngoài ra bạn cũng có thể ghi đè doUnexpectedFailure (Throwable) để tránh ghi nhật ký NullPointerException.

@Override 
protected void doUnexpectedFailure(Throwable t) { 
    if (this.sessionData != null) { 
    super.doUnexpectedFailure(t); 
    } 
} 
+0

Đó là một cách giải quyết, xa thanh lịch, vì nhiều lý do: sử dụng mã HTTP không đúng cách, tạo ngoại lệ không đúng cách, không sử dụng GWT RPC, v.v.Tuy nhiên, xem xét rằng GWT ẩn bất kỳ khả năng nào để thực hiện một bộ lọc đáp ứng bằng cách sử dụng các thông báo lỗi thông qua RPC, đó là một giải pháp có thể chấp nhận được. Nó đã cứu ngày của tôi! Cảm ơn. –

Các vấn đề liên quan