JavaRush /Java Blog /Random-IT /Stivale di conquista primaverile
Surplus
Livello 37
Москва

Stivale di conquista primaverile

Pubblicato nel gruppo Random-IT
Buona giornata, caro lettore! Ed è un piacere conoscerti, anche se il nome pomposo è stato il motivo principale per approfondire il modesto argomento sulla prima conoscenza dello sviluppo di Spring Boot. Vorrei condividere la mia esperienza nel portare a termine l'incarico introduttivo per uno stage sul portale JavaRush, presentando una panoramica dal lato di uno studente universitario tecnico del tutto normale che vuole mettere alla prova la forza delle sue conoscenze accumulate. Stivale primaverile della conquista - 1Non nego in alcun modo la possibile presenza di maleducazione nel codice allegato o nel metodo di pensiero, e accolgo con favore le critiche costruttive, perché è grazie a “conti e contusioni” che è possibile svilupparsi in una direzione professionale. Inoltre, non pretendo affatto di essere una "panacea" nel risolvere le condizioni date e ometto deliberatamente singoli frammenti del programma, lasciando l'importanza fondamentale di entrare in un argomento relativamente complesso senza le minime conseguenze per il sistema nervoso. È vero, è incauto negare l’ovvio: per me è stata dura e fino a un certo momento non mi era assolutamente chiaro nulla. E se provi sentimenti simili fin dal primo incontro con l'attività, allora "Benvenuto!" Scriviamo un'applicazione Web in Spring Boot utilizzando un'analogia semplificata di un test di ingresso al tirocinio utilizzando un motore di modelli Thymeleafe queryquery su un server MySQL locale per filtrare la serie di informazioni in arrivo. Quindi iniziamo!

Stivale primaverile. Che tipo di animale è e come cucinarlo?

In breve e concisamente, è uno strumento eccellente di Pivotel per risparmiare tempo prezioso nel processo di creazione di un'applicazione, eliminando la necessità di connettere direttamente librerie di terze parti, scrivere un'impressionante tela di mappatura e servlet. È sufficiente utilizzare il builder Spring Inizializr , integrato in IntelliJ IDEA Ultimate Edition (File - Nuovo - Progetto... - Spring Inizializr) o situato sul servizio web start.spring.io , specificando i pacchetti da includere tra un'ampia gamma di offerte.
Stivale primaverile della conquista - 2
Seguendo le specifiche tecniche proposte, utilizzeremo il gentleman’s set, standard per creare una semplice applicazione web utilizzando il database MySQL :
  • WEB è il componente principale per lo sviluppo di un'applicazione web, incluso un server Apache Tomcat locale all'indirizzo standard localhost:8080 e il framework universale Spring MVC.

  • DevTools : utilizzato per riavviare rapidamente un'applicazione in una JVM hot quando vengono rilevate modifiche nel codice o nei modelli compilati; Inoltre, libera Thymeleaf dalla pulizia della cache se il motore selezionato è incluso nel progetto.

  • JPA è una tecnologia necessaria per lavorare con i database e fornisce la mappatura relazionale degli oggetti Java, fornisce un'API ( Hibernate nel nostro caso) per la gestione, il salvataggio e il recupero delle entità.

  • Thymeleaf (Mustache, AngularJS, Vaadin e oltre) - motore di template per la visualizzazione delle applicazioni; Grazie alla mia relativa familiarità con i principi di html, ho scelto Thymeleaf, che ha reso il linguaggio la pietra angolare del mondo.

  • MySQL : collega i driver Java Database Connectivity per eseguire query SQL sul database.
