как создать консольную команду в весеннем загрузочном веб-приложении с помощью весенней оболочки?

Я создал веб-приложение restfull, используя веб-стартер весенней загрузки, который работает хорошо. Я могу получить к нему доступ через URL-адреса.

Но у меня есть требование создать консольную команду, которая может вычислять и сохранять некоторые значения в бэкэнде. Я хочу иметь возможность запускать консольную команду вручную или через скрипт bash.

Я не смог найти никакой документации о том, как интегрировать проект Spring-Shell в веб-приложение Spring Boot.

Также нет возможности выбрать зависимость от spring-shell в стартере весенней загрузки https://start.spring.io/

1) Должны ли веб-приложение и консоль быть двумя отдельными приложениями, и мне нужно развертывать их отдельно?

2) Можно ли развернуть веб-приложение и запустить консольные команды в одном приложении?

3) Каков наилучший подход к совместному использованию общего кода (модели, сервисов, объектов, бизнес-логики) между оболочкой и веб-приложениями?

Может ли кто-нибудь помочь в этом?


person vishal    schedule 05.09.2016    source источник


Ответы (2)


Вот 2 варианта:

(1) Rest API вызывается из командной строки

Вы можете создать Spring @RestController, который затем вызываете из командной строки?

curl -X POST -i -H "Content-type: application/json" -c cookies.txt -X POST http://hostname:8080/service -d '
    {
        "field":"value",
        "field2":"value2"
    }
    '

Вы можете легко встроить это в хороший сценарий оболочки.

(2) Используйте spring-boot-remote-shell (устарело)

Хотя это в основном для целей мониторинга/администрирования, вы можете использовать spring-boot-remote-shell для этого.

Зависимости

Для включения удаленной оболочки вам потребуются следующие зависимости:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-remote-shell</artifactId>
</dependency>
<dependency>
    <groupId>org.crsh</groupId>
    <artifactId>crsh.shell.telnet</artifactId>
    <version>1.3.0-beta2</version>
</dependency>

Скрипт Groovy:

Добавьте следующий скрипт в src/main/resources/custom.groovy:

package commands

import org.crsh.cli.Command
import org.crsh.cli.Usage
import org.crsh.command.InvocationContext

class custom {

    @Usage("Custom command")
    @Command
    def main(InvocationContext context) {
        return "Hello"
    }
}

Чтобы получить bean-компонент Spring из этого отличного скрипта (источник: https://stackoverflow.com/a/24300534/641627):

BeanFactory beanFactory = (BeanFactory) context.getAttributes().get("spring.beanfactory");
MyController myController = beanFactory.getBean(MyController.class);

Запустите SpringBootApp

С spring-boot-remote-shell в пути к классам приложение Spring Boot прослушивает порт 5000 (по умолчанию). Теперь вы можете сделать это:

$ telnet localhost 5000
Trying ::1...
Connected to localhost.
Escape character is '^]'.
  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::  (v1.3.5.RELEASE)

Справка

Вы можете ввести help, чтобы увидеть список доступных команд:

NAME       DESCRIPTION                                                                                                                                                                 
autoconfig Display auto configuration report from ApplicationContext                                                                                                                   
beans      Display beans in ApplicationContext                                                                                                                                         
cron       manages the cron plugin                                                                                                                                                     
custom     Custom command                                                                                                                                                              
dashboard                                                                                                                                                                              
egrep      search file(s) for lines that match a pattern                                                                                                                               
endpoint   Invoke actuator endpoints                                                                                                                                                   
env        display the term env                                                                                                                                                        
filter     A filter for a stream of map                                                                                                                                                
help       provides basic help                                                                                                                                                         
java       various java language commands                                                                                                                                              
jmx        Java Management Extensions                                                                                                                                                  
jul        java.util.logging commands                                                                                                                                                  
jvm        JVM informations                                                                                                                                                            
less       opposite of more                                                                                                                                                            
log        logging commands                                                                                                                                                            
mail       interact with emails                                                                                                                                                        
man        format and display the on-line manual pages                                                                                                                                 
metrics    Display metrics provided by Spring Boot                                                                                                                                     
shell      shell related command                                                                                                                                                       
sleep      sleep for some time                                                                                                                                                         
sort       Sort a map                                                                                                                                                                  
system     vm system properties commands                                                                                                                                               
thread     JVM thread commands 

Вызов нашей пользовательской команды

Наша пользовательская команда указана в списке (четвертая сверху), вы можете вызвать ее:

> custom
Hello

Итак, по сути, ваш crontab сделает telnet 5000 и выполнит custom

(3) Как использовать аргументы и параметры (чтобы ответить на вопрос в комментариях)

Аргументы

Чтобы использовать аргументы, вы можете ознакомиться с документацией:

class date {
  @Usage("show the current time")
  @Command
  Object main(
     @Usage("the time format")
     @Option(names=["f","format"])
     String format) {
    if (format == null)
      format = "EEE MMM d HH:mm:ss z yyyy";
    def date = new Date();
    return date.format(format);
  }
}

% date -h
% usage: date [-h | --help] [-f | --format]
% [-h | --help]   command usage
% [-f | --format] the time format

% date -f yyyyMMdd

Подкоманда (или опции)

Кадр из их документации:

@Usage("JDBC connection")
class jdbc {

  @Usage("connect to database with a JDBC connection string")
  @Command
  public String connect(
          @Usage("The username")
          @Option(names=["u","username"])
          String user,
          @Usage("The password")
          @Option(names=["p","password"])
          String password,
          @Usage("The extra properties")
          @Option(names=["properties"])
          Properties properties,
          @Usage("The connection string")
          @Argument
          String connectionString) {
     ...
  }

  @Usage("close the current connection")
  @Command
  public String close() {
     ...
  }
}

% jdbc connect jdbc:derby:memory:EmbeddedDB;create=true

Последняя команда выполняет:

  • команда jdbc
  • с помощью подкоманды connect
  • и аргумент jdbc:derby:memory:EmbeddedDB;create=true

Полный пример

Следующее содержит:

  • конструктор;
  • команда с аргументами;
  • фасоль управляемая весной;
  • подкоманда с аргументами.

Код:

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
person alexbt    schedule 05.09.2016
comment
как передать аргумент и параметры команде? В доке об этом ничего не сказано. - person vishal; 28.09.2016
comment
Я сделал то же самое, но получил исключение Не удалось создать экземпляр команды. У меня есть конструктор в моей команде. - person vishal; 29.09.2016
comment
Я задал дополнительный вопрос здесь stackoverflow.com/questions/39750597/ - person vishal; 29.09.2016
comment
Я ответил в этой теме и в другой теме тоже. Ваша проблема заключается в том, что @Autowiring не передает аргументы вашей команде. - person alexbt; 29.09.2016
comment
Спасибо, да, я пробовал это, но нет ни одного примера для команды Java, которая использует beanfactory для получения bean-компонентов. Не уверен, что это правильный синтаксис. Есть ли здесь преимущества использования groovy над java? – - person vishal; 29.09.2016
comment
Еще одна вещь, беспокоящая меня по поводу CRaSH (весенняя загрузочная удаленная оболочка), заключается в том, что CRaSH компилируется во время выполнения, что может увеличить производительность по сравнению с spring-shell? Было бы здорово, если бы spring-boot поддерживал интеграцию spring-shell из коробки. - person vishal; 29.09.2016
comment
К сожалению, Spring Remote Shell устарела в Spring Boot 1.5 - person Casey; 01.03.2017

Похоже, у вас есть два разных варианта использования: запуск запланированных задач и запуск команд вручную. Насколько я понимаю, Spring Shell не является частью экосистемы Boot. Вы можете написать приложение Spring Shell, которое является внешним по отношению к вашему загрузочному веб-приложению, но оно не будет встроено в него. По крайней мере из моего опыта.

В первом случае запланированных задач вы должны посмотреть Планировщик Spring. Вы должны иметь возможность настроить приложение Spring (загрузочное или обычное), в котором есть планировщик заданий. Затем вы можете настроить свои задачи, которые можно запланировать, позволяя планировщику выполнять свою работу.

Для ручного выполнения команд у вас есть несколько вариантов. Если вы используете Spring Shell, предположите, что он работает в собственном процессе, внешнем по отношению к процессу Spring Boot. Вам потребуется, чтобы приложение Shell вызывало приложение Boot (предполагая, что именно там вы хотите работать) с использованием технологий удаленного вызова методов (например, RMI, REST и т. д.).

Альтернативой Spring Shell является встраивание удаленной оболочки в ваше загрузочное приложение. По сути, вы можете использовать SSH для подключения к загрузочному приложению и определения команд аналогично Spring Shell. Преимущество заключается в том, что это происходит в том же процессе, что и загрузочное приложение. Таким образом, вы можете внедрить планировщик заданий и запускать те же задачи вручную, что запланированы. Это может быть хорошим вариантом, если вы хотите вручную отключить те же запланированные задачи. Документация для удаленной консоли находится здесь. .

Надеюсь это поможет

person EdH    schedule 05.09.2016
comment
Спасибо @Edh, я не хочу иметь 2 отдельных приложения (web и cli), потому что вся бизнес-логика общая, я не хочу повторять это в двух приложениях. Удаленная оболочка звучит довольно много, как я хочу. Рассмотрю это. - person vishal; 05.09.2016