Spring Web + Bootstrap 5.1

Hai hyvercoder! kali ini kita akan membuat aplikasi Spring web application dengan framework css yang sudah umum yaitu Bootstratp 5.1 dimana aplikasi ini berisikan data tamu atau member, aplikasi kali ini akan mengunakan

  • Spring Web Application
  • Thymeleaf
  • Bootstrap 5.1
  • Java 8/11
  • Maven

Buat project spring boot menggunakan Spring Initializr dependency yang akan kita gunakan adalah :

  • spring-boot-starter-thymeleaf
  • spring-boot-starter-web
  • bootstrap

Install dependencies dengan perintah mvn clean install, tanpilan struktur project seperti berikut

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.6.6</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>demo</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>11</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>

<dependency>
<groupId>org.webjars</groupId>
<artifactId>bootstrap</artifactId>
<version>5.1.3</version>
</dependency>

</dependencies>

<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>

</project>

Sekarang kita buat file html pada dir resources-templates

index.html

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <link rel="stylesheet" th:href="@{webjars/bootstrap/5.1.3/css/bootstrap.min.css}"/>
    <link rel="stylesheet" th:href="@{/css/styles.css}"/>
    <title>Belajar Spring Boot Web</title>
</head>
<body>
    <div class="container">
        <h1>Buku Tamu</h1>
        <a class="btn btn-primary" href="/bukutamu" >Buku Tamu</a>
        <a class="btn btn-primary" href="/daftar-bukutamu" >List Buku Tamu</a>
    </div>
</body>

<script type="text/javascript" th:src="@{webjars/bootstrap/5.1.3/js/bootstrap.min.js}"></script>
</html>

bukutamu.html

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <link rel="stylesheet" th:href="@{webjars/bootstrap/5.1.3/css/bootstrap.min.css}"/>
    <link rel="stylesheet" th:href="@{/css/styles.css}"/>
    <title>Belajar Spring Boot Web</title>
</head>
<body>
    <div>
        <div class="container">
            <a href="/"><h1>Buku Tamu</h1></a>
            <form action="/bukutamu/simpan" method="post">
          
              <label for="fname">Nama</label>
              <input type="text" class="form-control" id="fname" name="firstname" placeholder="Masukan nama">
          
              <label for="lname">Telepon</label>
              <input type="text" id="lname" name="lastname"  class="form-control" placeholder="Masukan nomor telepon">
            
              <label for="subject">Alamat</label>
              <textarea id="subject" name="subject"  class="form-control" placeholder="Masukan alamat"></textarea>
          
              <input class="btn btn-primary" type="submit"  value="Submit">
          
            </form>
          </div>
    </div>
</body>
<script type="text/javascript" th:src="@{webjars/bootstrap/5.1.3/js/bootstrap.min.js}"></script>
</html>

daftar-bukutamu.html

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <link rel="stylesheet" th:href="@{webjars/bootstrap/5.1.3/css/bootstrap.min.css}"/>
    <link rel="stylesheet" th:href="@{/css/styles.css}"/>
    <title>Belajar Spring Boot Web</title>
</head>
<body>
    <div class="container">
        <a href="/"><h1>Daftar Buku Tamu</h1></a>
        <table class="table">
            <thead>
              <tr>
                <th>Nama</th>
                <th>Telepom</th>
                <th>Alamat</th>
              </tr>
            </thead>
            <tbody>
              <tr>
                <td>John</td>
                <td>087885876037</td>
                <td>Cisauk Tangerang Selatan</td>
              </tr>
              <tr>
                <td>Mary</td>
                <td>087885876045</td>
                <td>Cisauk Tangerang Selatan</td>
              </tr>
              <tr>
                <td>July</td>
                <td>021-5098680</td>
                <td>Cisauk Tangerang Selatan</td>
              </tr>
            </tbody>
          </table>
    </div>
</body>

<script type="text/javascript" th:src="@{webjars/bootstrap/5.1.3/js/bootstrap.min.js}"></script>
</html>

Setelah kita membuat file ht kita juga bisa menambahkan custom css yaitu dengan cara membuat file css pada directory resources-static-css seperti berikut :

styles.css

h1{
    color:red;
}

selain file css, kita juga bisa menambahkan file js (javascript) pada directory yang sama.