Dopo la selezione finale dei componenti e la creazione, otteniamo una normale architettura di applicazione web con directory pronte per un ulteriore riempimento. I frammenti per interagire con la parte visiva, siano essi stili grafici CSS, pagine HTML standard o funzionalità JavaScript, dovrebbero essere posizionati in "risorse" e il componente back-end, di conseguenza, dovrebbe essere posizionato in "java". Dovremmo anche prestare attenzione al file pom.xml nell'intervallo root, che memorizza la struttura del progetto e le dipendenze tra i componenti. Se desideri espandere ulteriormente la funzionalità con pacchetti aggiuntivi o rimuovere cose non necessarie, dovresti eseguire le manipolazioni tra i tag <dependencies></dependencies>secondo un metodo simile.
Stivale primaverile della conquista - 3

Primi passi verso un grande futuro

Successivamente sorge una domanda piuttosto interessante e abbastanza logica: “Cosa fare adesso? Come funzionerà? Il programma è costruito sui principi di Model-View-Controller: organizza la lettura delle entità dal database collegato (Model) e viene visualizzato nell'interfaccia utente con controlli (View); la comunicazione tra i componenti e l'esecuzione delle azioni in base alle richieste trasmesse avviene grazie al Titolare. È la creazione di elementi chiave che funge da punto di riferimento per lo sviluppo continuo. Per evitare una china pericolosa e mantenere il rispetto dei vostri compagni di lavoro, dovreste posizionare i componenti nelle directory appropriate (ad esempio posizionare il file Controller nella cartella controllers nel ramo “java”) e conservare con cura ordine sul posto di lavoro.

L’essenza è una piccola parte di un grande meccanismo

O in altre parole, il nostro Modello in base alle condizioni poste nel problema. Allontanandoci dall'argomento della discussione e tornando al progetto introduttivo, possiamo affermare con sicurezza che ci sono differenze minime tra i compiti e aderire al concetto medio nella revisione successiva. Diciamo, appunti su un taccuino, tra cui:
  • Numero di identificazione per determinare la posizione nel flusso generale;
  • Un messaggio di testo di un certo numero di caratteri;
  • La data in cui l'utente lo ha aggiunto all'elenco generale;
  • Una variabile booleana per determinare "Fatto o non fatto" ("Letto o non letto").
Creiamo quindi una classe Note in una directory chiamata “entity” e aggiungiamo i campi appropriati:
@Entity
public class Note {

   @Id
   @GeneratedValue
   private int id;
   private String message;
   private Date date;
   private boolean done;

   public Note() {
   }

   public Note(String message) {
       this.message = message;
       this.date = new Date();
       this.done = false;
   }
}
Un'altra deviazione dall'argomento in discussione per una maggiore comprensione di ciò che sta accadendo da una posizione teorica. La connessione tra i componenti in Spring è specificata da annotazioni : puntatori speciali davanti agli oggetti, ognuno dei quali svolge un ruolo specifico nel meccanismo e inizia con il simbolo "@". L'annotazione @Entity indica a Spring Boot che i dati della classe successiva appartengono all'“Entity” e @Id e @GeneratedValue specificano il campo selezionato come identificatore con generazione automatica di un iteratore durante l'elaborazione di un array di informazioni. Ometto deliberatamente di aggiungere Getter e Setter standard per aumentare la compattezza del formato visivo. Successivamente, tenendo conto dell'utilizzo di un database per l'archiviazione dei record, passiamo al passaggio successivo nello sviluppo dell'applicazione: creeremo l'interfaccia NoteRepository nella directory "repository", un elemento di collegamento nella catena di scambio, ed erediteremo la maggior parte repository adatto per ulteriori lavori, indicando l'entità memorizzata e l'iteratore intero a cui accedere.
public interface NoteRepository extends JpaRepository<Note, Integer> {
}
In realtà, questo è tutto. Breve e conciso. Ora Spring Boot utilizzerà il componente creato per organizzare le interazioni con il database. Esistono relativamente molti tipi di repository legacy con diverse potenzialità di azione. JpaRepository è in cima alla scala e ha il maggior potenziale, inclusi CrudRepository e PageAndSortingRepository sotto di esso. Non andremo oltre e non devieremo dall'argomento, perché alcune sottigliezze si trovano sul sito Pivotel nella documentazione tecnica. Ora, dopo aver implementato l'immagine dei dati e specificato i metodi di comunicazione lato applicazione, è necessario prestare attenzione alla creazione di un database MySQL nell'apposito ambiente esterno “MySQL Workbench”, preinstallato sulla piattaforma desktop in un assembly dallo sviluppatore ufficiale con pacchetti aggiuntivi per la creazione di un server locale:
Stivale primaverile della conquista - 4
Successivamente, seguendo le istruzioni dell'ambiente e dopo aver cliccato sull'icona con il server locale corrente nella finestra principale, creiamo un diagramma di tabella in base ai campi della nostra entità (Nota) e lo compiliamo con i dati appropriati. È necessario chiarire separatamente le sottigliezze del dialetto MySQL, che richiedono urgentemente attenzione per ottenere con successo il risultato desiderato:
  • Non esiste un tipo booleano separato in quanto tale. Qualsiasi azione di elaborazione della richiesta convertirà "vero" o "falso" rispettivamente nel valore bit "1" o "0";
  • La data viene archiviata interamente nel tipo Timestamp. Se usi Date, che ti è familiare, dovrai limitarti solo alla posizione nel calendario.
