2016-08-23 3 views
0

Gibt es eine Möglichkeit, während der Serialisierung des Objekts full match/Wiederholung des Weges zu umgehen? Zum Beispiel:Serialisierung Objekte in Java

auf dem Client -

com.example.myProjectOne.model.MyClass

auf der Serverseite -

com.example.notMyProject.entity .MyClass

Ich bekomme -

java.lang.ClassNotFoundException: com.example.myProjectOne.model.MyClass

mit der vollständigen Übereinstimmung des Namen aller Arbeitspakete

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

zeigen Sie Ihren Code auf. – DimaSan

+0

Haben Sie eine Kontrolle darüber, wie * es * serialisiert ist? – Bohemian

+0

Vergessen Sie nicht, die Anmerkungen @Entity usw. zu verwenden. –

Antwort

0

Wenn Sie Bei der Java-Serialisierung müssen die Klassen mit beiden Enden übereinstimmen.

Schließen Sie Ihre Klasse in den Klassenpfad der Serverseite ein.

Wenn Sie das nicht können, können Sie es durch die effektive Schaffung eines Alias ​​Ihrer Klassenname für die andere Klasse funktioniert:

package com.example.myProjectOne.model; 

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

Es gibt ein paar Einschränkungen natürlich, zum Beispiel würde die funktionieren nur, wenn die beiden Klassen die gleichen nicht-flüchtigen Instanzfeldnamen und -typen verwenden.

0

Ja, Sie können. Sie müssen den Standard ObjectInputStream erweitern und überschreiben Sie die resolveClass Methode (vielleicht andere, nicht sicher).

So zum Beispiel:

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

@WilkinOh vielen Dank, jetzt versuchen Sie, wenn es Ihnen nichts ausmacht, ich könnte Ihnen ein paar Fragen stellen, wenn ich nicht etwas bekomme) – andy

+0

Sicher, fühle dich frei, aber sei dir bewusst, dass dieser Ansatz viel Hacking erfordern kann :) –