Sekarang kita masuk ke controller dimana controller ini berfungsi sebagai pengatur atau navigation , selain itu juga file controller inilah yang nantinya akan digunakan sebagai file java / class java yang bertugas mengelola logic aplikasi yang kita buat, buka class Main aplikasi ini class main adalaha class DemoApplication, kemudain tambahn route controller sebagai berikut :

package com.example.demo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;

@SpringBootApplication
@Controller
public class DemoApplication {

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


	@GetMapping("/")
	public String index(){
		return "index.html";
	}

	@GetMapping("/bukutamu")
	public String book(){
		return "bukutamu.html";
	}

	@GetMapping("/daftar-bukutamu")
	public String daftar(){
		return "daftar-bukutamu.html";
	}
}

pada class ini terdapat @Controller atau Annotation yang menandakan bahwa class ini digunakan sebagai controller index,bukutamu dan daftar-bukutamu dimana methode yang digunakan adalah GET , bisa kita lihat pada methode yang dibuat mengunakan Annotaion @GetMapping . dan mengembalikan nilai yaitu file-file html yg sebelumnya telah kita buat. Setelah itu sekarang kita coba jalankan aplikasi kita dengan perintan mvn spring-boot:run, jika tidak ada kesalahan makan akan terlihan halam index seperti berikut :

http://localhost:8080/

disini kita sudah melihat framewrok bootstrap sudah teintegrasi dengan thymeleaf bisa dilihat dari button yang digunakan adalah class button dari bootstrap dan file css yang kita buat juga terlihat pada h1 dengan warna merah.

Jikakedua button kita klick makan akan menmapilkan halaman seperti berikut :

http://localhost:8080/bukutamu

http://localhost:8080/daftar-bukutamu

The project source code can be downloaded on the GitHub   spring-boot-web-bootstrap

hyvercode

Guest Books CRUD spring-boot + mysql+thymeleaf

Hai hyvercoder! semua kali ini kita akan membuat aplikasi CRUD (Create Read Update Delete ) Guest-Book dimana aplikasi ini berisikan data tamu atau member, aplikasi kali ini akan mengunakan :

  • Spring-boot
  • Maven
  • Mysql
  • Java 1.8
  • Thymeleaf

Buat project spring-boot Structure project seperti ini :

Buat database dengan nama guest_books

create database guest_books;

Buat table dengan nama guest

CREATE TABLE guest_books.guest
(
  id integer PRIMARY KEY NOT NULL,
  name character varying(30),
  phone_number character varying(15)
);

 

Buat class entity dalam package entity dengan Nama Guest.java, Isi file class terse but seperti berikut

import javax.persistence.*;
import java.io.Serializable;

@Table(name = "guest")
@Entity
public class Guest implements Serializable {
    @Id
    @Column(name = "id_guest")
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Integer idGuest;
    @Column(name = "name",length = 30)
    private String name;
    @Column(name = "phone_number",length = 15)
    private String phoneNumber;

    public Integer getIdGuest() {
        return idGuest;
    }

    public void setIdGuest(Integer idGuest) {
        this.idGuest = idGuest;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getPhoneNumber() {
        return phoneNumber;
    }

    public void setPhoneNumber(String phoneNumber) {
        this.phoneNumber = phoneNumber;
    }

}

Buat class GuestRepository.java Pada package repository

package com.alfazid.guestbooks.repository;

import com.alfazid.guestbooks.model.Guest;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

import java.util.List;

@Repository
public interface GuestRepository extends JpaRepository<Guest,Integer> {
    List<Guest> findByName(String name);
}

Buat class GuestController.java dalam package controller

package com.alfazid.guestbooks.controller;

import com.alfazid.guestbooks.model.Guest;
import com.alfazid.guestbooks.repository.GuestRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.servlet.ModelAndView;

import java.util.List;
import java.util.Optional;


@Controller
public class GuestController {
    @Autowired
    private GuestRepository guestRepository;

    @GetMapping("/")
    public ModelAndView getList(Model model){
        List<Guest> list = guestRepository.findAll();
        model.addAttribute("list", list);
        return new ModelAndView ("index");
    }