Alla conquista dello stivale primaverile - 5
Dopo il completamento finale dei passaggi preparatori, indichiamo “MySQL Workbench” per inviare i dati al server locale facendo clic sull'icona “fulmine” sulla barra degli strumenti. Ora, se l'aggiunta delle informazioni è stata completata correttamente, possiamo tornare con sicurezza al nostro IDE nativo per continuare lo sviluppo aggiungendo la configurazione corrente del database a application.properties (solitamente situato nella directory "resources"):
spring.datasource.url=jdbc:mysql://localhost:3306/test?useSSL=false
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.jpa.show-sql=true
spring.jpa.hibernate.ddl-auto=update
E infine associare l'entità Note a MySQL utilizzando le annotazioni. @Table indica l'uso di una tabella con il nome e lo schema selezionati e @Column indica che le variabili appartengono a un campo specifico.
@Entity
@Table(name = "test", schema = "test", catalog = "")
public class Note {

   @Id
   @GeneratedValue
   private int id;
   @Column(name = "message")
   private String message;
   @Column(name = "date")
   private Date date;
   @Column(name = "done")
   private boolean done;

   public Note() {
   }

   public Note(String message) {
       this.message = message;
       this.date = new Date();
       this.done = false;
   }
}

Visualizza o interfaccia utente

Purtroppo, possiamo tranquillamente affermare quanto segue: "La visualizzazione dell'applicazione diventerà il principale ostacolo senza la minima conoscenza teorica o pratica". Ad essere sincero, la componente front-end ha assorbito una quantità sorprendente della quantità totale di lavoro e mi ha logorato i nervi per un lungo periodo di tempo. Ma grazie alla straordinaria semplicità di Thymeleaf, è stato possibile trovare un compromesso adeguato dopo una serie di incantevoli sconfitte. Ulteriori discussioni riguarderanno le complessità dell'utilizzo del motore selezionato, sebbene il concetto generale aderisca a una posizione simile. La tecnica principale è la capacità di utilizzare l'HTML più puro e assemblare la visualizzazione finale da singoli frammenti per evitare ripetizioni multiple di sezioni identiche. Supponiamo che l'architettura dell'interfaccia utente sia composta da una pagina principale composta da una barra di navigazione con controlli (aggiunta di una nuova voce, ritorno alla pagina principale) e una tabella dinamica per la visualizzazione delle entità ordinate in base al momento in cui è stata aggiunta la nota in ordine crescente (ASC) o direzione di decremento (DESC).significati. Prendiamo come standard la visualizzazione di tutti i record in ordine crescente. Secondo la politica gerarchica del motore di template selezionato, gli elementi di visualizzazione dei componenti dovrebbero trovarsi nel ramo "templates" nella directory "resources". Di conseguenza, ulteriori manipolazioni con i componenti tengono conto delle condizioni proposte. Creiamo una pagina principale con il nome "index" (o qualsiasi altro nome a seconda delle preferenze personali) su un modello html5. Per esempio:
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
     xmlns:th="http://www.thymeleaf.org">
