JavaRush /Blog Java /Random-FR /Démarrage de printemps de conquête
Surplus
Niveau 37
Москва

Démarrage de printemps de conquête

Publié dans le groupe Random-FR
Bonne journée, cher lecteur ! Et c'est un plaisir de vous rencontrer, même si le nom pompeux était la principale raison d'aborder le modeste sujet de la première connaissance du développement Spring Boot. Je voudrais partager mon expérience de réalisation de la mission d'introduction à un stage sur le portail JavaRush, en présentant un aperçu du côté d'un étudiant universitaire technique tout à fait ordinaire qui souhaite tester la force de ses connaissances accumulées. Conquête Spring Boot - 1Je ne nie en aucun cas la présence éventuelle d'impolitesse dans le code ou la méthode de réflexion ci-jointe, et j'accueille favorablement les critiques constructives, car c'est grâce aux « bosses et contusions » qu'il est possible d'évoluer dans une direction professionnelle. De plus, je ne prétends pas du tout être une « panacée » pour résoudre les conditions données et j'omets délibérément des fragments individuels du programme, laissant ainsi l'importance clé d'aborder un sujet relativement complexe sans la moindre conséquence pour le système nerveux. C’est vrai, c’est imprudent de nier une évidence : c’était dur pour moi et absolument rien n’était clair jusqu’à un certain moment. Et si vous ressentez des sentiments similaires dès la première rencontre avec la tâche, alors « Bienvenue ! Écrivons une application Web dans Spring Boot en utilisant une analogie simplifiée d'un test d'entrée en stage utilisant un moteur de modèle Thymeleafet querydes requêtes vers un serveur MySQL local pour filtrer le tableau d'informations entrant. Alors, commençons!

Démarrage de printemps. De quel genre d'animal s'agit-il et comment le cuisiner ?

En bref et de manière concise, il s'agit d'un excellent outil de Pivotel pour gagner un temps précieux dans le processus de création d'une application, éliminant le besoin de connecter directement des bibliothèques tierces, d'écrire un canevas de cartographie impressionnant et des servlets. Il suffit d'utiliser le builder Spring Initializr , intégré à IntelliJ IDEA Ultimate Edition (File - New - Project... - Spring Initializr) ou situé sur le service web start.spring.io , en spécifiant les packages à inclure parmi un large éventail de des offres.
Conquête Spring Boot - 2
Suite aux spécifications techniques avancées, nous utiliserons le gentleman’s set, standard pour créer une application web simple utilisant la base de données MySQL :
  • WEB est le composant principal pour développer une application Web, comprenant un serveur Apache Tomcat local à l'adresse standard localhost:8080 et le framework universel Spring MVC.

  • DevTools - utilisé pour redémarrer rapidement une application dans une JVM chaude lorsque des modifications sont détectées dans le code ou les modèles compilés ; De plus, cela libère Thymeleaf de vider le cache si le moteur sélectionné est inclus dans le projet.

  • JPA est une technologie nécessaire pour travailler avec des bases de données et fournit un mappage objet-relationnel des objets Java, fournit une API ( Hibernate dans notre cas) pour gérer, enregistrer et récupérer des entités.

  • Thymeleaf (Moustache, AngularJS, Vaadin et au-delà) - moteur de modèles pour la visualisation d'applications ; Grâce à ma relative familiarité avec les principes du html, j'ai choisi Thymeleaf, qui a propulsé le langage au rang de pierre angulaire du monde.

  • MySQL - connecte les pilotes Java Database Connectivity pour exécuter des requêtes SQL sur la base de données.
Après la sélection finale des composants et la création, nous obtenons une architecture d'application Web ordinaire avec des répertoires prêts à être remplis davantage. Les fragments permettant d'interagir avec la partie visuelle, qu'il s'agisse de styles graphiques CSS, de pages HTML standard ou de fonctionnalités JavaScript, doivent être situés dans « ressources », et le composant back-end, par conséquent, est censé être placé dans « java ». Nous devons également prêter attention au fichier pom.xml dans la plage racine, qui stocke la structure du projet et les dépendances entre les composants. Si vous souhaitez étendre davantage les fonctionnalités avec des packages supplémentaires ou supprimer des éléments inutiles, vous devez effectuer des manipulations entre les balises <dependencies></dependencies>selon une méthode similaire.
Conquête Spring Boot - 3

