Kotlin+SpringBootでアプリを作成してみた【Crud Web app】

## spring.initializr でプロジェクトを作成する

(1) ブラウザを開き、(https://start.spring.io/) を入力し、開く
(2) 下記を入力し、Dependenciesで下記を選択し、『GENERATE』ボタンを押す

- Project: Maven
- Language: kotlin
- SpringBoot: 3.3.6

- Group: br.edu.ifpi
- Artifact: GerencidorUsuarioApp
- Name : GerencidorUsuarioApp
- Description: Demo project for Spring Boot
- Package name: 

Dependencies
- Spring Web
- Spring Data JPA
- MySQL Driver
- Thymeleaf
- Validation

## データベースの作成とデータベースへの接続する

(1)postgresqlデータベースを作成する

(2)application.propertiesを編集する

```src/main/resources/application.properties
spring.jpa.database=mysql
spring.sql.init.platform=org.hibernate.dialect.MySQL8Dialect
spring.jpa.hibernate.ddl-auto=update
spring.datasource.url=jdbc:mysql://localhost:3306/your_database_name
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.jpa.show-sql=true
spring.jpa.properties.hibernate.format_sql=true
```
## Bootstrap で登録フォームを作成する

(1)formulario-cadastro.htmlを作成する

```resouce/templates/formulario-cadastro.html
<!DOCTYPE html>
<htmllang="en">
  <head>
    <title>formulario de cadastro</title>
    <!-- Bootstrap -->
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet">
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js"></script>
</head>
<body>
<div class="container">
    <h2>formulario de cadastro</h2>
    <form>

        <div class="mb-3">
            <input class="form-control" type="text" id="name" name="name" placeholder="Name">
        </div>

        <div class="mb-3">
            <input class="form-control" type="text" id="email" name="email" placeholder="Email">
        </div>

        <div class="mb-3">
            <input class="form-control" type="text" id="cpf" name="cpf" placeholder="Cpf">
        </div>

        <div class="mb-3">
            <input class="form-control" type="text" id="senha" name="senha" placeholder="Senha">
        </div>

        <div class="mb-3">
                <select class="form-select" id="floatingSelect" aria-label="Floating label select example">
                  <option selected value="">Selecione o papel</option>
                  <option value="Adminstrador">Adminstrador</option>
                  <option value="Usuario">Usuario</option>
                  <option value="Programador">Programador</option>
                </select>
        </div>
        <button type="submit" class="btn btn-primary">Cadastrar</button>
    </form>
</div>
  </body>
</html>
```
(2)controller/UsuarioControllerを作成する

```controller/UsuarioController.kt
package br.edu.ifpi.GerencidorUsuarioApp.controller
import org.springframework.stereotype.Controller

@Controller
class UsuarioController {

    @GetMapping("/formulario/cadastro")
    fun abrirFormularioCadastro(): String {

        return "formulario-cadastro"   
    }
}
```
(3)model/Usuarioを作成する

```model/Usuario.kt
package br.edu.ifpi.GerencidorUsuarioApp.model

data class Usuario (

    @field:NotBlank(message = "Nome e obrigatorio")
    var nome: String = "",

    @field:NotBlank(message = "Email e obrigatorio")
    @field:Email(message = "Email invalido")
    var email: String = "",

    @field:NotBlank(message = "Cpf e obrigatorio")
    @field:CPF(message = "Cpf invalido")
    var cpf: String = "",

    @field:NotBlank(message = "senha e obrigatorio")
    @field:Size(min=6, max=12, message = "A senha deve ter entre 6 e 12 caracteres")
    var senha: String = "",

    var papel: String = ""
){

}
```
(4)thymeleaf を使用してユーザー オブジェクトの入力と属性を設定する

```resouce/templates/formulario-cadastro.html
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
  <head>
    <title>formulario de cadastro</title>
    <!-- Bootstrap -->
    <link
      href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css"
      rel="stylesheet"
    />
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js"></script>
  </head>
  <body>
    <div class="container">
      <h2>formulario de cadastro</h2>
      <form th:object="${usuario}" method="post" action="/cadastrar">
        <div class="mb-3">
          <input
            class="form-control"
            type="text"
            id="nome"
            name="nome"
            placeholder="Nome"
            th:field="*{nome}"
          />
        </div>

        <div class="mb-3">
          <input
            class="form-control"
            type="text"
            id="email"
            name="email"
            placeholder="Email"
            th:field="*{email}"
          />
        </div>

        <div class="mb-3">
          <input
            class="form-control"
            type="text"
            id="cpf"
            name="cpf"
            placeholder="Cpf"
            th:field="*{cpf}"
          />
        </div>

        <div class="mb-3">
          <input
            class="form-control"
            type="text"
            id="senha"
            name="senha"
            placeholder="Senha"
            th:field="*{senha}"
          />
        </div>

        <div class="mb-3">
          <select
            class="form-select"
            id="floatingSelect"
            aria-label="Floating label select example"
            th:field="*{papel}"
          >
            <option selected value="">Selecione o papel</option>
            <option value="Adminstrador">Adminstrador</option>
            <option value="Usuario">Usuario</option>
            <option value="Programador">Programador</option>
          </select>
        </div>
        <button type="submit" class="btn btn-primary">Cadastrar</button>
      </form>
    </div>
  </body>
</html>

```
(5)コントローラーでユーザーオブジェクトを受け取る 

```controller/UsuarioController.kt
package br.edu.ifpi.GerencidorUsuarioApp.controller
import org.springframework.stereotype.Controller

@Controller
class UsuarioController {

    @GetMapping("/formulario/cadastro")
    fun abrirFormularioCadastro(model: Model): String {

        val usuario = Usuario()

        model.addAttribute("usuario", usuario)

        return "formulario-cadastro"   
    }

    @PostMapping("/cadastrar")
    fun cadastrarUsuario(@Validated usuario: Usuario, result: BindingResult):String{

        if(result.hasErrors()){
            return "formulario-cadastro"
        }

        println(usuario)
        return "home"

    }
}
```
(6)home.htmlを作成する

```resouce/templates/home.html
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>Geranciamento de Usuarios</title>
  </head>
  <body></body>
</html>

```

(7)formulario-cadastro.htmlを編集する

```resouce/templates/formulario-cadastro.html
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
  <head>
    <title>formulario de cadastro</title>
    <!-- Bootstrap -->
    <link
      href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css"
      rel="stylesheet"
    />
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js"></script>
  </head>
  <body>
    <div class="container">
      <h2>formulario de cadastro</h2>
      <form th:object="${usuario}" method="post" action="/cadastrar">
        <div class="mb-3">
          <input
            class="form-control"
            type="text"
            id="nome"
            name="nome"
            placeholder="Nome"
            th:field="*{nome}"
          />
          <div
            class="alert alert-danger"
            th:if="${#fields.hasErrors('nome')}"
            th:errors="*{nome}"
          ></div>
        </div>

        <div class="mb-3">
          <input
            class="form-control"
            type="text"
            id="email"
            name="email"
            placeholder="Email"
            th:field="*{email}"
          />
          <div
            class="alert alert-danger"
            th:if="${#fields.hasErrors('email')}"
            th:errors="*{email}"
          ></div>
        </div>

        <div class="mb-3">
          <input
            class="form-control"
            type="text"
            id="cpf"
            name="cpf"
            placeholder="Cpf"
            th:field="*{cpf}"
          />
          <div
            class="alert alert-danger"
            th:if="${#fields.hasErrors('cpf')}"
            th:errors="*{cpf}"
          ></div>
        </div>

        <div class="mb-3">
          <input
            class="form-control"
            type="text"
            id="senha"
            name="senha"
            placeholder="Senha"
            th:field="*{senha}"
          />
          <div
            class="alert alert-danger"
            th:if="${#fields.hasErrors('senha')}"
            th:errors="*{senha}"
          ></div>
        </div>

        <div class="mb-3">
          <select
            class="form-select"
            id="floatingSelect"
            aria-label="Floating label select example"
            th:field="*{papel}"
          >
            <option selected value="">Selecione o papel</option>
            <option value="Adminstrador">Adminstrador</option>
            <option value="Usuario">Usuario</option>
            <option value="Programador">Programador</option>
          </select>
        </div>
        <button type="submit" class="btn btn-primary">Cadastrar</button>
      </form>
    </div>
  </body>
</html>

```
(8)model/Usuarioを修正する

```model/Usuario.kt

package br.edu.ifpi.GerencidorUsuarioApp.model

import jakarta.Validation.constraints.NotBlank
import jakarta.Validation.constraints.Size
import org.hibernate.Validator.constraints.br.CPF

@Entity
data class Usuario (

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    var id: Long? = null,

    @field:NotBlank(message = "Nome e obrigatorio")
    var nome: String = "",

    @field:NotBlank(message = "Email e obrigatorio")
    @field:Email(message = "Email invalido")
    var email: String = "",

    @field:NotBlank(message = "Cpf e obrigatorio")
    @field:CPF(message = "Cpf invalido")
    var cpf: String = "",

    @field:NotBlank(message = "senha e obrigatorio")
    @field:Size(min=6, max=12, message = "A senha deve ter entre 6 e 12 caracteres")
    var senha: String = "",

    var papel: String = ""
){

}
```
(9)repository/UsuarioRepositoryを作成する

```repository/UsuarioRepository.kt


```

(10)controller/UsuarioControllerを編集する

```controller/UsuarioController.kt
package br.edu.ifpi.GerencidorUsuarioApp.controller
import org.springframework.stereotype.Controller

@Controller
class UsuarioController {

    @Autowired
    lateinit var repositorio: UsuarioRepository

    @GetMapping("/formulario/cadastro")
    fun abrirFormularioCadastro(model: Model): String {

        val usuario = Usuario()

        model.addAttribute("usuario", usuario)

        return "formulario-cadastro"   
    }

    @PostMapping("/cadastrar")
    fun cadastrarUsuario(@Validated usuario: Usuario, result: BindingResult):String{

        if(result.hasErrors()){
            return "formulario-cadastro"
        }

        println(usuario)
        repositorio.save(usuario)
        
        return "home"

    }
}
```
## ホームページにユーザー テーブルを実装する

(1)home.htmlを編集する

```resouce/templates/home.html


```
(2)formulario-edicao.htmlを作成する

```resouce/templates/formulario-edicao.html

```
(3)controller/UsuarioControllerを編集する

```controller/UsuarioController.kt

```
## 参考サイト
[Tutorial Criando Uma Aplicação Web CRUD com Kotlin, Spring Boot, Thymeleaf e Bootstrap - Aula 01](https://www.youtube.com/watch?v=4QuZa5OMRvU&list=PLl223bYTf3gsGGii0f-hceBD2bHtisu0M)
[Criação do formulário de cadastro com Bootstrap - Aula 02](https://www.youtube.com/watch?v=UY4NoxkR4sM)
[Criando a Função para Abrir o Formulário de Cadastro - Aula 03](https://www.youtube.com/watch?v=wbXPNnWZAoY)
[Criação da Classe Modelo Usuario e Enviando Objeto Usuário para o Formulário - Aula 04](https://www.youtube.com/watch?v=I2YNXVO--ho)
[Utilizando o thymeleaf para colocar os dados dos inputs nos atributos do objeto usuario - Vídeo 05](https://www.youtube.com/watch?v=qKTSpTd5xD8)
[Recebendo o Objeto Usuário no Controller - Aula 06](https://www.youtube.com/watch?v=DxomYId8Ht8)
[Implementando a Validação do Formulário de Cadastro - Aula 07](https://www.youtube.com/watch?v=OEEUAis0muI)
[Salvando dados do usuário no banco de dados - Aula 08](https://www.youtube.com/watch?v=BaKkwMGJiXs)
[Implementando a Tabela de Usuários na Página Home - Aula 09](https://www.youtube.com/watch?v=CEMZf49IwA0)
[Populando a Tabela com Dados do Banco de Dados - Aula 10](https://www.youtube.com/watch?v=2jFeHcEsMw0)
[Implementando a Edição de Dados de Usuário - Aula 11](https://www.youtube.com/watch?v=-lPOfMyU7gc)
[Implementando a Edição de Dados do Usuário - Aula 12](https://www.youtube.com/watch?v=pSaIK2kypBY)