一尘不染

如何在Spring Boot远程shell中将参数和选项传递给自定义远程shell命令?

spring-boot

根据上述问题的建议,我正在尝试Spring Boot远程外壳。

我已根据此文档创建了自定义命令,

http://docs.spring.io/spring-boot/docs/current/reference/html/production-
ready-remote-shell.html#production-ready-extending-the-remote-
shell

但是在现实的用例中,我们大多数都有参数和命令选项。在文档中没有提及如何定义它们,以便用户在运行命令时通过。

这是很好的解释,并且很容易做到。

http://docs.spring.io/spring-shell/docs/current/reference/htmlsingle/#simple-
application

https://projects.spring.io/spring-shell/

但是我们不能将弹簧壳与弹簧靴一起使用。

对于这些用例,可靠的生产就绪解决方案是什么?

更新:

在CRaSH doc上获得了解决方案

http://www.crashub.org/1.3/reference.html#developping_commands

登录到shell后,我可以在命令列表中看到myCommand,但是当我运行command时,

但我越来越例外

"Could not create command commandName instance".

我试图在命令中使用spring bean,所以我做了自动装配,例如

package commands;

import org.crsh.cli.Argument;
import org.crsh.cli.Command;
import org.crsh.cli.Usage;
import org.crsh.cli.Option;
import org.crsh.cli.Required;
import org.crsh.command.BaseCommand;
import org.crsh.command.InvocationContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;


@Usage("My test computation commands.")
public class myCommand extends BaseCommand {

    protected final Logger log = LoggerFactory.getLogger(getClass());

    /**
     * 
     */
    public Service1 service1;

    /**
     * 
     */
    public Service2 service2;

    /**
     * @param service1
     * @param service2
     */
    @Autowired
    public myCommand(Service1 service1, Service2 service2) {
        super();
        this.service1 = service1;
        this.service2 = service2;
    }


    @Usage("Test command")
    @Command
    public Map<String, Double> command1(InvocationContext<Object> context, @Usage("id") @Required @Argument int id)
            throws Exception {


        Map<String, Double> result = new HashMap<>();

        result.put("key1", service1.compute(id));
        result.put("key2", service2.compute(id));

        return result;

    }

}

阅读 518

收藏
2020-05-30

共1个答案

一尘不染

我认为您不能在Remote Shell命令中注入bean。

但是,您可以将InvocationContext注入到方法中,并使用它从上下文中检索spring托管的bean:

@Usage('Example using spring.beanfactory')
@Command
def mycommand(InvocationContext context, ...) {
    BeanFactory beans = context.attributes['spring.beanfactory']
    YourBean bean = beans.getBean(YourBean.class);
    ...
}

一个对我有用的完整示例:

package commands

import org.crsh.cli.Command
import org.crsh.cli.Usage
import org.crsh.command.InvocationContext
import org.springframework.beans.factory.BeanFactory
import com.alexbt.goodies.MyBean

class SayMessage {
    String message;
    SayMessage(){
        this.message = "Hello";
    }

    @Usage("Default command")
    @Command
    def main(InvocationContext context, @Usage("A Parameter") @Option(names=["p","param"]) String param) {
        BeanFactory beanFactory = (BeanFactory) context.getAttributes().get("spring.beanfactory");
        MyBean bean = beanFactory.getBean(MyBean.class);
        return message + " " + bean.getValue() + " " + param;
    }

    @Usage("Hi subcommand")
    @Command
    def hi(InvocationContext context, @Usage("A Parameter") @Option(names=["p","param"]) String param) {
        BeanFactory beanFactory = (BeanFactory) context.getAttributes().get("spring.beanfactory");
        MyBean bean = beanFactory.getBean(MyBean.class);
        return "Hi " + bean.getValue() + " " + param;
    }
}

> saymsg -p Johnny
> Hello my friend Johnny

> saymsg hi -p Johnny
> Hi my friend Johnny
2020-05-30