我正在编写一款使用Spring框架的命令行应用程序,该应用程序需要解析命令行参数。如何将这些参数传递给Spring?我应该如何构造main()函数,以便首先解析命令行参数,然后初始化Spring?即使这样,如何将包含解析参数的对象传递给Spring?
我正在编写一款使用Spring框架的命令行应用程序,该应用程序需要解析命令行参数。如何将这些参数传递给Spring?我应该如何构造main()函数,以便首先解析命令行参数,然后初始化Spring?即使这样,如何将包含解析参数的对象传递给Spring?
我能想到两种可能性。
1)设置一个静态引用(一个静态变量,在这种情况下通常被认为是不好的,但是因为只有一个命令行调用,所以在这种情况下是可以接受的)。
public class MyApp {
public static String[] ARGS;
public static void main(String[] args) {
ARGS = args;
// create context
}
}
然后,您可以通过以下方式在Spring中引用命令行参数:
<util:constant static-field="MyApp.ARGS"/>
如果你完全反对使用静态变量,你可以采取以下方法:
2) 通过编程方式将参数添加到应用程序上下文中:
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"
};
}
将命令行参数解析留给读者作为练习。
请查看我的Spring-CLI库 - 在http://github.com/sazzer/spring-cli - 这是一种实现此操作的方式。它提供了一个主类,自动加载spring上下文,并具有使用Commons-CLI自动解析命令行参数并将其注入到您的bean中的功能。
从Spring 3.1开始,不需要其他答案中建议的任何自定义代码。请查看CommandLinePropertySource,它提供了一种将CL参数注入到上下文中的自然方法。
如果你是一个幸运的Spring Boot开发者,你可以更进一步简化你的代码,利用SpringApplication给你以下内容:
默认情况下,该类将执行以下步骤来引导您的应用程序:
...
注册CommandLinePropertySource以将命令行参数公开为Spring属性
如果您对Spring Boot属性解析顺序感兴趣,请参阅this page。
您还可以将一个对象数组作为第二个参数传递给getBean
方法,它将被用作构造函数或工厂的参数。
public static void main(String[] args) {
Mybean m = (Mybean)context.getBean("mybean", new Object[] {args});
}
考虑以下类:
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;
}
}
随着:
/**
* 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"));
}
这里有一个引导Spring的示例,只需像平常一样获取传递的参数,然后使您在bean上调用的函数(在此案例中为deployer.execute())将它们作为字符串或通过任何您认为合适的格式进行接收。
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;
}
我不确定你想要实现什么,也许你可以添加一些关于命令和参数的详细信息,以及你期望应用程序产生的结果。
我认为这不是你需要的,但它可能会帮助其他读者:Spring支持使用双破折号从命令行接收属性(例如:java -jar app.jar --my.property="Property Value"
)。请查看此文档以获取更多信息:
https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-external-config.html#boot-features-external-config-command-line-args
// command line example : c:\> java.exe com.stackeroverflower.answer.132231.ProjetClientApplication --spring.profiles.active=local response --mysuperdate=2023-09-21T14:21:21.212
package com.stackeroverflower.answer.132231.ProjetClientApplication;
import java.util.Arrays;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.core.env.SimpleCommandLinePropertySource;
@SpringBootApplication
public class ProjetClientApplication {
private static final Logger logger = LoggerFactory.getLogger(ProjetClientApplication.class);
public static void main(String[] args) {
Arrays.stream(args).forEach(logger::info); // display >
// > INFO com.stackeroverflower.answer.132231.ProjetClientApplication - --spring.profiles.active=local
// > INFO com.stackeroverflower.answer.132231.ProjetClientApplication - response
// > INFO com.stackeroverflower.answer.132231.ProjetClientApplication - --respStatsAtDate=2023-09-21T14:21:21.212
// > INFO com.stackeroverflower.answer.132231.ProjetClientApplication - -Xms4096M
// > INFO com.stackeroverflower.answer.132231.ProjetClientApplication - -Xmx4096M
SpringApplication.run(ProjetClientApplication.class, args);
}
@Bean
public CommandLineRunner commandLineRunner(ApplicationContext ctx) {
return args -> {
SimpleCommandLinePropertySource ps = new SimpleCommandLinePropertySource(args);
logger.info(" mysuperdate value is : {}", ps.getProperty("mysuperdate") ); // display >
// INFO ProjetClientApplication :: lambda$1 > mysuperdate value is : 2023-09-21T14:21:21.212
}
}