35

GWTのシリアライザーのjava.io.Serializableサポートは制限されていますが、セキュリティ上の理由から、サポートするタイプのホワイトリストがあります。私が見つけたドキュメント、たとえばこのFAQエントリには、シリアル化するタイプはすべて「シリアル化ポリシーのホワイトリストに含める必要がある」と記載されており、リストはコンパイル時に生成されますが、コンパイラがどのように決定するかについては説明されていません。ホワイトリストに載っているもの。

java.lang.String生成されたリストには、やなどの標準ライブラリの一部であるいくつかのタイプが含まれていjava.util.HashMapます。をシリアル化しようとするとエラーが発生します。これはインターフェイスjava.sql.Dateを実装していますが、ホワイトリストに含まれていません。Serializableこのタイプをリストに追加するにはどうすればよいですか?

4

9 に答える 9

30

Dummy回避策があります。シリアル化に含めたいすべての型のメンバー フィールドを持つ新しいクラスを定義します。次に、メソッドを RPC インターフェースに追加します。

Dummy dummy(Dummy d);

実装はこれだけです:

Dummy dummy(Dummy d) { return d; }

非同期インターフェイスには次のようになります。

void dummy(Dummy d, AsyncCallback< Dummy> callback);

GWT コンパイラーはこれを検出し、Dummyクラスがそれらの型を参照するため、それらをホワイト リストに含めます。

Dummyクラスの例:

public class Dummy implements IsSerializable {
    private java.sql.Date d;
}
于 2009-06-14T12:36:44.673 に答える
11

サービス インターフェイスに含める特定の型とそれらが参照する型は、java.io.Serializable を実装している限り、自動的にホワイトリストに登録されます。例:

public String getStringForDates(ArrayList<java.util.Date> dates);

ArrayList と Date の両方がホワイトリストに含まれることになります。

特定の型の代わりに java.lang.Object を使用しようとすると、より複雑になります。

public Object getObjectForString(String str);

コンパイラは何をホワイトリストに載せるべきかわからないためです。その場合、オブジェクトがサービス インターフェイスのどこにも参照されていない場合は、IsSerializable インターフェイスで明示的にマークする必要があります。そうしないと、RPC メカニズムを介してオブジェクトを渡すことができません。

于 2008-09-28T00:50:16.177 に答える
8

ホワイトリストは GWT コンパイラーによって生成され、IsSerializable マーカー インターフェイスによって指定されたすべてのエントリが含まれます。

リストにタイプを追加するには、クラスが IsSerializable インターフェイスを実装していることを確認する必要があります。

さらに、シリアライゼーションが正しく機能するためには、クラスにデフォルトの引数なしコンストラクターが必要です (コンストラクターは、必要に応じてプライベートにすることができます)。また、クラスが内部の場合は、静的としてマークする必要があります。

于 2008-09-26T11:53:22.310 に答える
2

プログラムでホワイトリストにアクセスする最も簡単な方法は、次のようなクラスを作成することです。

public class SerializableWhitelist implements IsSerializable {
    String[] dummy1;
    SomeOtherThingsIWishToSerialize dummy2;
}

次に、それを.clientパッケージに含め、RPC サービスから参照します (したがって、コンパイラによって分析されます)。

パラメータ化されていないマップの転送を有効にするより良い方法を見つけることができませんでした。これは、より一般的なサービスを作成するために時々必要になることがあります...

于 2009-08-04T22:14:56.597 に答える
1

望ましい結果を確実にするために、すべて削除しますwar/<app>/gwt/*.gwt.rpc

于 2009-10-07T19:36:48.627 に答える
1

ホワイトリストは gwt コンパイラによって生成され、IsSerializable マーカー インターフェイスによって指定されたすべてのエントリが含まれています。

リストにタイプを追加するには、クラスが IsSerializable インターフェイスを実装していることを確認する必要があります。

-- アンドレイ

これはおそらく最も簡単な解決策です。これに関して覚えておくべき唯一のことは、シリアライズするすべてのクラスには、「パブリックで引数なし」のコンストラクターと、(要件に応じて) メンバー フィールドのセッター メソッドが必要であるということです。

于 2010-04-10T17:53:53.130 に答える
0

同じ質問があり、以前の回答に満足できない人へ...

このメッセージで説明されているように変更した Spring を使用しているため、GWTController で GWT を使用しています。メッセージには GrailsRemoteServiceServlet の変更方法が説明されていますが、GWTController は同じ方法で RPC.decodeRequest() と RPC.encodeResponseForSuccess() を呼び出します。

これは、私が使用している GWTController の最終バージョンです。

/**
 * Used to instantiate GWT server in Spring context.
 *
 * Original version from <a href="http://docs.google.com/Doc?docid=dw2zgx2_25492p5qxfq&hl=en">this tutorial</a>.
 * 
 * ...fixed to work as explained <a href="http://blog.js-development.com/2009/09/gwt-meets-spring.html">in this tutorial</a>.
 * 
 * ...and then fixed to use StandardSerializationPolicy as explained in
 * <a href="http://markmail.org/message/k5j2vni6yzcokjsw">this message</a> to allow
 * using Serializable instead of IsSerializable in model.
 */