Premiers pas vers un grand avenir

Ensuite, une question assez intéressante et tout à fait logique se pose : « Que faire maintenant ? Comment cela fonctionnera-t-il ? Le programme est construit sur les principes de Model-View-Controller : il organise la lecture des entités de la base de données connectée (Model) et s'affiche dans l'interface utilisateur avec des contrôles (View) ; la communication entre les composants et l'exécution des actions en fonction des requêtes transmises s'effectuent grâce au Contrôleur. C'est la création d'éléments clés qui sert de point de référence pour un développement continu. Afin d'éviter une pente glissante et de maintenir le respect de vos camarades dans le domaine de travail, vous devez placer les composants dans les répertoires appropriés (par exemple, placer le fichier Controller dans le dossier contrôleurs de la branche « java ») et conserver soigneusement ordre sur le lieu de travail.

L'essence est une petite partie d'un grand mécanisme

Ou en d’autres termes, notre Modèle selon les conditions posées dans le problème. En partant du sujet de discussion et en revenant au projet d'introduction, nous pouvons affirmer avec confiance qu'il existe des différences minimes entre les tâches et adhérer au concept moyen lors d'un examen plus approfondi. Disons, des notes dans un cahier, comprenant :
  • Numéro d'identification pour déterminer l'emplacement dans le flux général ;
  • Un message texte d'un certain nombre de caractères ;
  • La date à laquelle l'utilisateur l'a ajouté à la liste générale ;
  • Une variable booléenne pour déterminer « Fait ou pas fait » (« Lu ou non lu »).
Par conséquent, créons une classe Note dans un répertoire appelé « entité » et ajoutons les champs appropriés :
@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 autre écart par rapport au sujet de discussion pour une meilleure compréhension de ce qui se passe d'un point de vue théorique. La connexion entre les composants dans Spring est spécifiée par des annotations - des pointeurs spéciaux devant les objets, dont chacun joue un rôle spécifique dans le mécanisme et commence par le symbole « @ ». L'annotation @Entity indique à Spring Boot que les données de classe suivantes appartiennent à « l'entité », et @Id et @GeneratedValue spécifient le champ sélectionné comme identifiant avec génération automatique d'un itérateur lors du traitement d'un tableau d'informations. J'omets délibérément d'ajouter les Getter et Setter standards pour augmenter la compacité du format visuel. Ensuite, compte tenu de l'utilisation d'une base de données pour stocker les enregistrements, nous passons à l'étape suivante du développement de l'application : nous allons créer l'interface NoteRepository dans le répertoire « repository », élément de connexion dans la chaîne d'échange, et hériter du plus référentiel approprié pour des travaux ultérieurs, indiquant l'entité stockée et l'itérateur entier auquel accéder.
public interface NoteRepository extends JpaRepository<Note, Integer> {
}
En fait, c'est tout. Bref et concis. Désormais, Spring Boot utilisera le composant créé pour organiser les interactions avec la base de données. Il existe relativement de nombreux types de référentiels existants avec un potentiel d'action variable. JpaRepository se situe au sommet de l'échelle et a le plus de potentiel, y compris CrudRepository et PageAndSortingRepository en dessous. Nous n’irons pas plus loin et ne nous éloignerons pas du sujet, car certaines subtilités se trouvent sur le site de Pivotel dans la documentation technique. Désormais, après avoir implémenté l'image des données et spécifié les méthodes de communication côté application, vous devez faire attention à la création d'une base de données MySQL dans l'environnement externe approprié « MySQL Workbench », préinstallé sur la plate-forme de bureau dans un assemblage du développeur officiel. avec des packages supplémentaires pour créer un serveur local :
Conquête Spring Boot - 4
Ensuite, en suivant les instructions de l'environnement après avoir cliqué sur l'icône avec le serveur local actuel dans la fenêtre principale, nous créons un diagramme de table en fonction des champs de notre entité (Remarque) et le remplissons avec les données appropriées. Il est nécessaire de clarifier séparément les subtilités du dialecte MySQL, qui nécessitent une attention urgente pour obtenir le résultat souhaité :
  • Il n’existe pas de type booléen distinct en tant que tel. Toutes les actions de traitement de demande convertiront « vrai » ou « faux » en valeur binaire « 1 » ou « 0 », respectivement ;
  • La date est entièrement stockée dans le type Timestamp. Si vous utilisez Date, qui est familier à l'essentiel, vous devrez vous limiter uniquement à la position dans le calendrier.
