web-dev-qa-db-fra.com

Traiter avec des arguments de ligne de commande et du printemps

Quand j'écris une application de ligne de commande de printemps qui analyse des arguments de ligne de commande, comment puis-je les transmettre au printemps? Serais-je vouloir avoir mon principal () structuré de sorte qu'il analyse d'abord la ligne de commande argument puis introduit le printemps? Malgré tout, comment cela passerait-il l'objet qui détient les arguments analysés au printemps?

38
lowellk

Deux possibilités que je peux penser.

1) Définir une référence statique. (Une variable statique, bien que typiquement fronçée, elle est correcte dans ce cas, car il ne peut y avoir que 1 invocation de ligne de commande).

public class MyApp {
  public static String[] ARGS; 
  public static void main(String[] args) {
    ARGS = args;
      // create context
  }
}

Vous pouvez ensuite référencer les arguments de ligne de commande au printemps via:

<util:constant static-field="MyApp.ARGS"/>

Alternativement (si vous êtes complètement opposé aux variables statiques), vous pouvez:

2) Ajoutez de manière programmable les arguments au contexte de l'application:

 public class MyApp2 {
   public static void main(String[] args) {
     DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();

        // Define a bean and register it
     BeanDefinition beanDefinition = BeanDefinitionBuilder.
       rootBeanDefinition(Arrays.class, "asList")
       .addConstructorArgValue(args).getBeanDefinition();
     beanFactory.registerBeanDefinition("args", beanDefinition);
     GenericApplicationContext cmdArgCxt = new GenericApplicationContext(beanFactory);
     // Must call refresh to initialize context 
     cmdArgCxt.refresh();

     // Create application context, passing command line context as parent
     ApplicationContext mainContext = new ClassPathXmlApplicationContext(CONFIG_LOCATIONS, cmdArgCxt);

     // See if it's in the context
     System.out.println("Args: " + mainContext.getBean("args"));
   }

   private static String[] CONFIG_LOCATIONS = new String[] {
     "applicationContext.xml"
   };

 }

L'analyse des arguments de ligne de commande est laissée comme un exercice au lecteur.

39
flicken

Jetez un coup d'œil à ma bibliothèque Spring-CLI - à http://github.com/sazzer/spring-cli - comme une façon de le faire. Il vous donne une classe principale qui charge automatiquement les contextes de printemps et permet d'utiliser les commons-CLI pour analyse automatiquement les arguments de ligne de commande et les injecter dans vos haricots.

6
Graham

Vous pouvez également transmettre un tableau d'objet en tant que deuxième paramètre sur getBean qui sera utilisé comme arguments sur le constructeur ou l'usine.

public static void main(String[] args) {
   Mybean m = (Mybean)context.getBean("mybean", new Object[] {args});
}
5
BeWarned

À partir du printemps 3.1, aucun code personnalisé suggéré dans d'autres réponses. Vérification CommandlinePropertySource , il offre un moyen naturel d'injecter des arguments de cl dans votre contexte.

Et si vous êtes un développeur de démarrage de printemps chanceux, vous pouvez simplifier votre code un pas en avant le fait que - SpringApplication vous donne ce qui suit:

Par classement par défaut effectuera les étapes suivantes à bootstrap Votre application:

...

Enregistrez un CommandlinePropertSource pour exposer les arguments de ligne de commande en tant que propriétés de printemps

Et si vous êtes intéressé par la commande de résolution de propriété de démarrage de printemps, veuillez consulter cette page .

4
Sergey Pauk

Considérez la classe suivante:

public class ExternalBeanReferneceFactoryBean 
    extends AbstractFactoryBean
    implements BeanNameAware {

    private static Map<String, Object> instances = new HashMap<String, Object>();
    private String beanName;

    /**
     * @param instance the instance to set
     */
    public static void setInstance(String beanName, Object instance) {
        instances.put(beanName, instance);
    }

    @Override
    protected Object createInstance() 
        throws Exception {
        return instances.get(beanName);
    }

    @Override
    public Class<?> getObjectType() {
        return instances.get(beanName).getClass();
    }

    @Override
    public void setBeanName(String name) {
        this.beanName = name;
    }

}

de même que:

/**
 * Starts the job server.
 * @param args command line arguments
 */
public static void main(String[] args) {

    // parse the command line
    CommandLineParser parser = new GnuParser();
    CommandLine cmdLine = null;
    try {
        cmdLine = parser.parse(OPTIONS, args);
    } catch(ParseException pe) {
        System.err.println("Error parsing command line: "+pe.getMessage());
        new HelpFormatter().printHelp("command", OPTIONS);
        return;
    }

    // create root beanFactory
    DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();

    // register bean definition for the command line
    ExternalBeanReferneceFactoryBean.setInstance("commandLine", cmdLine);
    beanFactory.registerBeanDefinition("commandLine", BeanDefinitionBuilder
        .rootBeanDefinition(ExternalBeanReferneceFactoryBean.class)
        .getBeanDefinition());

    // create application context
    GenericApplicationContext rootAppContext = new GenericApplicationContext(beanFactory);
    rootAppContext.refresh();

    // create the application context
    ApplicationContext appContext = new ClassPathXmlApplicationContext(new String[] { 
        "/commandlineapp/applicationContext.xml"
    }, rootAppContext);

    System.out.println(appContext.getBean("commandLine"));

}
3
Brian Dilley

Voici un exemple pour démarrer le ressort de la sangle pour une méthode principale, saisissez simplement les paramètres transcédés comme Normal, puis rendez la fonction que vous appelez votre haricot (dans le cas du déploiement.execute ()) les emmenez comme des chaînes ou via n'importe quel format que vous vous sentez approprié .

public static void main(String[] args) throws IOException, ConfigurationException {
    Deployer deployer = bootstrapSpring();

    deployer.execute();
}

private static Deployer bootstrapSpring()
{
    FileSystemXmlApplicationContext appContext = new FileSystemXmlApplicationContext("spring/deployerContext.xml");

    Deployer deployer = (Deployer)appContext.getBean("deployer");
    return deployer;
}
1
Bradley Beddoes

Je ne sais pas ce que vous essayez d'atteindre exactement, vous pouvez peut-être ajouter des détails sur ce que la commande et les arguments ressemblent à ce que vous attendez de votre candidature.

Je pense que ce n'est pas ce dont vous avez besoin, mais cela pourrait aider les autres lecteurs: Printemps prend en charge la réception des propriétés de la ligne de commande à double trait d'un trait d'un trait (par exemple, Java -jar app.jar --my.property="Property Value" consulter cette documentation pour plus d'informations: https://docs.spring.io/spring-boot/docs/current/reeference/html/boot-features-external-config.html#boot-features-external-config-command-line-Args =

0
Gerardo Roza