public class GWTController extends RemoteServiceServlet implements Controller, ServletContextAware {

 // Instance fields

 private RemoteService remoteService;

 private Class<? extends RemoteService> remoteServiceClass;

 private ServletContext servletContext;

 // Public methods

 /**
  * Call GWT's RemoteService doPost() method and return null.
  * 
  * @param request
  *            The current HTTP request
  * @param response
  *            The current HTTP response
  * @return A ModelAndView to render, or null if handled directly
  * @throws Exception
  *             In case of errors
  */
 public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
  doPost(request, response);
  return null; // response handled by GWT RPC over XmlHttpRequest
 }

 /**
  * Process the RPC request encoded into the payload string and return a string that encodes either the method return
  * or an exception thrown by it.
  * 
  * @param payload
  *            The RPC payload
  */
 public String processCall(String payload) throws SerializationException {
  try {
   RPCRequest rpcRequest = RPC.decodeRequest(payload, this.remoteServiceClass, this);

   // delegate work to the spring injected service
   return RPC.invokeAndEncodeResponse(this.remoteService, rpcRequest.getMethod(), rpcRequest.getParameters(), rpcRequest.getSerializationPolicy());
  } catch (IncompatibleRemoteServiceException e) {
   return RPC.encodeResponseForFailure(null, e);
  }
 }

 /**
  * Setter for Spring injection of the GWT RemoteService object.
  * 
  * @param RemoteService
  *            The GWT RemoteService implementation that will be delegated to by the {@code GWTController}.
  */
 public void setRemoteService(RemoteService remoteService) {
  this.remoteService = remoteService;
  this.remoteServiceClass = this.remoteService.getClass();
 }

 @Override
 public ServletContext getServletContext() {
  return servletContext;
 }

 public void setServletContext(ServletContext servletContext) {
  this.servletContext = servletContext;
 }
}
于 2009-10-26T20:34:55.023 に答える
0

私はこの問題を抱えていましたが、Serializable オブジェクトのコード行まで問題を追跡することになりました。

Logger.getLogger(this.getClass().getCanonicalName()).log(Level.INFO, "Foo");

例外がキャッチされる前に、他の苦情はありませんでした:

 @Override
  protected void serialize(Object instance, String typeSignature)
      throws SerializationException {
    assert (instance != null);

    Class<?> clazz = getClassForSerialization(instance);

    try {
      serializationPolicy.validateSerialize(clazz);
    } catch (SerializationException e) {
      throw new SerializationException(e.getMessage() + ": instance = " + instance);
    }
    serializeImpl(instance, clazz);
  }

そして、スタック トレースのビジネス エンドは次のとおりです。

com.google.gwt.user.client.rpc.SerializationException: Type 'net.your.class' was not included in the set of types which can be serialized by this SerializationPolicy or its Class object could not be loaded. For security purposes, this type will not be serialized.: instance = net.your.class@9c7edce
    at com.google.gwt.user.server.rpc.impl.ServerSerializationStreamWriter.serialize(ServerSerializationStreamWriter.java:619)
于 2013-02-06T16:04:33.800 に答える
0

クライアント パッケージに入れたり、ダミーのサービス インターフェイスで使用したりするだけでは、システムが最適化して削除したように見えたため、十分ではないことがわかりました。

サービス インターフェイスで既に使用されている型の 1 つから派生したクラスを作成し、それをクライアント パッケージに貼り付けるのが最も簡単であることがわかりました。他に何も必要ありません。

public class GWTSerializableTypes extends SomeTypeInServiceInterface implements IsSerializable {
    Long l;
    Double d;
    private GWTSerializableTypes() {}
}
于 2011-09-23T16:38:13.657 に答える