Conquérir Spring Boot - 5
Après l'achèvement final des étapes préparatoires, nous indiquons « MySQL Workbench » pour envoyer les données au serveur local en cliquant sur l'icône « éclair » dans la barre d'outils. Désormais, si l'ajout des informations a été effectué correctement, nous pouvons revenir en toute confiance à notre IDE natif pour poursuivre le développement en ajoutant la configuration actuelle de la base de données à application.properties (généralement situé dans le répertoire « ressources ») :
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
Et enfin lier l'entité Note à MySQL à l'aide d'annotations. @Table indique l'utilisation d'une table avec le nom et le schéma sélectionnés, et @Column indique que les variables appartiennent à un champ spécifique.
@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;
   }
}

Vue ou interface utilisateur

Hélas, nous pouvons affirmer sans risque ce qui suit : « La visualisation de l'application deviendra la principale pierre d'achoppement sans la moindre connaissance théorique ou pratique. » Pour être franc, le composant front-end a occupé une quantité incroyable de travail total et m'a énervé en toute confiance pendant une longue période de temps. Mais grâce à l’étonnante simplicité de Thymeleaf, il a été possible de trouver un compromis convenable après une série de défaites enchanteresses. Une discussion plus approfondie portera sur les subtilités de l'utilisation du moteur sélectionné, bien que le concept général adhère à une position similaire. La technique principale est la possibilité d'utiliser le HTML le plus pur et d'assembler l'affichage final à partir de fragments individuels pour éviter les répétitions multiples de sections identiques. Supposons que l'architecture de l'interface utilisateur se compose d'une page principale composée d'une barre de navigation avec des contrôles (ajout d'une nouvelle entrée, retour à la page principale) et d'un tableau dynamique pour afficher les entités triées selon le moment où la note a été ajoutée dans un ordre croissant (ASC) ou décrémentation (DESC). Prenons comme position standard l'affichage de tous les enregistrements par ordre croissant. Selon la politique hiérarchique du moteur de template sélectionné, les éléments de visualisation des composants doivent être situés sur la branche « templates » dans le répertoire « ressources ». Par conséquent, les manipulations ultérieures avec les composants tiennent compte des conditions proposées. Créons une page principale avec le nom « index » (ou tout autre nom selon vos préférences personnelles) sur un modèle html5. Par exemple:
<!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>
Et donc, décomposons les éléments clés de l’application finale. Thymeleaf utilise une syntaxe distincte pour indiquer l'utilisation de procédures et commence par le mot-clé « th: », le lien vers la bibliothèque avec lequel est nécessairement inclus dans la balise d'ouverture <html>.
<div th:if="${not #lists.isEmpty(notes)}">
L'opération "if" n'est absolument pas différente de la façon habituelle de faire les choses et vérifie l'attribut "notes" entrant pour la présence d'objets à afficher davantage. Il convient de mentionner séparément le chevauchement du sujet avec l'utilisation de Controller, en tenant compte de son utilisation pour organiser l'interaction du modèle et de la visualisation. De nombreux moments vagues se dessinent dans le futur, revenez en arrière si vous le souhaitez.
<head th:replace="operations/list :: notebook"></head>
L'opération « remplacer » indique le remplacement d'un « stub » ou d'un bloc actif par un fragment sélectionné de la page actuelle ou séparée - ce dernier cas est clairement observé dans l'exemple. Nous copions le fragment appelé « notebook » de « list.html » du répertoire « opérations » dans le <div></div> du fichier « index », remplaçant complètement le contenu dans la destination finale. Le sortant a le contenu suivant :
<!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>
Revenons à l'aperçu constructif et passons en revue les fonctions Thymeleaf utilisées dans l'ordre, en omettant la syntaxe HTML standard ou les styles graphiques utilisés, et en nous concentrant spécifiquement sur la compréhension du mécanisme du moteur de modèle.
<div th:fragment="notebook">
L'opération « fragment » précise le nom du fragment et permet d'utiliser le contenu du bloc pour la commande « replace ». De plus! Des utilisations multiples au sein d’une même page ne sont en aucun cas exclues, mettant là encore en avant l’analogie avec les procédures ou fonctions des langages de programmation.
<a th:href="@{'/sort/{sortDate}' (sortDate = 'ASC')}">
Un appel à l'annotation @PostMapping est utilisé dans le contrôleur avec le mappage « /sort/{sortDate} », où {sortDate} est l'attribut de direction de tri sortant. Quelque chose de similaire peut être vu dans le bloc suivant, qui ajoute un changement dynamique en fonction de la position de l'élément sélectionné par l'utilisateur dans la boucle d'itération :
<a th:href="@{'/edit/{id}'(id=${note.id})}">
<tr th:each="note : ${notes}">
L'énumération des valeurs est très similaire à l'utilisation familière d'un bloc for dans la syntaxe Java : la variable « note » prend l'élément actuel du tableau d'attributs d'entrée ${notes} — un tableau d'entités — et est utilisée pour modifier les valeurs. plus tard. Pour être franc, nous pourrions consacrer un article séparé à la liste du large éventail de fonctionnalités de Thymeleaf avec des exemples d'application pratique - le moteur de modèles est extrêmement simple et ne nécessite pas du tout d'apprendre un bagage impressionnant de syntaxe supplémentaire. Les fonctions décrites ci-dessus sont décrites dans la documentation technique sur le site officiel des développeurs et sont d'une importance capitale pour organiser la communication avec le back-end. Par conséquent, vous pouvez passer en toute confiance à la partie suivante et finale. Bien sûr, en attachant les composants restants de la visualisation dans un lien vers l'application terminée à la fin de l'article.