<head th:replace="fragments/head :: head"></head>
<body>
<div class="container">
   <div th:replace="fragments/header :: header"></div>
   <div th:if="${not #lists.isEmpty(notes)}">
       <div th:replace="operations/list :: notebook"></div>
   </div>
   <div th:replace="fragments/footer :: footer"></div>
</div>
</body>
</html>
E quindi, analizziamo i componenti chiave dell’applicazione finale. Thymeleaf utilizza una sintassi separata per indicare l'uso delle procedure e inizia con la parola chiave “th:”, il collegamento alla libreria con la quale è necessariamente incluso nel tag di apertura <html>.
<div th:if="${not #lists.isEmpty(notes)}">
L'operazione "se" non è completamente diversa dal solito modo di fare le cose e controlla l'attributo "note" in entrata per la presenza di oggetti da visualizzare ulteriormente. Vale la pena menzionare separatamente la sovrapposizione dell'argomento con l'uso di Controller, tenendo conto del suo utilizzo per organizzare l'interazione del modello e della visualizzazione. Molti istanti vaghi prendono forma nel futuro, basta tornare indietro se vuoi.
<head th:replace="operations/list :: notebook"></head>
L'operazione “sostituisci” indica la sostituzione di uno “stub” o di un blocco attivo con un frammento selezionato dalla pagina corrente o separata - quest'ultimo caso è chiaramente osservato nell'esempio. Copiamo il frammento denominato “notebook” da “list.html” della directory “operazioni” nel <div></div> del file “indice”, sostituendo completamente il contenuto nella destinazione finale. Quello in uscita ha il seguente contenuto:
<!DOCTYPE html>
<!--suppress ALL -->
<html xmlns="http://www.w3.org/1999/xhtml"
     xmlns:th="http://www.thymeleaf.org">

<div th:fragment="notebook">
   <table class="table table-bordered table-hover horizontal-align">
       <thead>
       <tr>
           <th style="width: 5%">#</th>
           <th style="width: 60%">Message</th>
           <th class="dropdown" style="width: 20%">Date
               <a th:href="@{'/sort/{sortDate}' (sortDate = 'ASC')}"><i class="fa fa-chevron-circle-up"></i></a>
               <a th:href="@{'/sort/{sortDate}' (sortDate = 'DESC')}"><i class="fa fa-chevron-circle-down"></i></a>
           </th>
           <th style="width: 5%">Done</th>
           <th style="width: 5%">Edit</th>
           <th style="width: 5%">Delete</th>
       </tr>
       </thead>
       <tbody>
       <tr th:each="note : ${notes}">
           <td th:text="${note.id}" style="text-align: center">#</td>
           <td th:text="${note.message}">Message</td>
           <td th:text="${#dates.format(note.date, 'EEE, d MMM yyyy HH:mm')}" style="text-align: center">Date</td>
           <td style="text-align: center">
               <i th:if="${note.done} == true" class="fa fa-plus-square-o" style="font-size:20px;color:#337ab7"></i>
               <i th:if="${note.done} == false" class="fa fa-minus-square-o" style="font-size:20px;color:#337ab7"></i>
           </td>
           <td style="text-align: center"><a th:href="@{'/edit/{id}'(id=${note.id})}"><i class="fa fa-edit" style="font-size:20px"></i></a></td>
           <td style="text-align: center"><a th:href="@{'/delete/{id}'(id=${note.id})}"><i class="fa fa-trash" style="font-size:20px"></i></a></td>
       </tr>
       </tbody>
   </table>
