Comment exécuter une classe à partir de Jar qui n'est pas la classe principale dans son fichier Manifeste
J'ai un POT avec 4 classes, chacune a la méthode principale. Je veux pouvoir exécuter chacun de ceux-ci selon les besoins. J'essaie de l'exécuter à partir de la ligne de commande sur Linux box.
E.g. The name of my JAR is MyJar.jar
Il a une structure de répertoire pour les classes principales comme suit:
com/mycomp/myproj/dir1/MainClass1.class
com/mycomp/myproj/dir2/MainClass2.class
com/mycomp/myproj/dir3/MainClass3.class
com/mycomp/myproj/dir4/MainClass4.class
Je sais que je peux spécifier une classe comme main dans mon fichier Manifeste. Mais existe-t-il un moyen de spécifier un argument sur la ligne de commande pour exécuter la classe que je souhaite exécuter?
J'ai essayé ceci:
jar cfe MyJar.jar com.mycomp.myproj.dir2.MainClass2 com/mycomp/myproj/dir2/MainClass2.class /home/myhome/datasource.properties /home/myhome/input.txt
Et J'ai eu cette erreur:
com/mycomp/myproj/dir2/MainClass2.class : no such file or directory
(Dans la commande ci-dessus, '/home/myhome/datasource.propriétés' et '/home/myhome/entrée.txt " sont les arguments de ligne de commande).
6 answers
Vous pouvez créer votre jar sans Classe principale dans son fichier Manifeste. Puis:
java -cp MyJar.jar com.mycomp.myproj.dir2.MainClass2 /home/myhome/datasource.properties /home/myhome/input.txt
, Vous pouvez exécuter tout classe qui a un public final static main
méthode à partir d'un fichier JAR, , même si le fichier jar est un Main-Class
définie.
Exécuter la classe principale:
java -jar MyJar.jar // will execute the Main-Class
Exécute une autre classe avec une méthode public static void main
:
java -cp MyJar.jar com.mycomp.myproj.AnotherClassWithMainMethod
Remarque: la première utilise -jar
, le second utilise -cp
.
En plus d'appeler java -jar myjar.jar com.mycompany.Myclass
, vous pouvez également faire de la classe principale de votre manifeste une classe de répartiteur.
Exemple:
public class Dispatcher{
private static final Map<String, Class<?>> ENTRY_POINTS =
new HashMap<String, Class<?>>();
static{
ENTRY_POINTS.put("foo", Foo.class);
ENTRY_POINTS.put("bar", Bar.class);
ENTRY_POINTS.put("baz", Baz.class);
}
public static void main(final String[] args) throws Exception{
if(args.length < 1){
// throw exception, not enough args
}
final Class<?> entryPoint = ENTRY_POINTS.get(args[0]);
if(entryPoint==null){
// throw exception, entry point doesn't exist
}
final String[] argsCopy =
args.length > 1
? Arrays.copyOfRange(args, 1, args.length)
: new String[0];
entryPoint.getMethod("main", String[].class).invoke(null,
(Object) argsCopy);
}
}
Tout d'abord jar
crée un pot et ne l'exécute pas. Essayez plutôt java -jar
.
Deuxièmement, pourquoi passez-vous la classe deux fois, en tant que FQCN (com.mycomp.myproj.dir2.MainClass2
) et en tant que file (com/mycomp/myproj/dir2/MainClass2.class
)?
Modifier:
Il semble que java -jar
nécessite une classe principale à spécifier. Vous pouvez essayer java -cp your.jar com.mycomp.myproj.dir2.MainClass2 ...
à la place. -cp
définit le jar sur le chemin de classe et permet à java d'y rechercher la classe principale.
Une autre option similaire à laquelle je pense que Nick a brièvement fait allusion dans les commentaires est de créer plusieurs pots wrapper. Je ne l'ai pas essayé, mais je pense qu'ils pourraient être complètement vides à l'exception du fichier manifeste, qui devrait spécifier la classe principale à charger ainsi que l'inclusion du MyJar.jar au chemin de classe.
MyJar1.jar \ META-INF \ MANIFEST.MF
Manifest-Version: 1.0
Main-Class: com.mycomp.myproj.dir1.MainClass1
Class-Path: MyJar.jar
MyJar2.jar \ META-INF \ MANIFEST.MF
Manifest-Version: 1.0
Main-Class: com.mycomp.myproj.dir2.MainClass2
Class-Path: MyJar.jar
Etc.
Ensuite, exécutez-le simplement avec java -jar MyJar2.jar
Ajouter ci-dessous plugin dans votre pom.fichier XML et spécifiez la classe principale avec un nom complet dans element.
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>1.2.5.RELEASE</version>
<configuration>
<mainClass>**main Class name with full qualified name**</mainClass>
</configuration>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>