Contrôleur, administrateur dans une petite entreprise

"La pierre angulaire de l'architecture d'une application Web" - il n'y a peut-être aucun moyen de trouver une description plus précise de l'importance du composant Contrôleur dans l'organisation du travail du programme : la plupart des opérations sont effectuées précisément par l'élément de connexion entre le le modèle et la vue. Grâce aux mécanismes d'action de Spring Boot, vous pouvez utiliser en toute confiance les méthodes de mappage et de requête GET/POST sans le moindre problème, et vous connecter automatiquement au référentiel de données. Créons la classe NoteController dans un fichier séparé dans le répertoire « contrôleurs », en faisant encore une fois référence à l'utilisation de l'annotation appropriée :
@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 œil attentif peut remarquer un changement important dans la conception de l'architecture de l'application associé à l'ajout d'un service pour isoler la logique métier du travail avec le service de gestion de base de données. Les actions réalisées sont nécessaires pour augmenter la polyvalence du produit fini et offrir une large marge de modification des fonctionnalités de l'interface utilisateur sans qu'il soit nécessaire de modifier les méthodes de communication avec la base de données. La représentation standard ne se démarque en rien de la foule des représentations similaires : l'interface est située dans un répertoire séparé et est implémentée par une classe avec l'annotation @Service pour la détection 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();
   }
}
Revenons à l'examen du contrôleur et examinons les subtilités de l'organisation du travail à l'aide des méthodes Spring Boot. L'annotation @Autowired indique la nécessité de lier automatiquement un service à une variable spécifiée du type approprié et d'établir une connexion avec la base de données. Une plus grande attention doit être accordée à la façon dont la vue communique, indiquée par l'annotation @GetMapping("/"), qui renvoie une page nommée « index » lors de la réception d'un appel à localhost:8080. Vous pouvez utiliser une approche différente, en spécifiant la description étendue @RequestMapping(value = "/", method = RequestMethod.GET) ou en remplaçant le type de retour par un ModelAndView prêt à l'emploi. Cependant, selon l'état actuel de l'expérience dans l'application pratique, je ne remarque aucune différence fondamentale dans le résultat final et j'utilise l'option habituelle. Développons le contrôleur en ajoutant de nouveaux éléments à l'aide d'un onglet supplémentaire. Après que l'utilisateur clique sur un élément de la barre de navigation, @GetMapping("/new") est appelé et redirigé vers la page « nouvelle » depuis le répertoire « opérations », renvoyant un paramètre nommé « message » lors de la confirmation des données saisies à l'aide du bouton et redirection vers le bloc principal. La nécessité d'une correspondance complète du nom de la variable dans la fenêtre de saisie avec le nom de la valeur transférée nécessite une mention particulière.
<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:/";
}
Une technique similaire est utilisée pour mettre à jour un enregistrement. Après avoir cliqué sur le contrôle, le mappage @GetMapping("/edit/{id}") est appelé et l'identifiant de la chaîne URL est transféré, l'attribut « note » est ajouté avec une entrée pour une édition ultérieure. @RequestParam(value = "done", requirejs = false) boolean done) spécifiant une valeur spécifique joue un rôle clé dans l'utilisation de la case à cocher lors de l'utilisation du moteur de modèle Thymeleaf et est défini sur "false" par défaut.
@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:/";
}
Supprimer des éléments de la base de données est extrêmement simple et ne nécessite aucune manipulation significative en appelant la fonction de service appropriée en utilisant la valeur transmise :
@GetMapping("/delete/{id}")
public String delete(@PathVariable Integer id) {
   service.deleteNote(id);
   return "redirect:/";
}
Apportons maintenant de petits ajustements aux fragments finis et passons à une communication passionnante avec MySQL à l'aide de requêtes dans Spring Data JPA, en ajoutant séparément une fonction permettant de gérer un filtrage simple avant de fermer le contrôleur.
@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;
}

Requête si petite, mais si importante.

Il est gênant d'admettre que le filtrage des valeurs, contrairement aux attentes, s'est avéré être une autre pierre d'achoppement dans l'accomplissement de la tâche technique, surmontant avec confiance le seuil de complexité établi par la pagination - divisant le tableau de données en pages séparées d'une certaine taille pour un affichage ultérieur. Très probablement, la fatigue accumulée faisait des ravages, mais... l'inspiration est venue après une rencontre complètement accidentelle avec les requêtes Query.
public interface NoteRepository extends JpaRepository<Note, Integer> {
   List<Note> findAllByOrderByDateAsc();
   List<Note> findAllByOrderByDateDesc();
}
Spring Data JPA offre la possibilité de créer des requêtes de base de données très granulaires qui éliminent le besoin de trier les informations une fois reçues et offrent un large éventail de potentiels d'application. Par exemple:
List<Note> findAllByOrderByDateAsc();
La méthode sera convertie en requête SQL et affichera tous les enregistrements (findAll) triés (byOrder) par date (byDate) par ordre croissant (Asc). De plus, vous pouvez créer des combinaisons complexes et échantillonner dans de nombreux domaines avec une seule exigence. Dites, sélectionnez tous les enregistrements (findAll) terminés (byDoneTrue) dans l'ordre (byOrder) décroissant (Decs) par valeur de date (byDate) :
Page<Note> findAllByDoneTrueOrderByDateDesc(Pageable pageable);

Conclusion ou autre confession d'un programmeur novice

Tous! Vous pouvez lancer l'application web en toute sécurité en utilisant la combinaison Shift+F10 ou en cliquant sur l'icône correspondante. Spring Boot construira le programme sur Apache Maven et installera un serveur Apache Tomcat local sur localhost:8080. Il ne vous reste plus qu'à suivre le lien dans n'importe quel navigateur.
Conquête Spring Boot - 6
Et bien sûr, développez une méthodologie pour répondre à d’autres exigences commerciales. Le potentiel de l'application est limité par les efforts, l'ingéniosité et l'imagination du développeur.
Conquête Spring Boot - 7
Étant franc et attentif au chemin parcouru, je suis encore et toujours convaincu de la justesse de la direction choisie et réalise les avantages d'étudier sur le portail pédagogique JavaRush. Grâce à une variété de tâches pratiques, il a été possible de retrouver l'intérêt séduisant pour l'apprentissage de la programmation, qui avait été complètement supprimé dans le programme obsolète et étonnamment ennuyeux d'un établissement d'enseignement supérieur d'une direction similaire. Quatre mois d'étude active de matériel dans la pile technologique back-end ont investi beaucoup plus de connaissances que des années entières de participation à des conférences et à des cours de laboratoire. Croyez-le ou non. Je vous souhaite de ne pas céder aux difficultés d'aborder une matière complexe, car c'est en surmontant les obstacles que l'on devient meilleur et se développe professionnellement et personnellement. J'espère que cette petite histoire m'a aidé à découvrir de nouvelles idées pour utiliser l'outil étonnant appelé SpringBoot. PSGithub . _
Commentaires
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION