2016-08-23 6 views
0

オブジェクトの完全一致/反復のシリアル化中に回避する方法はありますか?たとえば、次のようにクライアント上Javaのシリアル化オブジェクト

-

com.example.myProjectOne.model.MyClass

サーバー側 -

com.example.notMyProject.entity 。マイクラス

私は -

にjava.lang.ClassNotFoundException:すべてのワークパッケージの名前の完全な偶然の一致と com.example.myProjectOne.model.MyClass

public class Server implements Runnable { 

private SettingsConnection settingsConnection; 
private OnReceiveObject onReceiveObject; 
private Serializer serializer; 

/** 
* @param remoteServerAddress - address remote server 
* @param inputPort - the port on which the is server 
* @param outputPort - the port which used for send 
* @param password - the password which should to be same on the client side and the server side 
* @param handler - defines the name of the method, which should to be called, after received the data on server side 
*/ 
public Server(String remoteServerAddress, int inputPort, int outputPort, String password, OnReceiveObject handler) { 
    settingsConnection = new SettingsConnection(); 
    settingsConnection.setAddressRemoteServer(remoteServerAddress); 
    settingsConnection.setInputPort(inputPort); 
    settingsConnection.setOutputPort(outputPort); 
    this.onReceiveObject = handler; 
    serializer = new Serializer(); 
    new Thread(this).start(); 
} 

public void sendData(Serializable object, String callBackFunction) { 

    Container container = new Container(); 

    try { 
     container.setData(serializer.serialize(object), container.getInitVector())); 
     container.setHandler(callBackFunction); 
     InetAddress ipAddress = InetAddress.getByName(settingsConnection.getAddressRemoteServer()); 

     try (Socket socketConnectionToSever = new Socket(ipAddress, settingsConnection.getOutputPort())) { 
      OutputStream outputStream = socketConnectionToSever.getOutputStream(); 
      if (outputStream != null) { 
       outputStream.write(serializer.serialize(container)); 
       outputStream.flush(); 
      } 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 
    } catch (IOException e) { 
     e.printStackTrace(); 
    } 
} 

@Override 
public void run() { 

    final ExecutorService asyncTakesCode = Executors.newCachedThreadPool(); 

    Runnable threadTaskServer = new Runnable() { 
     @Override 
     public void run() { 
      try { 
       ServerSocket serverSocket = new ServerSocket(settingsConnection.getInputPort()); 
       while (true) { 
        Socket connectionSocketClient = serverSocket.accept(); 
        asyncTakesCode.submit(new ThreadTaskClient(connectionSocketClient)); 
       } 
      } catch (IOException e) { 
       System.err.println("Unable to process client request"); 
       e.printStackTrace(); 
      } 
     } 
    }; 

    Thread threadServer = new Thread(threadTaskServer); 
    threadServer.start(); 
} 

private class ThreadTaskClient implements Runnable { 
    private final Socket connectionSocketClient; 

    private ThreadTaskClient(Socket connectionSocketClient) { 
     this.connectionSocketClient = connectionSocketClient; 
    } 

    @Override 
    public void run() { 

     InputStream inputStream = null; 
     try { 
      inputStream = connectionSocketClient.getInputStream(); 
     } catch (IOException e1) { 
      e1.printStackTrace(); 
     } 

     try { 
      Object o = serializer.deserialize(IOUtils.readFully(inputStream, -1, false)); 
      if (o instanceof Container) { 
       Container container = (Container) o; 
       Serializable remoteObject = (Serializable) serializer.deserialize(container.getData())); 
       String callBackFunction = container.getHandler(); 
       onReceiveObject.processRemoteObject(remoteObject, callBackFunction); 
      } 
     } catch (IOException | ClassNotFoundException e) { 
      e.printStackTrace(); 
     } finally { 
      try { 
       connectionSocketClient.close(); 
      } catch (IOException e) { 
       e.printStackTrace(); 
      } 
     } 
    } 
+0

はあなたのコードを示しています。 – DimaSan

+0

*どのように*シリアル化されているかを制御できますか? – Bohemian

+0

注釈@Entityなどを使用することを忘れないでください。 –

答えて

0

あなたがしている場合javaのシリアライゼーションを使用すると、クラスは両端で一致する必要があります。

クラスをサーバー側のクラスパスに含めます。

あなたはそれが効果的に他のクラスのクラス名のエイリアスを作成することで動作させることができ、それを行うことができない場合は、次の

package com.example.myProjectOne.model; 

public class MyClass extends com.example.notMyProject.entity.MyClass { 
} 

例えば、もちろんいくつかの注意事項、考えがあります。 2つのクラスが同じ非一時インスタンスのフィールド名と型を共有する場合にのみ機能します。

0

はい、できます。 ObjectInputStreamのデフォルト値を拡張し、resolveClassメソッドをオーバーライドする必要があります(おそらく他のもの、わかりません)。

したがって、たとえば:

ObjectInputStream ois = new ObjectInputStream(lis) { 
     protected Class<?> resolveClass(ObjectStreamClass osc) throws IOException, ClassNotFoundException { 
      if (osc.getName().contains("some.package.element")) { 
       try { 
        Field nameField = osc.getClass().getField("name"); 
        nameField.setAccessible(true); 
        nameField.set(osc, osc.getName().replace("some.package.element", "another.package.element")); 
        nameField.setAccessible(false); // hack because "name" is private 
       } catch (NoSuchFieldException | IllegalAccessException e) { 
        // ... 
       } 
      } 
      return super.resolveClass(osc); 
     } 
    } 
+0

@Wilkinよろしくお願いします。私が何かを手に入れなければ、何か質問してもらえますか? – andy

+0

確かに、この方法では多くのハッキングが必要になるかもしれません。 :) –

関連する問題