    @GetMapping("/param")
    public ModelAndView getListByName(Model model, @Param("name") String name){
        List<Guest> list;
        if(name.isEmpty()){
            list= guestRepository.findAll();
        }else{
            list= guestRepository.findByName(name);
        }
        model.addAttribute("list", list);
        return new ModelAndView ("index");
    }

    @GetMapping("/create")
    public ModelAndView create(Guest guest){
        return new ModelAndView ("create");
    }

    @PostMapping("/create")
    public ModelAndView insert(Guest guest){
        guestRepository.save(guest);
        return new ModelAndView ("redirect:/");
    }

    @GetMapping("/update/{id}")
    public ModelAndView edit(Model model,@PathVariable("id") Integer id){
        Optional<Guest> guestBooks = guestRepository.findById(id);
        if(guestBooks.isPresent()){
            model.addAttribute("guest",guestBooks.get());
            return new ModelAndView ("update");
        }
        return new ModelAndView ("redirect:/");

    }

    @PostMapping("/update/{id}")
    public ModelAndView update(@PathVariable("id") Integer id, Guest guest){
        guestRepository.save(guest);
        return new ModelAndView ("redirect:/");
    }

    @GetMapping("/delete/{id}")
    public ModelAndView delete(@PathVariable("id") Integer id){
        guestRepository.deleteById(id);
        return new ModelAndView ("redirect:/");
    }
}

Buat file html pada folder resources/templates

file index.html adalah halaman utama web saat aplikasi dijalankan

<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <title>Guest Books</title>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
    <link rel="stylesheet" type="text/css" th:href="@{/css/bootstrap.min.css}" />
</head>
<body>
<div class="container" style="margin-top:30px;">
    <div class="d-flex justify-content-between flex-wrap flex-md-nowrap align-items-center pt-3 pb-2 mb-3">
        <h2>Guest Books</h2>
        <div class="btn-toolbar mb-5 mb-md-0">
            <div class="btn-group mr-2">
                <input type="text" placeholder="Input name" name="name" id="name" onsubmit="name"
                       class="form-control input-sm form-control-sm"/>
                <button class="btn btn-sm btn-secondary" onclick="onSearch()">Cari</button>
            </div>
            <a class="btn btn-sm btn-secondary" href="/create">
                Tambah Data
            </a>
        </div>
    </div>
    <div class="table-responsive">
        <table class="table table-striped table-sm table-hover">
            <thead>
            <tr>
                <th>Guest ID</th>
                <th>Name</th>
                <th>Phone</th>
                <th style="text-align: center">#</th>
            </tr>
            </thead>
            <tbody>
            <tr th:each="data,iter : ${list}">
                <td th:text="${data.idGuest}"></td>
                <td th:text="${data.name}"></td>
                <td th:text="${data.phoneNumber}"></td>
                <td style="width: 100px;">
                    <a class="btn btn-sm btn-secondary" th:href="@{/update/{id}(id=${data.idGuest})}" style="padding: 3px;">Edit</a>
                    <a class="btn btn-sm btn-secondary" th:href="@{/delete/{id}(id=${data.idGuest})}" style="padding: 3px;">delete</a>
                </td>
            </tr>
            </tbody>
        </table>
    </div>
    <script>
    function onSearch() {
        var name = document.getElementById("name").value;
        if (name !="") {
            window.location = "/param?name="+name;
        } else {
            window.location = "/"
        }
    }
    </script>
</div>
</body>
</html>

Buat file create.html , ini adalah halaman untuk membuat data tamu / member baru

<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <title>Guest Books</title>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
    <link rel="stylesheet" type="text/css" th:href="@{/css/bootstrap.min.css}" />
</head>
<body>
<div class="container">
    <div class="row">
        <main role="main" class="col-md-9 ml-sm-auto col-lg-10 px-4">
            <div class="d-flex justify-content-between flex-wrap flex-md-nowrap align-items-center pt-3 pb-2 mb-3">
                <h2>Guest Books</h2>
            </div>
            <div class="col-sm-8 col-md-8 col-lg-8 col-xs-12">
                <form action="#" th:action="@{/create}" th:object="${guest}" method="POST">
                    <div class="form-group row has-success">
                        <label class="control-label col-sm-3" for="name">Name</label>
                        <div class="col-sm-6">
                            <input class="form-control form-control-sm" type="text" th:field="*{name}" id="name"
                                   name="name" placeholder="Input name" required>
                        </div>
                    </div>
                    <div class="form-group row has-success">
                        <label class="control-label col-sm-3" for="phoneNumber">Phone</label>
                        <div class="col-sm-6">
                        <input class="form-control form-control-sm" type="text" th:field="*{phoneNumber}" id="phoneNumber"
                               name="name" placeholder="Input Phone Number" required>
                        </div>
                    </div>
                    <div class="">
                        <div class="col-sm-6" style="float: right;">
                            <a class="btn btn-sm btn-secondary" href="/">
                                Cancel
                            </a>
                            <input type="submit" class="btn btn-secondary btn-sm" value="Save"/>
                        </div>
                    </div>
                </form>
            </div>
        </main>
    </div>
</div>
</body>
</html>

Buat file update.html , ini adalah halaman untuk merubah data tamu / member

<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <title>Guest Books</title>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
    <link rel="stylesheet" type="text/css" th:href="@{/css/bootstrap.min.css}" />
</head>
<body>
<div class="container">
    <div class="row">
        <main role="main" class="col-md-9 ml-sm-auto col-lg-10 px-4">
            <div class="d-flex justify-content-between flex-wrap flex-md-nowrap align-items-center pt-3 pb-2 mb-3">
                <h2>Guest Books</h2>
            </div>
            <div class="col-sm-8 col-md-8 col-lg-8 col-xs-12">
                <form action="#" th:action="@{/update/{id}(id=${guest.idGuest})}" th:object="${guest}" method="POST">
                    <div class="form-group row has-success">
                        <div class="col-sm-6">
                            <input class="form-control form-control-sm" th:field="*{idGuest}" type="text" id="idGuest"
                                   name="idGuest"  hidden style="background-color: transparent;border: gray solid 1px;">
                        </div>
                    </div>