</div>
</html>
Torniamo alla panoramica costruttiva ed esaminiamo in ordine le funzioni Thymeleaf utilizzate, omettendo la sintassi HTML standard o gli stili grafici utilizzati e concentrandoci specificamente sulla comprensione del meccanismo del motore dei template.
<div th:fragment="notebook">
L'operazione “frammento” specifica il nome del frammento e permette di utilizzare il contenuto del blocco per il comando “sostituisci”. Inoltre! Non sono in alcun modo esclusi utilizzi multipli all'interno di una stessa pagina, riproponendo ancora una volta l'analogia con procedure o funzioni nei linguaggi di programmazione.
<a th:href="@{'/sort/{sortDate}' (sortDate = 'ASC')}">
Una chiamata all'annotazione @PostMapping viene utilizzata nel Controller con la mappatura "/sort/{sortDate}", dove {sortDate} è l'attributo della direzione di ordinamento in uscita. Qualcosa di simile può essere visto nel blocco seguente, che aggiunge una modifica dinamica a seconda della posizione dell'elemento selezionato dall'utente nel ciclo di iterazione:
<a th:href="@{'/edit/{id}'(id=${note.id})}">
<tr th:each="note : ${notes}">
L'enumerazione dei valori è molto simile all'uso familiare di un blocco for nella sintassi Java: la variabile "note" prende l'elemento corrente dall'array di attributi di input ${notes}, un array di entità, e viene utilizzata per modificare i valori più tardi. Ad essere sinceri, potremmo dedicare un articolo separato all'elenco dell'ampia gamma di funzionalità di Thymeleaf con esempi di applicazione pratica: il motore del modello è estremamente semplice e non richiede affatto l'apprendimento di un bagaglio impressionante di sintassi aggiuntiva. Le funzioni sopra descritte sono descritte nella documentazione tecnica sul sito ufficiale degli sviluppatori e sono di fondamentale importanza nell'organizzazione della comunicazione con il back-end. Pertanto, puoi passare con sicurezza alla parte successiva e finale. Naturalmente allegando i restanti componenti della visualizzazione in un collegamento all'applicazione finita alla fine dell'articolo.

Controller, amministratore in una piccola azienda

"La pietra angolare nell'architettura di un'applicazione web" - forse non c'è modo di trovare una descrizione più accurata dell'importanza del componente Controller nell'organizzazione del lavoro del programma: la maggior parte delle operazioni vengono eseguite proprio dall'elemento di collegamento tra modello e vista. Grazie alla meccanica di azione di Spring Boot, puoi utilizzare con sicurezza i metodi di mappatura e di richiesta GET/POST senza il minimo problema e connettere automaticamente il repository di dati. Creiamo la classe NoteController in un file separato nella directory “controllers”, facendo sempre riferimento all'utilizzo dell'apposita annotazione:
@Controller
public class NoteController {

   private NoteService service;

   @Autowired
   public void setNoteService(NoteService service) {
       this.service = service;
   }

   @GetMapping("/")
   public String list(Model model) {
       return "index";
   }
}
Un occhio attento potrebbe notare un cambiamento importante nella progettazione dell'architettura dell'applicazione associato all'aggiunta di un servizio per isolare la logica aziendale dal lavoro con il servizio di gestione del database. Le azioni completate sono necessarie per aumentare la versatilità del prodotto finito e fornire un'ampia possibilità di modificare la funzionalità dell'interfaccia utente senza la necessità di modificare i metodi di comunicazione con il database. La rappresentazione standard non si distingue in alcun modo dalla massa di simili: l'interfaccia si trova in una directory separata ed è implementata da una classe con l'annotazione @Service per il rilevamento Spring Boot:
public interface NoteService {
   Note getNoteById(Integer id);
   void saveNote(Note note);
   void updateNote(Integer id, String message, boolean done);
   void deleteNote(Integer id);
   List<Note> findAll();
}

