[JAVA] J'ai créé un système d'exemple MVC simple à l'aide de Spring Boot

Spring Boot pour la première fois

J'ai l'impression d'être en retard, mais j'ai commencé à étudier Spring Boot. La plupart des entreprises utilisaient leurs propres frameworks et systèmes Struts2, mais les vulnérabilités qui faisaient du bruit ces jours-ci et la tendance aux microservices, et quand j'ai participé au JJUG CCC 2017 Spring au printemps, partout Spring Boot J'ai décidé d'utiliser Spring Boot car il y a beaucoup d'histoires à ce sujet, et il y a beaucoup d'informations et de livres sur le net.

En pensant à l'utiliser, j'ai réalisé que c'était pratique car je pouvais le démarrer immédiatement et ajouter des fonctions facilement. Si vous lisez le livre, regardez le document officiel et recherchez les informations sur le net, un système simple sera complété en un rien de temps. Cependant, il y avait quelques points addictifs ... Il est normal de déplacer les fonctions de manière appropriée, mais j'ai décidé de créer un système d'échantillonnage simple et de l'étudier.

La source créée est publiée sur github, donc j'espère qu'elle sera utile pour ceux qui commencent à partir de maintenant. https://github.com/ewai/spring-boot-mvc-template

TODO restant

Nous prévoyons de le créer et de le mettre à jour de temps en temps.

J'ai fait un exemple de système comme celui-ci

Présentation du système

Système de gestion des informations sur les livres (Système qui effectue une gestion simple du maître)

Vous devez vous connecter pour travailler avec les données Seul l'administrateur peut s'inscrire / mettre à jour ← L'autorité TODO ne fonctionne pas bien

Diagramme de transition d'écran

image.png

En dehors de l'écran supérieur, il ne peut être affiché que lorsqu'il a été authentifié.

Jetons un coup d'œil à la démo pour le moment

https://ewai.info/sbt/

utilisateur mot de passe Autorité
sbt sbt Autorité utilisateur normale (système de référence uniquement)
admin admin Droits d'administrateur (les données peuvent être mises à jour)

Structure du répertoire

src
  ├─main
  │  ├─java
  │  │  └─info
  │  │      └─ewai
  │  │          └─sbmt