                    <div class="form-group row has-success">
                        <label class="control-label col-sm-3" for="name">Name</label>
                        <div class="col-sm-6">
                            <input class="form-control form-control-sm" type="text" th:field="*{name}" id="name"
                                   name="name" placeholder="Input name" required>
                        </div>
                    </div>
                    <div class="form-group row has-success">
                        <label class="control-label col-sm-3" for="phoneNumber">Phone</label>
                        <div class="col-sm-6">
                        <input class="form-control form-control-sm" type="text" th:field="*{phoneNumber}" id="phoneNumber"
                               name="name" placeholder="Input Phone Number" required>
                        </div>
                    </div>
                    <div class="">
                        <div class="col-sm-6" style="float: right;">
                            <a class="btn btn-sm btn-secondary" href="/">
                                Cancel
                            </a>
                            <input type="submit" class="btn btn-secondary btn-sm" value="Update"/>
                        </div>
                    </div>
                </form>
            </div>
        </main>
    </div>
</div>
</body>
</html>

Pastikan semua dependencies yg aplikasi butuhkan pada file pom.xml sama seperti berikut :

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.4.0</version>
		<relativePath/> <!-- lookup parent from repository -->
	</parent>
	<groupId>com.alfazid</groupId>
	<artifactId>guestbooks</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>tes1</name>
	<description>Guest Books</description>

	<properties>
		<java.version>1.8</java.version>
	</properties>

	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-data-jpa</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-thymeleaf</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-devtools</artifactId>
		</dependency>
		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
			<scope>runtime</scope>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>
	</dependencies>

	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
	</build>

</project>

Setup database yang terdapat pada file resources/application.yml sesuikan database , username dan password sesuai dengan local mesin kalian

spring:
  datasource:
    driverClassName:
    url: jdbc:mysql://localhost:3306/guest_books?createDatabaseIfNotExist=true&useUnicode=true&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=Asia/Jakarta&useSSL=false
    username: root
    password: 
  jpa:
    show-sql: true
    hibernate:
      ddl-auto: update
    properties:
      hibernate:
        dialect: org.hibernate.dialect.MySQL5Dialect
        format_sql: true

Untuk menjalankan aplikasi gunakan perintah

- mvn clean install
- mvn spring-boot:run

jika aplikasi tidak terjadi kesalahan saat running maka tampilan aplikasi yang kita buat superti berikut:

Halaman utama

Halaman tambah data

Halaman ubah data

The project source code can be downloaded on the GitHub  guest-books

hyvercode