@Service
public class NoteServiceImpl implements NoteService{

   private NoteRepository repository;

   @Autowired
   public void setProductRepository(NoteRepository repository) {
       this.repository = repository;
   }

   @Override
   public Note getNoteById(Integer id) {
       return repository.findOne(id);
   }

   @Override
   public void saveNote(Note note) {
       repository.save(note);
   }

   @Override
   public void updateNote(Integer id, String message, boolean done) {
       Note updated = repository.findOne(id);
       updated.setDone(done);
       updated.setMessage(message);
       repository.save(updated);
   }

   @Override
   public void deleteNote(Integer id) {
       repository.delete(id);
   }

   @Override
   public List<Note> findAll() {
       return repository.findAll();
   }
}
Torniamo alla revisione del controller e esaminiamo le complessità dell'organizzazione del lavoro utilizzando i metodi Spring Boot. L'annotazione @Autowired indica la necessità di associare automaticamente un servizio a una variabile specificata del tipo appropriato e stabilire una connessione con il database. Occorre prestare maggiore attenzione al modo in cui comunica la vista, indicato dall'annotazione @GetMapping("/"), che restituisce una pagina denominata “index” quando riceve una chiamata a localhost:8080. È possibile utilizzare un approccio diverso, specificando la descrizione estesa @RequestMapping(value = "/", metodo = RequestMethod.GET) o sostituendo il tipo restituito con un ModelAndView già pronto. Tuttavia, secondo l'attuale esperienza nell'applicazione pratica, non noto alcuna differenza fondamentale nel risultato finale e utilizzo la solita opzione. Espandiamo il controller aggiungendo nuovi elementi utilizzando una scheda aggiuntiva. Dopo che l'utente ha fatto clic su un elemento della barra di navigazione, @GetMapping("/new") viene chiamato e reindirizzato alla pagina "nuova" dalla directory "operazioni", restituendo un parametro denominato "messaggio" quando si confermano i dati immessi utilizzando il pulsante e reindirizzamento al blocco principale. Una menzione particolare merita la necessità di una corrispondenza completa del nome della variabile nella finestra di input con il nome del valore trasferito.
<input type="text" class="form-control" id="message" th:name="message" placeholder="Enter your note." maxlength="100"/>
@GetMapping("/new")
public String newNote() {
   return "operations/new";
}

@PostMapping("/save")
public String updateNote(@RequestParam String message) {
   service.saveNote(new Note(message));
   return "redirect:/";
}
Una tecnica simile viene utilizzata per aggiornare un record. Dopo aver fatto clic sul controllo viene richiamata la mappatura @GetMapping("/edit/{id}") e viene trasferito l'identificatore dalla stringa URL, viene aggiunto l'attributo “note” con una voce per ulteriori modifiche. @RequestParam(value = "done", require = false) boolean done) la specifica di un valore specifico gioca un ruolo chiave nell'uso della casella di controllo quando si utilizza il motore del modello Thymeleaf ed è impostata su "false" per impostazione predefinita.
@GetMapping("/edit/{id}")
public String edit(@PathVariable Integer id, Model model) {
   Note note = service.getNoteById(id);
   model.addAttribute("note", note);
   return "operations/edit";
}

@PostMapping("/update")
public String saveNote(@RequestParam Integer id, @RequestParam String message,
                      @RequestParam(value = "done", required = false) boolean done) {
   service.updateNote(id, message, done);
   return "redirect:/";
}
Rimuovere elementi dal database è estremamente semplice e non richiede alcuna manipolazione significativa chiamando la funzione di servizio appropriata utilizzando il valore passato:
@GetMapping("/delete/{id}")
public String delete(@PathVariable Integer id) {
   service.deleteNote(id);
   return "redirect:/";
}
Ora apportiamo piccole modifiche ai frammenti finiti e passiamo a un'entusiasmante comunicazione con MySQL utilizzando query di query in Spring Data JPA, aggiungendo separatamente una funzione per la gestione di semplici filtri prima di chiudere il Controller.
@Controller
public class NoteController {

