2015-01-28 12 views
30

Se sto sviluppando un'applicazione basata su console Spring Boot piuttosto semplice, non sono sicuro del posizionamento del codice di esecuzione principale. Devo metterlo nel metodo public static void main(String[] args), o hanno la classe di applicazione principale implementi l'interfaccia CommandLineRunner e inserire il codice nel metodo run(String... args)?Come funziona un'applicazione basata su console Spring Boot?

Userò un esempio come contesto. Dire che ho la seguente applicazione [rudimentale] (coded per interfacce, stile della molla):

Application.java

public class Application { 

    @Autowired 
    private GreeterService greeterService; 

    public static void main(String[] args) { 
    // ****** 
    // *** Where do I place the following line of code 
    // *** in a Spring Boot version of this application? 
    // ****** 
    System.out.println(greeterService.greet(args)); 
    } 
} 

GreeterService.java (interfaccia)

public interface GreeterService { 
    String greet(String[] tokens); 
} 

GreeterServiceImpl.java (classe di implementazione)

@Service 
public class GreeterServiceImpl implements GreeterService { 
    public String greet(String[] tokens) { 

    String defaultMessage = "hello world"; 

    if (args == null || args.length == 0) { 
     return defaultMessage; 
    } 

    StringBuilder message = new StringBuilder(); 
    for (String token : tokens) { 
     if (token == null) continue; 
     message.append(token).append('-'); 
    } 

    return message.length() > 0 ? message.toString() : defaultMessage; 
    } 
} 

La versione Primavera Boot equivalente di Application.java sarebbe qualcosa sulla falsariga: GreeterServiceImpl.java (classe di implementazione)

@EnableAutoConfiguration 
public class Application 
    // *** Should I bother to implement this interface for this simple app? 
    implements CommandLineRunner { 

    @Autowired 
    private GreeterService greeterService; 

    public static void main(String[] args) { 
     SpringApplication.run(Application.class, args); 
     System.out.println(greeterService.greet(args)); // here? 
    } 

    // Only if I implement the CommandLineRunner interface... 
    public void run(String... args) throws Exception { 
     System.out.println(greeterService.greet(args)); // or here? 
    } 
} 
+3

Utilizzare un 'CommandLineRunner' che è quello che è stato progettato per, è anche possibile creare un'istanza di esso e avere delle dipendenze iniettate in esso. Questo fallirebbe nel tuo primo scenario dato che non avresti una dipendenza iniettata o non sarei in grado di accedervi dal metodo statico. –

+0

@ M.Deinum quindi tali applicazioni basate su console devono implementare l'interfaccia CommandLineRunner come una regola generale? Ciò fornisce una chiarezza sufficiente per me, perché anche i documenti non si concentrano su questo punto (probabilmente perché è implicito per la maggior parte della gente!). –

+3

Bene, idealmente crei un bean che implementa questa interfaccia (e non la tua classe 'Application'). Ha a che fare con la separazione delle preoccupazioni (l'avvio dell'applicazione e l'esecuzione della logica). –

risposta

42

si dovrebbe avere un caricatore standard:

@SpringBootApplication 
public class MyDemoApplication { 
    public static void main(String[] args) { 
     SpringApplication.run(MyDemoApplication.class, args); 
    } 
} 

e implementare un'interfaccia CommandLineRunner con @Component annotazione

@Component 
    public class MyRunner implements CommandLineRunner { 

     @Override  
     public void run(String... args) throws Exception { 

     } 
    } 

@EnableAutoConfiguration farà la solita magia SpringBoot.

UPDATE:

Come suggerisce il @jeton laters Springboot implementa una scala:

spring.main.web-environment=false 
spring.main.banner-mode=off 

Vedi docs at 72.2

+4

Perché pensi che questo sia il modo corretto di implementare un'applicazione CLI usando Spring Boot? 'CommandLineRunner' e' ApplicationRunner' non sono pensati solo per essere utilizzati per le app CLI. Inoltre, quando si utilizza uno di essi, Spring esegue il rispettivo metodo 'run' prima di avviare il metodo' main' della propria app come evidente dal messaggio di registro 'INFO 6961 --- [restartedMain] org.behrang.rpn.Main: Iniziato Main in XX.YYY secondi (JVM in esecuzione per MM.NNN) 'appare dopo l'esecuzione del codice nel metodo' CommandLineRunner.run (...) '. – Behrang

+4

@Behrang Allora qual è il modo corretto per farlo, allora? – Wesam

+1

@Wesam Sfortunatamente non c'è un modo elegante per fare questo che io sappia. Ecco una possibile soluzione: https://gist.github.com/behrangsa/6a7f050e7f6d193918ad7e910812fb28 – Behrang