2017-01-31 4 views
-1

J'ai un canal nio que mon client doit charger un fichier de classe à partir de l'ordinateur serveur. Ils sont dans la même gamme de propriété intellectuelle. J'ai deux interfaces communes sur le serveur et le client. Et une classe qui implémente l'interface sur la machine serveur. J'utilise le code suivant sur mon ordinateur client, mais ClassNotFoundException apparaîtra lorsque je l'exécuterai.Comment utiliser classloader pour charger le fichier de classe du serveur au client

URL url = new URL("file:///E:/Computing/Master/classes/"); 
URLClassLoader ucl = new URLClassLoader(new URL[]{url}); 
Class clazz = ucl.loadClass("com.counter.controller.Action"); 
ProcessAlgorithm iAction = (ProcessAlgorithm) clazz.newInstance(); 

Quel est le processus complet de chargement de classe dans ce cas?

+0

J'ai une question. Où est ta question? : D – Matt

+0

vous êtes censé poser une question ici. Vous pouvez en effet répondre à votre propre question, mais vous devez d'abord poser une question. –

+0

Le RMI intégré de Java utilise cette distribution de classes pour que cela fonctionne, mais je vous préviens que ce n'est pas une bonne idée. Je suggère de distribuer des données plutôt que du code autant que possible. –

Répondre

1

J'ai trouvé la solution et je voudrais la partager ici. Tout d'abord, ce travail est le chargement de la classe réseau. Il peut être trouvé dans javadoc avec ce nom. En fait, il n'y a pas moyen de charger un fichier de classe à partir d'ordinateurs distants en utilisant le code suivant:

URL url = new URL("file:///E:/Computing/Master/classes/"); 
URLClassLoader ucl = new URLClassLoader(new URL[]{url}); 
Class clazz = ucl.loadClass("com.counter.controller.Action"); 
ProcessAlgorithm iAction = (ProcessAlgorithm) clazz.newInstance(); 

Même lorsque vous changez son URL à « http » alors qu'il n'y a pas de protocole http entre deux ordinateurs distincts. Eh bien, commençons le bon chemin. Supposons que vous ayez deux ordinateurs avec des adresses IP 192.168.10.1 (serveur) et 192.168.10.2 (client). Il existe un fichier de classe que le client ne doit pas copier du disque du serveur sur son disque. Commencez par définir la même interface sur les deux machines JVM (serveur et client). avec le même package comme l'interface suivante:

package org.counter.biz; 

public interface ProcessAlgorithm { 

    int doProcess() ; 

} 

Ainsi, cette interface est commune sur le serveur et le client. En second lieu, votre classe principale doit être définie sur le serveur et implémente l'interface:

package org.counter.biz; 

public class Action implements ProcessAlgorithm { 

    @Override 
    public int doProcess() { 

     /* something to do */ 

    } 
} 

Et enfin le fichier de classe doit être envoyé au client sur la prise ou le canal de prise. Ici, j'utilise Socketchannel sur mon serveur et Socket sur mon client. (En fait, vous devez savoir comment connecter deux ordinateurs distants via la prise en premier.)

code côté serveur d'envoyer octets de fichier de classe au client:

private void sendAlgorithmFile(SocketChannel client, String filePath) throws IOException { 

     ByteBuffer buffer = ByteBuffer.allocate(8192); 
     buffer.clear(); 

     /*file path like E:\\classes\\Action.class*/ 
     Path path = Paths.get(filePath); 
     FileChannel fileChannel = FileChannel.open(path); 
     int bytes = 0; 
     int counter = 0; 


     do { 
      bytes = fileChannel.read(buffer); 
      if (bytes <= 0) 
       break; 
      counter += bytes; 
      buffer.flip(); 
      do { 
       bytes -= client.write(buffer); 
      } while (bytes > 0); 
      buffer.clear(); 
     } while (true); 


     fileChannel.close(); 

    } 

Il y a beaucoup d'envoyer un fichier via prise. C'est mon code et son exactitude a été examinée.

Côté client pour recevoir le fichier et le remplacer par une classe qui n'est pas enregistrée sur le disque du client.

package org.counter.biz; 

import java.io.IOException; 
import java.io.InputStream; 
import java.net.Socket; 

public class MyClassLoader extends ClassLoader { 

    private Socket clientChannel; 
    private int count = 0; 

    public MyClassLoader(Socket channel){ 
     this.clientChannel = channel; 
    } 

    @Override 
    protected Class findClass(String className){ 

     Class myClass = null; 

     InputStream inputStream = null; 

     try { 
      inputStream = clientChannel.getInputStream(); 
     }catch (IOException e){e.printStackTrace();} 


     byte[] bytes = new byte[8192]; 
     byte[] myBytes = null; 

     try { 
      while ((count = inputStream.read(bytes)) > 0){ 
       myBytes = new byte[count]; 
       System.arraycopy(bytes, 0, myBytes, 0, count); 
       myClass = defineClass(className, myBytes, 0, myBytes.length); 
      } 
      inputStream.close(); 
     }catch (IOException io){} 


     return myClass; 

    } 

} 

Puis:

public class Client { 
    public static void main(String[] args) throws Exception{ 
    MyClassLoader myClassLoader = new MyClassLoader(clientSocket); 
    Class clazz = myClassLoader.findClass(null); 
    ProcessAlgorithm iAction = (ProcessAlgorithm) clazz.newInstance(); 
    } 
} 

vous pouvez utiliser la classe comme celui-ci

iAction.doProcess(); 

En cas de question, je suis ici pour répondre. :)