│ │ ├─config (paramètres relatifs à la sécurité, etc.
  │  │              ├─domain (entity,référentiel etc.
  │  │              ├─service  (service
  │  │              └─web (controller, validator
  │  │                  └─form (form
  │  └─resources
  │      ├─static
  │      │  ├─css
  │      │  └─img
│ └─ modèles (modèles de feuilles de thymel
  └─test
      └─java
          └─info
              └─ewai
                  └─sbt (TODO Junit

Il a une configuration de package standard. Il semble que vous deviez spécifier @ComponentScan ("xxx") s'il ne respecte pas la norme. Je l'ai fait librement sans le savoir au début.

Documentation officielle http://docs.spring.io/spring-boot/docs/1.5.6.RELEASE/reference/htmlsingle/#using-boot-using-the-default-package

Bibliothèque définie dans build.gradle

build.gradle


~
        springBootVersion = '1.5.6.RELEASE'
~
    compile("org.webjars:jquery:3.2.1")
    compile("org.webjars:bootstrap:3.3.7")

    compile('org.springframework.boot:spring-boot-starter-actuator')
    compile('org.springframework.boot:spring-boot-starter-data-jpa')
    compile('org.springframework.boot:spring-boot-starter-thymeleaf')
    compile('org.springframework.boot:spring-boot-starter-security')
    compile('org.springframework.boot:spring-boot-starter-jetty')
    compile('org.thymeleaf.extras:thymeleaf-extras-springsecurity4:3.0.2.RELEASE')
    runtime('mysql:mysql-connector-java:5.1.43')
    testCompile('org.springframework.boot:spring-boot-starter-test')
    testCompile('org.springframework.security:spring-security-test')

source github build.gradle

Par défaut, tomcat est utilisé, mais Jetty est utilisé car l'entreprise utilise Jetty.

environnement

Environnement de développement

Bibliothèque

Serveur d'application

DB

Environnement DB

Sur la base du MySQL officiel de Docker Hub, j'ai créé un Dockerfile qui enregistre automatiquement le DDL et les données de test. Si vous construisez docker à partir de là et créez une image, elle contiendra DDL et des données de test. Depuis le démarrage de MySQL, vous pouvez démarrer le système immédiatement.

Ce qui suit est une procédure de construction assez approximative.


Première fois

#Cloner ou télécharger ceci
https://github.com/ewai/docker-spring-boot-template-mysql

Ci-dessous, exécutez la commande

#Création d'image
docker build -t sbtdb .

#Création de conteneurs
docker run -d --name sbtdb -p 3306:3306 sbtdb

Il devrait maintenant fonctionner.
docker ps -a

OK si l'état est UP.
* DDL et les données de test ont déjà été saisies.


Après la deuxième fois

Vérifiez l'état
docker ps -a
 
Démarrez le conteneur si le statut est Quitté
docker start sbtdb

Lorsque le statut devient UP, vous pouvez vous connecter, alors essayez de vous connecter avec MySQL Workbench. sbtdb

Informations de connexion
jdbc:mysql://localhost/sbtdb

Utilisateur: sbt
Mot de passe: sbt

Exemple) MySQL Workbench image.png

Essayez de bouger

image.png

Description autour de la source

Authentification de connexion

Sources connexes

build.gradle


+ compile('org.springframework.boot:spring-boot-starter-security')

Active Spring Security.

Ajoutez simplement ceci et l'authentification de base sera appliquée automatiquement. J'ai fait cette partie parce que je veux authentifier la connexion.

SecurityConfig.java


package info.ewai.sbmt.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.authentication.configurers.GlobalAuthenticationConfigurerAdapter;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;

import info.ewai.sbmt.service.UserService;

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    public void configure(WebSecurity web) throws Exception {
        web.ignoring().antMatchers("/img/**", "/css/**", "/js/**", "/webjars/**");
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .antMatchers("/").permitAll()
                .anyRequest().authenticated()
                .and()
            .formLogin()
                .loginPage("/login")
                .usernameParameter("username")
                .passwordParameter("password").permitAll().and()
            .logout()
                .logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
                .logoutSuccessUrl("/")
                .deleteCookies("JSESSIONID")
                .invalidateHttpSession(true).permitAll();
    }

    @Configuration
    protected static class AuthenticationConfiguration extends GlobalAuthenticationConfigurerAdapter {
        @Autowired
        UserService userService;

        @Override
        public void init(AuthenticationManagerBuilder auth) throws Exception {
            auth.userDetailsService(userService).passwordEncoder(new BCryptPasswordEncoder());
        }
    }
}

SimpleController.java


    @RequestMapping(value = "/login", method = RequestMethod.GET)
    public String login() {
        return "login";
    }

C'est un contrôleur qui passe uniquement à la page de connexion. Je pense que j'ai trouvé que ce genre de chose ne peut être fait que par réglage, mais j'ai oublié, alors Une fois, je les ai rassemblés dans SimpleController.java.

UserService.java


@Component
public class UserService implements UserDetailsService {

    @Autowired
    private UserRepository userRepository;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        if (StringUtils.isEmpty(username)) {
            throw new UsernameNotFoundException("Username is empty");
        }
        User user = userRepository.findByUsername(username);
        if (user == null) {
            throw new UsernameNotFoundException("User not found for name: " + username);
        }
        return user;
    }
}

UserRepository.java


public interface UserRepository extends JpaRepository<User, Long> {
    public User findByUsername(String username);
}

Autre info.ewai.sbmt.domain.User info.ewai.sbmt.domain.Authorities login.html

J'ai implémenté UserDetails et l'ai fait presque comme standard, Il peut être possible de l'utiliser en convertissant et en synchronisant les informations utilisateur du système interne.

Utilisateurs / privilèges pouvant être utilisés dans l'exemple de système

Entrée de données par défaut

utilisateur mot de passe Autorité Contenu de l'autorisation
sbt sbt ROLE_USER Autorité utilisateur normale (système de référence uniquement)
admin admin ROLE_ADMIN Droits d'administrateur (les données peuvent être mises à jour)
admin admin ACTUATOR Autorisation d'utiliser Spring Boot Actuator

Écran de recherche

BookController.java


    @RequestMapping(value = "/book", method = RequestMethod.GET)
    public String index(Model model) {
        List<Book> list = this.bookservice.findAll();
        model.addAttribute("booklist", list);
        model.addAttribute("bookForm", new BookForm());
        return "book";
    }

BookService.java


    public List<Book> findByBookNameLikeAndTagLike(String bookName, String tag) {
        if (StringUtils.isEmpty(bookName) && (StringUtils.isEmpty(tag))) {
            return this.findAll();
        }
        return this.bookRepository.findByBookNameLikeAndTagLike("%" + bookName + "%", "%" + tag + "%");
    }

BookRepository.java


public interface BookRepository extends JpaRepository<Book, Long> {

    public List<Book> findByBookNameLikeAndTagLike(String bookName, String tag);
}

Si vous spécifiez Like dans la méthode, vous pouvez effectuer une recherche ambiguë, j'ai donc essayé de l'utiliser. Je pensais que% serait ajouté automatiquement au paramètre, mais je ne pouvais pas, alors j'ai ajouté%. Il semble que vous puissiez facilement paginer avec des fonctions standard, mais je ne l'ai pas fait pour le moment.

En fait, je pense qu'il est possible de créer du SQL compliqué, donc je pense que je vais créer un référentiel personnalisé et écrire JPQL et SQL.

@PersistenceContext
EntityManager entityManager;
 ~
Query query = entityManager.createQuery("from Book where id = :id")

Écran d'édition

Vérifiez l'entrée

Je crée un Varidator personnalisé et je le vérifie.

BookValidator.java


@Component
public class BookValidator implements Validator {

    @Autowired
    BookService bookService;

    @Override
    public boolean supports(Class<?> clazz) {
        return BookForm.class.isAssignableFrom(clazz);
    }

    @Override
    public void validate(Object target, Errors errors) {

        // required check
        ValidationUtils.rejectIfEmptyOrWhitespace(errors, "bookName", "field.required");

        // TODO form check
        // BookForm form = BookForm.class.cast(target);
        // errors.rejectValue("field", "errorCode");

        // global message
        if (errors.hasErrors()) {
            errors.reject("input.error");
        }
    }
}

BookForm.java


Presque livre.Identique à l'entité Java

Des vérifications simples telles que des vérifications obligatoires et des vérifications de taille peuvent être effectuées en annotant le formulaire. Il est possible de vérifier, mais je voulais réutiliser Form et je ne voulais pas distribuer le chèque à Form et Validator Les chèques sont regroupés dans Validator.

Le message d'erreur est défini.

Le message d'erreur se trouve dans messages_ja.properties.

BookController.java


    @RequestMapping(value = "/book/save", method = RequestMethod.POST)
    public String save(@Valid @ModelAttribute BookForm bookForm, BindingResult result, Model model) {
        logger.info("save/" + bookForm.getBookId());

        if (result.hasErrors()) {
            return "book-edit";
        }

        try {
            this.bookservice.save(new Book(bookForm));
        } catch (Exception e) {
            result.reject("exception.error");
            result.reject("using defaultMessage", e.toString());
            return "book-edit";
        }

        return "book-complete";
    }

new Book(bookForm) Je passe de la forme à l'entité à. N'y a-t-il pas un bon moyen?

// Afficher le message global bindingResult.reject("errorCode")

// Afficher un message d'erreur pour chaque champ bindingResult.reject("field", "errorCode")

Dans Controller, définissez le rejet dans BindingResult et Dans Validator, définissez le rejet dans Erreurs.

@Valid @ModelAttribute BookForm bookForm, BindingResult result

Il semble être une règle d'écrire la définition de la partie argument dans cet ordre. Mettre le BindingResult au premier plan entraînera une erreur. J'y suis entré un peu.

Si @Valid est ajouté, il sera appelé dans un état qui a été vérifié à l'avance par Validator. Je ne vérifie donc que result.hasErrors () pour les erreurs.

Processus de mise à jour

BookService.java


    @Transactional
    public Book save(Book book) {
        return this.bookRepository.save(book);
    }

En fait, je pense qu'un traitement plus compliqué arrivera, mais il s'agit simplement d'économiser. Si @Transactional est ajouté, il sera annulé lorsqu'une exception se produit. Il semble que les exceptions non contrôlées (RuntimeException, etc.) soient annulées.

J'ai été autorisé à faire référence) http://qiita.com/NagaokaKenichi/items/a279857cc2d22a35d0dd

J'ai pensé à ajouter @Transactional à la méthode Controller, En raison du contrôle de l'écran, l'exception est interceptée et traitée, mais elle n'a pas été annulée, donc Je me demande si toute la logique métier doit être attachée ici en la mettant en service J'ai pensé.

Bien sûr, si c'est compliqué, il semble que vous allez retirer Transaction d'EntityManager et la contrôler, Je me demande s'il est acceptable d'utiliser des annotations comme base ou non.

Standardisation des modèles Thymeleaf

S'il y a un changement dans la source qui est couramment utilisée sur chaque écran, toutes les pages doivent être changées ... J'ai partagé la source comme.

Ce qui suit est une source courante.

common.html


<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org"
      xmlns:sec="http://www.springframework.org/schema/security">
<head>
<!-- common head -->
<th:block th:fragment="head"><meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css"
          th:href="@{/webjars/bootstrap/3.3.7/css/bootstrap.min.css}" rel="stylesheet" />
    <link href="/css/common.css"
          th:href="@{/css/common.css}" rel="stylesheet" />
    <script src="http://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"
            th:src="@{/webjars/jquery/3.2.1/jquery.min.js}"></script>
    <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"
            th:src="@{/webjars/bootstrap/3.3.7/js/bootstrap.min.js}"></script></th:block>
</head>
<body>
    <div th:fragment="header" class="container" id="header">
        <h1><a href="/">Book</a></h1>
        <p style="text-align:right;" th:if="${#httpServletRequest.remoteUser != null}">Hello 
          <span th:text="${#httpServletRequest.remoteUser}" /> | 
          <a href="/logout">Se déconnecter</a>  | 
          <a href="https://github.com/ewai/spring-boot-mvc-template" target="_blank" alt="spring-boot-mvc-template"><img src="img/mark-github.svg" /></a>
        </p>
    </div>

    <div th:fragment="footer" class="container" id="footer">
        <ul>
            <li><a href="https://github.com/ewai/spring-boot-mvc-template" target="_blank"><img src="img/mark-github.svg"  alt="spring-boot-mvc-template"/></a> <a href="https://github.com/ewai/spring-boot-mvc-template">spring-boot-mvc-template</a></li>
            <li><a href="https://github.com/ewai/docker-spring-boot-template-mysql">docker-spring-boot-template-mysql</a></li>
        </ul>
    </div>

</body>
</html>

Le modèle se trouve à l'intérieur de la balise ** th: fragment **. J'en ai fait trois.

Puisqu'il s'agit d'un fichier commun, j'ai pensé que je devrais le mettre dans un répertoire différent, mais il n'a pas été lu, il est donc placé directement sous les modèles.

book.html


<head>
    <th:block th:include="common::head"></th:block>
    <title>Book Search</title>
</head>
<body>
    <th:block th:replace="common::header"></th:block>
  ~~~contenu~~~
    <th:block th:replace="common::footer"></th:block>
</body>
</html>

J'utilise chaque page comme ça.

L'inconvénient est que vous ne pouvez pas vérifier la conception au format HTML. Personnellement, je lance l'application et la vérifie en l'exécutant, Il vaut peut-être mieux ne pas l'utiliser lorsque le concepteur le crée avec du html pur et le vérifie.

Autour de l'autorité

Lors de l'affichage uniquement pour un utilisateur spécifique

build.gradle


   + compile('org.thymeleaf.extras:thymeleaf-extras-springsecurity4:2.1.3.RELEASE')

Au début, j'ai ajouté ce qui suit, mais cela n'a pas fonctionné (sec: authorize = "hasRole ('ROLE_ADMIN')" était affiché en html tel quel) et cela a fonctionné lorsque j'ai abaissé la version.

compile('org.thymeleaf.extras:thymeleaf-extras-springsecurity4:3.0.2.RELEASE')

Lors de l'affichage uniquement des utilisateurs autorisés

index.html


<li class="list-group-item" sec:authorize="hasRole('ROLE_ADMIN')"><a href="/book/create" th:href="@{/book/create}" class="btn btn-link" id="link">Inscription au livre</a></li>

Ajouté pour que sec puisse être utilisé

index.html


      xmlns:sec="http://www.springframework.org/schema/security">

https://github.com/thymeleaf/thymeleaf-extras-springsecurity

Faites-en un fichier exécutable

build.gradle


springBoot {
    executable = true
}

Si vous ajoutez ceci et que vous le construisez, il devient un fichier jar exécutable. Qu'est-ce que ça veut dire?

./spring-boot-mvc-template-0.0.1-SNAPSHOT.jar

Il est possible de l'exécuter ainsi.

Il peut être utilisé lorsque vous souhaitez le démarrer automatiquement au démarrage du système d'exploitation.

Pour centos7

/etc/systemd/system/sbt.service


[Unit]
Description=sbt
After=syslog.target

[Service]
User=sbtuser
ExecStart=/xxx/xxx/spring-boot-mvc-template-0.0.1-SNAPSHOT.jar
SuccessExitStatus=143

[Install]
WantedBy=multi-user.target

cmd


systemctl enable sbt.service

Maintenant, il démarrera automatiquement au démarrage du système d'exploitation.

Spring Boot Actuator

build.gradle


   + compile('org.springframework.boot:spring-boot-starter-actuator')

Je l'ai ajouté car vous pouvez facilement vérifier l'état du serveur simplement en ajoutant ceci. Un utilisateur qui a l'autorité "ACUTIATOR" dans getAuthorities () de User (UserDetails) Il semble que vous ne puissiez pas le voir tant que vous ne vous êtes pas connecté. Cette fois, l'utilisateur admin a cette autorisation, vous pouvez donc la voir en vous connectant en tant qu'admin / admin.

http://localhost:8080/health

/health


{"status":"UP","diskSpace":{"status":"UP","total":247762329600,"free":125178765312,"threshold":10485760},"db":{"status":"UP","database":"MySQL","hello":1}}

Vous pouvez voir que le serveur est actif, que la base de données est active et que l'espace disque est toujours libre.

Quand j'ai essayé de me référer à lui comme un utilisateur sans autorité "ACUTIATOR", Puisque {"status": "UP"} est renvoyé, vous pouvez voir si le serveur est opérationnel.

http://localhost:8080/env Comme prévu, si vous ne disposez pas des droits "ACUTIATOR", vous ne pouvez pas faire référence au système de variables d'environnement. J'ai une erreur.

Access is denied. User must have one of the these roles: ACTUATOR

http://localhost:8080/mappings Il semble qu'un document de conception puisse être réalisé.

/mappings


   "{[/book],methods=[GET]}":{  
      "bean":"requestMappingHandlerMapping",
      "method":"public java.lang.String info.ewai.sbmt.web.BookController.index(org.springframework.ui.Model)"
   },
   "{[/book/edit/{bookId}],methods=[GET]}":{  
      "bean":"requestMappingHandlerMapping",
      "method":"public java.lang.String info.ewai.sbmt.web.BookController.edit(info.ewai.sbmt.web.form.BookForm,org.springframework.validation.BindingResult,java.lang.Long,org.springframework.ui.Model)"
   },
   "{[/book/save],methods=[POST]}":{  
      "bean":"requestMappingHandlerMapping",
      "method":"public java.lang.String info.ewai.sbmt.web.BookController.save(info.ewai.sbmt.web.form.BookForm,org.springframework.validation.BindingResult,org.springframework.ui.Model)"
   },

Il y aura probablement également d'autres points de terminaison. http://qiita.com/MariMurotani/items/01dafd2978076b5db2f3

Il semble que vous puissiez le personnaliser et changer le port de l'URL, mais laissez-le tel quel.

Informations qui ont servi de référence

Spring Framework Reference Documentation 4.3.0.RELEASE http://docs.spring.io/spring/docs/4.3.0.RELEASE/spring-framework-reference/htmlsingle/

Spring Boot Reference Guide 1.5.6.RELEASE http://docs.spring.io/spring-boot/docs/1.5.6.RELEASE/reference/htmlsingle/

Présentation détaillée du développement d'applications Spring Java avec Spring Framework Il a été utile d'expliquer et de comprendre les fonctions de Spring en général. Il y a aussi un peu écrit sur Spring Boot.

Introduction à la programmation Spring Boot

finalement

C'est une botte de printemps qui est très facile à fabriquer, mais il y avait des moments où je ne connaissais pas les règles. Cependant, j'ai estimé que c'était relativement facile à résoudre en raison de l'abondance d'informations sur les documents officiels, les livres et Internet. Cette fois, j'ai fait un système d'échantillonnage simple, donc je pense qu'il y aura divers essais, erreurs et addictions lorsque je fais un système pratique, mais j'ai senti que j'aimerais l'utiliser. Merci à toutes les personnes qui ont publié diverses informations dans des livres et en ligne.

Recommended Posts

J'ai créé un système d'exemple MVC simple à l'aide de Spring Boot
J'ai créé un formulaire de recherche simple avec Spring Boot + GitHub Search API.
J'ai fait une simple fonction de recommandation.
[Ruby] J'ai créé un simple client Ping
Un débutant Java a essayé de créer une application Web simple à l'aide de Spring Boot
Étapes pour créer une application chameau simple avec les démarreurs Apache Camel Spring Boot
[LINE BOT] J'ai créé un Ramen BOT avec Java (Maven) + Heroku + Spring Boot (1)
Créez une application de recherche simple avec Spring Boot
Créez une application Spring Boot à l'aide d'IntelliJ IDEA
[Rails] J'ai créé une fonction de brouillon en utilisant enum
J'ai fait un exemple de la façon d'écrire un délégué dans Swift UI 2.0 à l'aide de MapKit
Déléguez le motif entre les vues. J'ai également fait une transition de page d'exemple en utilisant NavigationLink.
J'ai fait un jeu de problèmes de calcul simple en Java
[Compatible JUnit 5] Ecrire un test en utilisant JUnit 5 avec Spring boot 2.2, 2.3
Implémentez une API Rest simple avec Spring Security avec Spring Boot 2.0
J'ai créé un serveur et un client Restful au printemps.
[Introduction à Spring Boot] Soumettez un formulaire à l'aide de thymeleaf
Créez un site de démonstration simple avec Spring Security avec Spring Boot 2.1
J'ai écrit un test avec Spring Boot + JUnit 5 maintenant
J'ai créé une application de chat.
Essayez d'utiliser Spring Boot Security
Je n'ai pas compris Spring Boot depuis un mois
Un exemple CRUD simple utilisant Java Servlet / JSP et MySQL
J'ai essayé de démarrer avec Swagger en utilisant Spring Boot
Implémentez une API Rest simple avec Spring Security & JWT avec Spring Boot 2.0
J'ai créé un Dockerfile pour démarrer Glassfish 5 en utilisant Oracle Java
Implémentez un serveur API Web REST simple avec Spring Boot + MySQL
J'ai essayé d'imprimer un formulaire avec Spring MVC et Jasper Reports 1/3 (paramètres Jasper Reports)
J'ai créé une interface de ligne de commande avec WinMerge Plugin en utilisant JD-Core
[Rails] J'ai créé une mini-application de calendrier simple avec des spécifications personnalisées.
J'ai essayé d'imprimer un formulaire avec Spring MVC et Jasper Reports 3/3 (contrôle Spring MVC)
Comment créer un hinadan pour un projet Spring Boot à l'aide de SPRING INITIALIZR
02. J'ai créé une API pour me connecter de Spring Boot à MySQL (My Batis)
J'ai essayé de me connecter à MySQL en utilisant le modèle JDBC avec Spring MVC
Intégré dans Spring Boot à l'aide d'un fichier de définition de bean nommé application.xml
Exemple de code pour le test unitaire d'un contrôleur Spring Boot avec MockMvc
J'ai essayé de créer une application simple en utilisant Dockder + Rails Scaffold
Guide de démarrage de Spring Boot [Utilisation d'un service Web RESTful]
Exécutez un modèle simple réalisé avec Keras sur iOS à l'aide de CoreML
J'ai essayé d'utiliser Spring + Mybatis + DbUnit
Tutoriel Spring Boot à l'aide de l'authentification Spring Security
J'ai créé une application shopify @java
J'ai créé une interface graphique avec Swing
Spring Boot: exemple de projet d'API Restful
Un exemple simple de rappels en Java
J'ai essayé Flyway avec Spring Boot
J'ai créé une application correspondante (application Android)
J'ai créé un outil de génération package.xml.
[Android] J'ai créé une application de podomètre.
J'ai essayé de créer une simple application Android de reconnaissance faciale en utilisant OpenCV
J'ai essayé d'imprimer un formulaire avec Spring MVC et Jasper Reports 2/3 (création de modèle de formulaire)
Déployer automatiquement des applications Web développées en Java à l'aide de Jenkins [Spring Boot App Edition]
[Spring Boot] Je suis tombé sur un test du nombre d'appels de méthode (framework Spock)
Qu'est-ce qu'un fichier .original Spring Boot?
Créez un lot à la demande simple avec Spring Batch
Un simple échantillon d'ArBiMap (carte bidirectionnelle)
Essayez d'utiliser Spring Boot avec VS Code
J'ai fait une mort risquée avec Ruby