   private String sortDateMethod = "ASC";

   @GetMapping("/")
   public String list(Model model) {
       List<Note> notebook = filterAndSort();
       model.addAttribute("notes", notebook);
       model.addAttribute("sort", sortDateMethod);
       return "index";
   }

private List<Note> filterAndSort() {
   List<Note> notebook = null;
   switch (sortDateMethod) {
       case "ASC":
           notebook = service.findAllByOrderByDateAsc();
           break;
       case "DESC":
           notebook = service.findAllByOrderByDateDesc();
           break;
   }
   return notebook;
}

Domanda così piccola, ma così importante.

È imbarazzante ammetterlo, il filtraggio dei valori, contrariamente alle aspettative, si è rivelato un altro ostacolo nell'adempimento del compito tecnico, superando con sicurezza la soglia di complessità stabilita dall'impaginazione, suddividendo l'array di dati in pagine separate di una certa dimensione per un'ulteriore visualizzazione. Molto probabilmente, la stanchezza accumulata stava mettendo a dura prova, ma... l'ispirazione è arrivata dopo un incontro del tutto casuale con le query di Query.
public interface NoteRepository extends JpaRepository<Note, Integer> {
   List<Note> findAllByOrderByDateAsc();
   List<Note> findAllByOrderByDateDesc();
}
Spring Data JPA offre la possibilità di creare query di database altamente granulari che eliminano la necessità di ordinare le informazioni una volta ricevute e hanno un'ampia gamma di potenzialità applicative. Per esempio:
List<Note> findAllByOrderByDateAsc();
Il metodo verrà convertito in una query SQL e visualizzerà tutti i record (findAll) ordinati (byOrder) per data (byDate) in ordine crescente (Asc). Inoltre, puoi creare combinazioni complesse ed campionare in molti campi con un unico requisito. Ad esempio, seleziona tutti i record (findAll) completati (byDoneTrue) in ordine (byOrder) decrescenti (Decs) in base al valore della data (byDate):
Page<Note> findAllByDoneTrueOrderByDateDesc(Pageable pageable);

Conclusione o un'altra confessione di un programmatore alle prime armi

Tutto! Puoi avviare in tutta sicurezza l'applicazione web utilizzando la combinazione Maiusc+F10 o facendo clic sull'icona corrispondente. Spring Boot creerà il programma su Apache Maven e installerà un server Apache Tomcat locale su localhost:8080. Ora devi solo seguire il collegamento in qualsiasi browser.
Stivale primaverile della conquista - 6
E, naturalmente, sviluppare una metodologia per soddisfare altri requisiti aziendali. Il potenziale dell'applicazione è limitato dallo sforzo, dall'intraprendenza e dall'immaginazione dello sviluppatore.
Stivale primaverile della conquista - 7
Essendo franco e prestando attenzione al percorso percorso, sono ancora e ancora convinto della correttezza della direzione scelta e realizzo i vantaggi dello studio sul portale educativo JavaRush. Grazie a una varietà di compiti pratici, è stato possibile restituire l'interesse seducente per la programmazione dell'apprendimento, che era stato completamente soppresso nel programma obsoleto e sorprendentemente noioso di un istituto di istruzione superiore di una direzione simile. Quattro mesi di studio attivo del materiale nello stack tecnologico di back-end hanno investito molte più conoscenze rispetto a interi anni trascorsi a frequentare lezioni e lezioni di laboratorio. Credici o no. Ti auguro di non cedere alle difficoltà di entrare in materie complesse, perché è attraverso il superamento degli ostacoli che miglioriamo e sviluppiamo professionalmente e personalmente. Spero che questa piccola storia mi abbia aiutato a scoprire alcune nuove idee per l'utilizzo dello straordinario strumento chiamato SpringBoot. PS Github .
Commenti
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION