Spring Boot Tutorial - Build Employee Management Project from Scratch using Spring Boot + Spring Security + Thymeleaf and MySQL Database
🎓 Top 15 Udemy Courses (80-90% Discount): My Udemy Courses - Ramesh Fadatare — All my Udemy courses are real-time and project oriented courses.
▶️ Subscribe to My YouTube Channel (178K+ subscribers): Java Guides on YouTube
▶️ For AI, ChatGPT, Web, Tech, and Generative AI, subscribe to another channel: Ramesh Fadatare on YouTube
Overview
The Employee Management System project will implement the following features:
- List Employees
- Add Employee
- Update Employee
- Delete Employee
- Pagination
- Sorting
- User Login
- User Registration
- User Logout
Tools and Technologies Used
- Java 17+
- Spring Boot 3
- Spring Data JPA (Hibernate)
- Spring Security 6
- MySQL
- Eclipse STS
- Maven
- Tomcat
- Thymeleaf
Step 1: Create Spring Boot Project
Spring Boot provides a web tool called Spring Initializer to bootstrap an application quickly. Follow these steps:
Go to Spring Initializer
Visit https://start.spring.io/.
Use the following details:
- Project Name:
employee-management-webapp - Project Type:
Maven - Dependencies:
Spring Web,Spring Data JPA,MySQL Driver,Spring Security,Thymeleaf - Package name:
net.javaguides.springboot
Step 2: Add Maven Dependencies
Here is the complete pom.xml file for your reference:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.thymeleaf.extras</groupId>
<artifactId>thymeleaf-extras-springsecurity6</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>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>mysql.com</groupId>
<artifactId>mysql-connector-j</artifactId>
<scope>runtime</scope>
</dependency>
Step 3: Configure MySQL Database
Spring Boot tries to auto-configure a DataSource if the spring-boot-starter-data-jpa dependency is in the classpath by reading the database configuration from the application.properties file.
Configure application.properties
Open the application.properties file and add the following properties:
# DATASOURCE (DataSourceAutoConfiguration & DataSourceProperties)
spring.datasource.url=jdbc:mysql://localhost:3306/demo
spring.datasource.username=root
spring.datasource.password=root
# Hibernate ddl auto (create, create-drop, validate, update)
spring.jpa.hibernate.ddl-auto = update
logging.level.org.hibernate.SQL=DEBUG
logging.level.org.hibernate.type=TRACE
You will need to create a database named demo in MySQL, and change the spring.datasource.username and spring.datasource.password properties as per your MySQL installation.
Spring Boot uses Hibernate as the default JPA implementation. The property spring.jpa.hibernate.ddl-auto is used for database initialization. We’ve used the value update for this property.
Step 4: Create Models
Let's create models or entities for our Employee Management System application.
Create the Employee Class
Create an Employee class inside the model package:
package net.javaguides.springboot.model;
import jakarta.persistence.*;
@Entity
@Table(name = "employees")
public class Employee {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
@Column(name = "first_name")
private String firstName;
@Column(name = "last_name")
private String lastName;
@Column(name = "email")
private String email;
// Getters and Setters
}
Create the User Class
Create a User class inside the model package:
package net.javaguides.springboot.model;
import java.util.Collection;
import jakarta.persistence.*;
@Entity
@Table(name = "user", uniqueConstraints = @UniqueConstraint(columnNames = "email"))
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(name = "first_name")
private String firstName;
@Column(name = "last_name")
private String lastName;
private String email;
private String password;
@ManyToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
@JoinTable(
name = "users_roles",
joinColumns = @JoinColumn(
name = "user_id", referencedColumnName = "id"),
inverseJoinColumns = @JoinColumn(
name = "role_id", referencedColumnName = "id"))
private Collection<Role> roles;
// Getters and Setters
}
Create the Role Class
Create a Role class inside the model package:
package net.javaguides.springboot.model;
import jakarta.persistence.*;
@Entity
@Table(name = "role")
public class Role {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
// Getters and Setters
}
Step 5: Create Repository Layer
We will create JPA repositories to access data from the database.
Create EmployeeRepository
Create an EmployeeRepository interface inside the repository package:
package net.javaguides.springboot.repository;
import org.springframework.data.jpa.repository.JpaRepository;
import net.javaguides.springboot.model.Employee;
public interface EmployeeRepository extends JpaRepository<Employee, Long> {
}
Create UserRepository
Create a UserRepository interface inside the repository package:
package net.javaguides.springboot.repository;
import org.springframework.data.jpa.repository.JpaRepository;
import net.javaguides.springboot.model.User;
public interface UserRepository extends JpaRepository<User, Long> {
User findByEmail(String email);
}
Step 6: Create Service Layer
We will implement a service layer.
Create EmployeeService Interface
Create an EmployeeService interface inside the service package:
package net.javaguides.springboot.service;
import java.util.List;
import org.springframework.data.domain.Page;
import net.javaguides.springboot.model.Employee;
public interface EmployeeService {
List<Employee> getAllEmployees();
void saveEmployee(Employee employee);
Employee getEmployeeById(long id);
void deleteEmployeeById(long id);
Page<Employee> findPaginated(int pageNo, int pageSize, String sortField, String sortDirection);
}
Create EmployeeServiceImpl Class
Create an EmployeeServiceImpl class inside the service package:
package net.javaguides.springboot.service;
import java.util.List;
import java.util.Optional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;
import net.javaguides.springboot.model.Employee;
import net.javaguides.springboot.repository.EmployeeRepository;
@Service
public class EmployeeServiceImpl implements EmployeeService {
@Autowired
private EmployeeRepository employeeRepository;
@Override
public List<Employee> getAllEmployees() {
return employeeRepository.findAll();
}
@Override
public void saveEmployee(Employee employee) {
this.employeeRepository.save(employee);
}
@Override
public Employee getEmployeeById(long id) {
Optional<Employee> optional = employeeRepository.findById(id);
Employee employee = null;
if (optional.isPresent()) {
employee = optional.get();
} else {
throw new RuntimeException(" Employee not found for id :: " + id);
}
return employee;
}
@Override
public void deleteEmployeeById(long id) {
this.employeeRepository.deleteById(id);
}
@Override
public Page<Employee> findPaginated(int pageNo, int pageSize, String sortField, String sortDirection) {
Sort sort = sortDirection.equalsIgnoreCase(Sort.Direction.ASC.name()) ? Sort.by(sortField).ascending() :
Sort.by(sortField).descending();
Pageable pageable = PageRequest.of(pageNo - 1, pageSize, sort);
return this.employeeRepository.findAll(pageable);
}
}
Create UserService Interface
Create a UserService interface inside the service package:
package net.javaguides.springboot.service;
import org.springframework.security.core.userdetails.UserDetailsService;
import net.javaguides.springboot.dto.UserRegistrationDto;
import net.javaguides.springboot.model.User;
public interface UserService extends UserDetailsService {
User save(UserRegistrationDto registrationDto);
}
Create UserServiceImpl Class
Create a UserServiceImpl class inside the service package:
package net.javaguides.springboot.service;
import java.util.Arrays;
import java.util.Collection;
import java.util.stream.Collectors;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import net.javaguides.springboot.dto.UserRegistrationDto;
import net.javaguides.springboot.model.Role;
import net.javaguides.springboot.model.User;
import net.javaguides.springboot.repository.UserRepository;
@Service
public class UserServiceImpl implements UserService {
private UserRepository userRepository;
@Autowired
private BCryptPasswordEncoder passwordEncoder;
public UserServiceImpl(UserRepository userRepository) {
super();
this.userRepository = userRepository;
}
@Override
public User save(UserRegistrationDto registrationDto) {
User user = new User(registrationDto.getFirstName(),
registrationDto.getLastName(), registrationDto.getEmail(),
passwordEncoder.encode(registrationDto.getPassword()), Arrays.asList(new Role("ROLE_USER")));
return userRepository.save(user);
}
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
User user = userRepository.findByEmail(username);
if (user == null) {
throw new UsernameNotFoundException("Invalid username or password.");
}
return new org.springframework.security.core.userdetails.User(user.getEmail(), user.getPassword(), mapRolesToAuthorities(user.getRoles()));
}
private Collection<? extends GrantedAuthority> mapRolesToAuthorities(Collection<Role> roles){
return roles.stream().map(role -> new SimpleGrantedAuthority(role.getName())).collect(Collectors.toList());
}
}
Step 7: Create DTO
Create UserRegistrationDto Class
Create a UserRegistrationDto class inside the dto package:
package net.javaguides.springboot.dto;
public class UserRegistrationDto {
private String firstName;
private String lastName;
private String email;
private String password;
public UserRegistrationDto() {
}
public UserRegistrationDto(String firstName, String lastName, String email, String password) {
super();
this.firstName = firstName;
this.lastName = lastName;
this.email = email;
this.password = password;
}
// Getters and Setters
}
Step 8: Spring Security Configuration
Create SecurityConfiguration Class
Create a SecurityConfiguration class inside the config package:
package net.javaguides.springboot.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
@Configuration
@EnableWebSecurity
public class SecurityConfiguration {
@Autowired
private UserDetailsService userDetailsService;
@Bean
public BCryptPasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
.authorizeHttpRequests((requests) -> requests
.requestMatchers("/registration**", "/js/**", "/css/**", "/img/**").permitAll()
.anyRequest().authenticated()
)
.formLogin((form) -> form
.loginPage("/login")
.permitAll()
)
.logout((logout) -> logout
.logoutUrl("/logout")
.logoutSuccessUrl("/login?logout")
.permitAll()
);
return http.build();
}
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
}
}
Let's understand above Spring Security code, we defined a SecurityConfiguration class for setting up security in a Spring Boot application using Spring Security 6.3. Let's break down each part of the code:
Package and Imports
package net.javaguides.springboot.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
- Package Declaration: Declares the package for the configuration class.
- Imports: Imports the necessary Spring Security and Spring Framework classes and interfaces.
Class and Annotations
@Configuration
@EnableWebSecurity
public class SecurityConfiguration {
- @Configuration: Indicates that this class contains Spring configuration.
- @EnableWebSecurity: Enables Spring Security's web security support and provides Spring MVC integration.
Fields
@Autowired
private UserDetailsService userDetailsService;
- userDetailsService: A service that provides the
UserDetailsfor authentication. It is injected by Spring using the@Autowiredannotation.
Beans
@Bean
public BCryptPasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
- BCryptPasswordEncoder: A bean that provides a password encoder using the BCrypt hashing function, which is a strong and secure way to store passwords.
Security Filter Chain
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
.authorizeHttpRequests((requests) -> requests
.requestMatchers("/registration**", "/js/**", "/css/**", "/img/**").permitAll()
.anyRequest().authenticated()
)
.formLogin((form) -> form
.loginPage("/login")
.permitAll()
)
.logout((logout) -> logout
.logoutUrl("/logout")
.logoutSuccessUrl("/login?logout")
.permitAll()
);
return http.build();
}
- SecurityFilterChain: Defines the security filter chain.
- HttpSecurity: Allows configuring web-based security for specific http requests.
- authorizeHttpRequests: Configures authorization for HTTP requests.
- requestMatchers: Specifies the URL patterns that should be permitted without authentication.
- anyRequest().authenticated(): Requires authentication for any other requests.
- formLogin: Configures form-based authentication.
- loginPage("/login"): Specifies the custom login page URL.
- permitAll(): Allows access to the login page for all users.
- logout: Configures logout functionality.
- logoutUrl("/logout"): Specifies the logout URL.
- logoutSuccessUrl("/login?logout"): Redirects to the login page with a logout message after logout.
- permitAll(): Allows access to the logout functionality for all users.
- authorizeHttpRequests: Configures authorization for HTTP requests.
Global Authentication Configuration
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
}
- configureGlobal: Configures the global authentication manager.
- userDetailsService: Sets the custom
UserDetailsServicefor authentication. - passwordEncoder: Sets the
BCryptPasswordEncoderfor encoding passwords.
- userDetailsService: Sets the custom
Step 9: Create Controller Layer
Let's create the controller layer to handle web requests.
9.1 Create EmployeeController Class
Create the EmployeeController class inside the controller package:
package net.javaguides.springboot.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import net.javaguides.springboot.model.Employee;
import net.javaguides.springboot.service.EmployeeService;
import java.util.List;
@Controller
public class EmployeeController {
@Autowired
private EmployeeService employeeService;
@GetMapping("/")
public String viewHomePage(Model model) {
return findPaginated(1, "firstName", "asc", model);
}
@GetMapping("/showNewEmployeeForm")
public String showNewEmployeeForm(Model model) {
Employee employee = new Employee();
model.addAttribute("employee", employee);
return "new_employee";
}
@PostMapping("/saveEmployee")
public String saveEmployee(@ModelAttribute("employee") Employee employee) {
employeeService.saveEmployee(employee);
return "redirect:/";
}
@GetMapping("/showFormForUpdate/{id}")
public String showFormForUpdate(@PathVariable(value = "id") long id, Model model) {
Employee employee = employeeService.getEmployeeById(id);
model.addAttribute("employee", employee);
return "update_employee";
}
@GetMapping("/deleteEmployee/{id}")
public String deleteEmployee(@PathVariable(value = "id") long id) {
employeeService.deleteEmployeeById(id);
return "redirect:/";
}
@GetMapping("/page/{pageNo}")
public String findPaginated(@PathVariable(value = "pageNo") int pageNo,
@RequestParam("sortField") String sortField,
@RequestParam("sortDir") String sortDir,
Model model) {
int pageSize = 5;
Page<Employee> page = employeeService.findPaginated(pageNo, pageSize, sortField, sortDir);
List<Employee> listEmployees = page.getContent();
model.addAttribute("currentPage", pageNo);
model.addAttribute("totalPages", page.getTotalPages());
model.addAttribute("totalItems", page.getTotalElements());
model.addAttribute("sortField", sortField);
model.addAttribute("sortDir", sortDir);
model.addAttribute("reverseSortDir", sortDir.equals("asc") ? "desc" : "asc");
model.addAttribute("listEmployees", listEmployees);
return "index";
}
}
9.2 Create UserRegistrationController Class
Create the UserRegistrationController class inside the controller package:
package net.javaguides.springboot.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import net.javaguides.springboot.dto.UserRegistrationDto;
import net.javaguides.springboot.service.UserService;
@Controller
@RequestMapping("/registration")
public class UserRegistrationController {
@Autowired
private UserService userService;
@ModelAttribute("user")
public UserRegistrationDto userRegistrationDto() {
return new UserRegistrationDto();
}
@GetMapping
public String showRegistrationForm() {
return "registration";
}
@PostMapping
public String registerUserAccount(@ModelAttribute("user") UserRegistrationDto registrationDto) {
userService.save(registrationDto);
return "redirect:/registration?success";
}
}
9.3 Create MainController Class
Create the MainController class inside the controller package:
package net.javaguides.springboot.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
@Controller
public class MainController {
@GetMapping("/login")
public String login() {
return "login";
}
}
Step 10: Create Thymeleaf Templates
10.1 Create index.html
Create an index.html file inside the src/main/resources/templates directory:
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="ISO-8859-1">
<title>Employee Management System</title>
<link rel="stylesheet" type="text/css" href="/css/bootstrap.min.css"/>
</head>
<body>
<div class="container">
<h2>Employee Management System</h2>
<div th:if="${employees != null}">
<a class="btn btn-primary mb-3" th:href="@{/showNewEmployeeForm}">Add Employee</a>
<table class="table table-bordered">
<thead>
<tr>
<th th:click="|@{/page/1(sortField='firstName',sortDir=${reverseSortDir})}|">First Name</th>
<th th:click="|@{/page/1(sortField='lastName',sortDir=${reverseSortDir})}|">Last Name</th>
<th th:click="|@{/page/1(sortField='email',sortDir=${reverseSortDir})}|">Email</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<tr th:each="employee : ${listEmployees}">
<td th:text="${employee.firstName}">First Name</td>
<td th:text="${employee.lastName}">Last Name</td>
<td th:text="${employee.email}">Email</td>
<td>
<a th:href="@{/showFormForUpdate/{id}(id=${employee.id})}">Edit</a> |
<a th:href="@{/deleteEmployee/{id}(id=${employee.id})}">Delete</a>
</td>
</tr>
</tbody>
</table>
</div>
<div>
<ul class="pagination">
<li th:if="${currentPage > 1}">
<a class="page-link" th:href="@{/page/{pageNo}(pageNo=${currentPage - 1})}">Previous</a>
</li>
<li th:each="i : ${#numbers.sequence(1, totalPages)}"
th:classappend="${i == currentPage} ? 'active'">
<a class="page-link" th:href="@{/page/{pageNo}(pageNo=${i})}" th:text="${i}">1</a>
</li>
<li th:if="${currentPage < totalPages}">
<a class="page-link" th:href="@{/page/{pageNo}(pageNo=${currentPage + 1})}">Next</a>
</li>
</ul>
</div>
</div>
</body>
</html>
10.2 Create new_employee.html
Create a new_employee.html file inside the src/main/resources/templates directory:
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="ISO-8859-1">
<title>Employee Management System</title>
<link rel="stylesheet" type="text/css" href="/css/bootstrap.min.css"/>
</head>
<body>
<div class="container">
<h2>Add Employee</h2>
<form th:action="@{/saveEmployee}" th:object="${employee}" method="post">
<div class="form-group">
<label>First Name</label>
<input type="text" class="form-control" th:field="*{firstName}" placeholder="First Name"/>
</div>
<div class="form-group">
<label>Last Name</label>
<input type="text" class="form-control" th:field="*{lastName}" placeholder="Last Name"/>
</div>
<div class="form-group">
<label>Email</label>
<input type="email" class="form-control" th:field="*{email}" placeholder="Email"/>
</div>
<button type="submit" class="btn btn-primary">Save</button>
</form>
</div>
</body>
</html>
10.3 Create update_employee.html
Create an update_employee.html file inside the src/main/resources/templates directory:
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="ISO-8859-1">
<title>Employee Management System</title>
<link rel="stylesheet" type="text/css" href="/css/bootstrap.min.css"/>
</head>
<body>
<div class="container">
<h2>Update Employee</h2>
<form th:action="@{/saveEmployee}" th:object="${employee}" method="post">
<div class="form-group">
<label>First Name</label>
<input type="text" class="form-control" th:field="*{firstName}" placeholder="First Name"/>
</div>
<div class="form-group">
<label>Last Name</label>
<input type="text" class="form-control" th:field="*{lastName}" placeholder="Last Name"/>
</div>
<div class="form-group">
<label>Email</label>
<input type="email" class="form-control" th:field="*{email}" placeholder="Email"/>
</div>
<button type="submit" class="btn btn-primary">Save</button>
</form>
</div>
</body>
</html>
10.4 Create registration.html
Create a registration.html file inside the src/main/resources/templates directory:
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="ISO-8859-1">
<title>User Registration</title>
<link rel="stylesheet" type="text/css" href="/css/bootstrap.min.css"/>
</head>
<body>
<div class="container">
<h2>User Registration</h2>
<form th:action="@{/registration}" th:object="${user}" method="post">
<div class="form-group">
<label>First Name</label>
<input type="text" class="form-control" th:field="*{firstName}" placeholder="First Name"/>
</div>
<div class="form-group">
<label>Last Name</label>
<input type="text" class="form-control" th:field="*{lastName}" placeholder="Last Name"/>
</div>
<div class="form-group">
<label>Email</label>
<input type="email" class="form-control" th:field="*{email}" placeholder="Email"/>
</div>
<div class="form-group">
<label>Password</label>
<input type="password" class="form-control" th:field="*{password}" placeholder="Password"/>
</div>
<button type="submit" class="btn btn-primary">Register</button>
</form>
</div>
</body>
</html>
10.5 Create login.html
Create a login.html file inside the src/main/resources/templates directory:
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="ISO-8859-1">
<title>Login</title>
<link rel="stylesheet" type="text/css" href="/css/bootstrap.min.css"/>
</head>
<body>
<div class="container">
<h2>Login</h2>
<form th:action="@{/login}" method="post">
<div th:if="${param.error}">
<div class="alert alert-danger">Invalid username or password.</div>
</div>
<div th:if="${param.logout}">
<div class="alert alert-info">You have been logged out.</div>
</div>
<div class="form-group">
<label>Email</label>
<input type="email" class="form-control" name="username" placeholder="Email" required autofocus/>
</div>
<div class="form-group">
<label>Password</label>
<input type="password" class="form-control" name="password" placeholder="Password" required/>
</div>
<button type="submit" class="btn btn-primary">Login</button>
</form>
<div>
<span>New user? <a th:href="@{/registration}">Register here</a></span>
</div>
</div>
</body>
</html>
Step 11: Run the Spring Boot Application
We’ve successfully built our employee management system application. Let's run our Spring Boot application and test it.
Navigate to the root directory of the application and run the following command:
$ mvn spring-boot:run
The application will start at Spring Boot’s default Tomcat port 8080.
Step 12: YouTube Video Series
You can develop this project from scratch using line-by-line coding from my YouTube videos.
Employee Management Module
- Spring Boot Thymeleaf CRUD Database Real-Time Project - PART 1
- Spring Boot Thymeleaf CRUD Database Real-Time Project - PART 2
- Spring Boot Thymeleaf CRUD Database Real-Time Project - PART 3
- Spring Boot Thymeleaf CRUD Database Real-Time Project - PART 4
- Spring Boot Thymeleaf CRUD Database Real-Time Project - PART 5
- Spring Boot Thymeleaf CRUD Database Real-Time Project - PART 6
- Spring Boot Thymeleaf CRUD Database Real-Time Project - PART 7
Registration and Login Module
- Registration and Login with Spring Boot and Spring Security - PART 1
- Registration and Login with Spring Boot and Spring Security - PART 2
- Registration and Login with Spring Boot and Spring Security - PART 3
- Registration and Login with Spring Boot and Spring Security - PART 4
- Registration and Login with Spring Boot and Spring Security - PART 5
- Registration and Login with Spring Boot and Spring Security - PART 6
- Registration and Login with Spring Boot and Spring Security - PART 7
- Registration and Login with Spring Boot and Spring Security - PART 8
Conclusion
This tutorial demonstrated how to create a complete Employee Management System using Spring Boot 3, Spring MVC, Spring Security 6, Thymeleaf, and MySQL. We covered everything from setting up the Spring Boot project, configuring Spring Security, creating the service and repository layers, and building the Thymeleaf templates. By following this guide, you can build a robust and secure employee management application.
Comments
Post a Comment
Leave Comment