Создайте приложение регистрации пользователей с помощью Spring Boot, Spring Form Validation

View more categories:

1- Цель примера

Статья основана на:
  • Eclipse 3.7 (Oxygen)

  • Spring Boot 2.x

  • Spring Validation

  • Thymeleaf

В данной статье я покажу вам как создать приложение регистрации пользователя, используя  Spring Boot + Spring Validation + Thymeleaf. Темы упомянутые в данной статье включают:

  1. Создать Form регистрации на Spring.
  2. Использовать Spring Validator для подтверждения (validate) информации, которую ввел пользователь.
  3. Объявнить принцип работы Spring Validator.
Просмотр приложения:

2- Создать Spring Boot project

На  Eclipse создать проект  Spring Boot.
Ввести:
  • Name: SbRegistrationFormValidationThymeleaf
  • Group: org.o7planning
  • Description: Spring Boot + Form Validation + Thymeleaf
  • Package: org.o7planning.sbformvalidation
Выбрать технологии и библиотеки для использования:
  • Security
  • Validation
  • Web
  • Thymeleaf
OK, Project создан.
SbRegistrationFormValidationThymeleafApplication.java
package org.o7planning.sbformvalidation;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class SbRegistrationFormValidationThymeleafApplication {

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

 

3- Конфигурация pom.xml

В данном примере мы используем библиотеку  Commons Validation чтобы проверить точность электронную почту, которую ввел пользователь. поэтому нужно объявить данную библиотеку в  pom.xml.
** Commons Validation **
<dependencies>
    .....

        <!-- https://mvnrepository.com/artifact/commons-validator/commons-validator -->
    <dependency>
        <groupId>commons-validator</groupId>
        <artifactId>commons-validator</artifactId>
        <version>1.6</version>
    </dependency>

        .....    
</dependencies>
Полное содержание файла  pom.xml:
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
             http://maven.apache.org/xsd/maven-4.0.0.xsd">
            
    <modelVersion>4.0.0</modelVersion>

    <groupId>org.o7planning</groupId>
    <artifactId>SbRegistrationFormValidationThymeleaf</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>jar</packaging>

    <name>SbRegistrationFormValidationThymeleaf</name>
    <description>Spring Boot + Form Validation + Thymeleaf</description>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.0.0.M5</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <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.springframework.boot</groupId>
            <artifactId>spring-boot-starter-validation</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        
        <!-- https://mvnrepository.com/artifact/commons-validator/commons-validator -->
        <dependency>
            <groupId>commons-validator</groupId>
            <artifactId>commons-validator</artifactId>
            <version>1.6</version>
        </dependency>

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

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

    <repositories>
        <repository>
            <id>spring-snapshots</id>
            <name>Spring Snapshots</name>
            <url>https://repo.spring.io/snapshot</url>
            <snapshots>
                <enabled>true</enabled>
            </snapshots>
        </repository>
        <repository>
            <id>spring-milestones</id>
            <name>Spring Milestones</name>
            <url>https://repo.spring.io/milestone</url>
            <snapshots>
                <enabled>false</enabled>
            </snapshots>
        </repository>
    </repositories>

    <pluginRepositories>
        <pluginRepository>
            <id>spring-snapshots</id>
            <name>Spring Snapshots</name>
            <url>https://repo.spring.io/snapshot</url>
            <snapshots>
                <enabled>true</enabled>
            </snapshots>
        </pluginRepository>
        <pluginRepository>
            <id>spring-milestones</id>
            <name>Spring Milestones</name>
            <url>https://repo.spring.io/milestone</url>
            <snapshots>
                <enabled>false</enabled>
            </snapshots>
        </pluginRepository>
    </pluginRepositories>


</project>

4- Security, MessageSource

В данном примере мы не концентрируемся на вопрос безопасности приложения. Но нам понадобится библиотека  Spring Security, чтобы кодировать (encode) пароль пользователя, перед тем как сохранить в базу данных. И вам нужно объявить  Spring BEAN для кодирования пароля.
WebSecurityConfig.java
package org.o7planning.sbformvalidation.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
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.crypto.password.PasswordEncoder;

@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

	@Bean
	public PasswordEncoder passwordEncoder() {
		BCryptPasswordEncoder bCryptPasswordEncoder = new BCryptPasswordEncoder();
		return bCryptPasswordEncoder;
	}

	// In this example we do not use Security.
	// Override this method with empty code
	// to disable the default Spring Boot security.
	@Override
	protected void configure(HttpSecurity http) throws Exception {
		// Empty code!
	}
}
В данном примере мы имеет файл  validation.properties. Данный файл содержит коды ошибок (Error code), используются для оповещения пользователя когда они вводят неправильную информацию.
validation.properties
NotEmpty.appUserForm.userName=User name is required
NotEmpty.appUserForm.firstName=First Name is required
NotEmpty.appUserForm.lastName=Last name is required
NotEmpty.appUserForm.email=Email is required
NotEmpty.appUserForm.password=Password is required
NotEmpty.appUserForm.confirmPassword=Confirm Password is required
NotEmpty.appUserForm.gender=Gender is required
NotEmpty.appUserForm.countryCode=Country is required

Pattern.appUserForm.email=Invalid email
Duplicate.appUserForm.email=Email has been used by another account
Duplicate.appUserForm.userName=Username is not available
Match.appUserForm.confirmPassword=Password does not match the confirm password
Вам нужно объявить  MessageResource Spring Bean, чтобы  Spring автоматически скачал (load) содержание файла  validation.properties в память.
WebConfiguration.java
package org.o7planning.sbformvalidation.config;

import org.springframework.context.MessageSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.support.ReloadableResourceBundleMessageSource;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
@EnableWebMvc
public class WebConfiguration implements WebMvcConfigurer {

	@Bean
	public MessageSource messageSource() {
		ReloadableResourceBundleMessageSource messageSource = new ReloadableResourceBundleMessageSource();
		// Load file: validation.properties
		messageSource.setBasename("classpath:validation");
		messageSource.setDefaultEncoding("UTF-8");
		return messageSource;
	}

}

5- Model, DAO

Класс  AppUser представляет запись (record) таблицы  APP_USER. Он является пользователем (user) успешно зарегистрированный в систему.
AppUser.java
package org.o7planning.sbformvalidation.model;

public class AppUser {
    

    private Long userId;
    private String userName;
    private String firstName;
    private String lastName;
    private boolean enabled;
    private String gender;
    private String email;
    private String encrytedPassword;
    
    private String countryCode;

    public AppUser() {

    }

    public AppUser(Long userId, String userName, String firstName, String lastName, //
            boolean enabled, String gender, //
            String email,String countryCode, String encrytedPassword) {
        super();
        this.userId = userId;
        this.userName = userName;
        this.firstName = firstName;
        this.lastName = lastName;
        this.enabled = enabled;
        this.gender = gender;
        this.email = email;
        this.countryCode= countryCode;
        this.encrytedPassword = encrytedPassword;
    }

    public Long getUserId() {
        return userId;
    }

    public void setUserId(Long userId) {
        this.userId = userId;
    }

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    public String getFirstName() {
        return firstName;
    }

    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }

    public String getLastName() {
        return lastName;
    }

    public void setLastName(String lastName) {
        this.lastName = lastName;
    }

    public boolean isEnabled() {
        return enabled;
    }

    public void setEnabled(boolean enabled) {
        this.enabled = enabled;
    }

    public String getGender() {
        return gender;
    }

    public void setGender(String gender) {
        this.gender = gender;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public String getEncrytedPassword() {
        return encrytedPassword;
    }

    public void setEncrytedPassword(String encrytedPassword) {
        this.encrytedPassword = encrytedPassword;
    }

    public String getCountryCode() {
        return countryCode;
    }

    public void setCountryCode(String countryCode) {
        this.countryCode = countryCode;
    }

}

 
Country.java
package org.o7planning.sbformvalidation.model;

public class Country {

    private String countryCode;
    private String countryName;

    public Country() {

    }

    public Country(String countryCode, String countryName) {
        this.countryCode = countryCode;
        this.countryName = countryName;
    }

    public String getCountryCode() {
        return countryCode;
    }

    public void setCountryCode(String countryCode) {
        this.countryCode = countryCode;
    }

    public String getCountryName() {
        return countryName;
    }

    public void setCountryName(String countryName) {
        this.countryName = countryName;
    }
}
 
Gender.java
package org.o7planning.sbformvalidation.model;

public class Gender {

    public static final String MALE = "M";
    public static final String FEMALE = "F";
}

 
Классы  DAO (Data Access Object) используются для манипуляции с ресурсами данных, как например  query, insert, update, delete. Данные классы обычно аннотированы (annotate) с помощью  @Repository чтобы  Spring управлял ими как  Spring BEAN.
AppUserDAO.java
package org.o7planning.sbformvalidation.dao;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.o7planning.sbformvalidation.formbean.AppUserForm;
import org.o7planning.sbformvalidation.model.AppUser;
import org.o7planning.sbformvalidation.model.Gender;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Repository;

@Repository
public class AppUserDAO {

    // Config in WebSecurityConfig
    @Autowired
    private PasswordEncoder passwordEncoder;

    private static final Map<Long, AppUser> USERS_MAP = new HashMap<>();

    static {
        initDATA();
    }

    private static void initDATA() {
        String encrytedPassword = "";

        AppUser tom = new AppUser(1L, "tom", "Tom", "Tom", //
                true, Gender.MALE, "tom@waltdisney.com", encrytedPassword, "US");

        AppUser jerry = new AppUser(2L, "jerry", "Jerry", "Jerry", //
                true, Gender.MALE, "jerry@waltdisney.com", encrytedPassword, "US");

        USERS_MAP.put(tom.getUserId(), tom);
        USERS_MAP.put(jerry.getUserId(), jerry);
    }

    public Long getMaxUserId() {
        long max = 0;
        for (Long id : USERS_MAP.keySet()) {
            if (id > max) {
                max = id;
            }
        }
        return max;
    }

    //

    public AppUser findAppUserByUserName(String userName) {
        Collection<AppUser> appUsers = USERS_MAP.values();
        for (AppUser u : appUsers) {
            if (u.getUserName().equals(userName)) {
                return u;
            }
        }
        return null;
    }

    public AppUser findAppUserByEmail(String email) {
        Collection<AppUser> appUsers = USERS_MAP.values();
        for (AppUser u : appUsers) {
            if (u.getEmail().equals(email)) {
                return u;
            }
        }
        return null;
    }

    public List<AppUser> getAppUsers() {
        List<AppUser> list = new ArrayList<>();

        list.addAll(USERS_MAP.values());
        return list;
    }

    public AppUser createAppUser(AppUserForm form) {
        Long userId = this.getMaxUserId() + 1;
        String encrytedPassword = this.passwordEncoder.encode(form.getPassword());

        AppUser user = new AppUser(userId, form.getUserName(), //
                form.getFirstName(), form.getLastName(), false, //
                form.getGender(), form.getEmail(), form.getCountryCode(), //
                encrytedPassword);

        USERS_MAP.put(userId, user);
        return user;
    }

}
 
CountryDAO.java
package org.o7planning.sbformvalidation.dao;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.o7planning.sbformvalidation.model.Country;
import org.springframework.stereotype.Repository;

@Repository
public class CountryDAO {

    private static final Map<String, Country> COUNTRIES_MAP = new HashMap<>();

    static {
        initDATA();
    }

    private static void initDATA() {

        Country vn = new Country("VN", "Vietnam");
        Country en = new Country("EN", "England");
        Country fr = new Country("FR", "France");
        Country us = new Country("US", "US");
        Country ru = new Country("RU", "Russia");

        COUNTRIES_MAP.put(vn.getCountryCode(), vn);
        COUNTRIES_MAP.put(en.getCountryCode(), en);
        COUNTRIES_MAP.put(fr.getCountryCode(), fr);
        COUNTRIES_MAP.put(us.getCountryCode(), us);
        COUNTRIES_MAP.put(ru.getCountryCode(), ru);
    }

    public Country findCountryByCode(String countryCode) {
        return COUNTRIES_MAP.get(countryCode);
    }

    public List<Country> getCountries() {
        List<Country> list = new ArrayList<>();
        list.addAll(COUNTRIES_MAP.values());
        return list;
    }

}

 

6- Form Bean, Validator

Класс  AppUserForm представляет данные, которые пользователь должен ввести на Form регистрации.
AppUserForm.java
package org.o7planning.sbformvalidation.formbean;

public class AppUserForm {

    private Long userId;
    private String userName;
    private String firstName;
    private String lastName;
    private boolean enabled;
    private String gender;
    private String email;
    private String password;
    private String confirmPassword;
    private String countryCode;

    public AppUserForm() {

    }

    public AppUserForm(Long userId, String userName, //
            String firstName, String lastName, boolean enabled, //
            String gender, String email, String countryCode, //
            String password, String confirmPassword) {
        this.userId = userId;
        this.userName = userName;
        this.firstName = firstName;
        this.lastName = lastName;
        this.enabled = enabled;
        this.gender = gender;
        this.email = email;
        this.countryCode = countryCode;
        this.password = password;
        this.confirmPassword = confirmPassword;
    }

    public Long getUserId() {
        return userId;
    }

    public void setUserId(Long userId) {
        this.userId = userId;
    }

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    public String getFirstName() {
        return firstName;
    }

    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }

    public String getLastName() {
        return lastName;
    }

    public void setLastName(String lastName) {
        this.lastName = lastName;
    }

    public boolean isEnabled() {
        return enabled;
    }

    public void setEnabled(boolean enabled) {
        this.enabled = enabled;
    }

    public String getGender() {
        return gender;
    }

    public void setGender(String gender) {
        this.gender = gender;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public String getCountryCode() {
        return countryCode;
    }

    public void setCountryCode(String countryCode) {
        this.countryCode = countryCode;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String getConfirmPassword() {
        return confirmPassword;
    }

    public void setConfirmPassword(String confirmPassword) {
        this.confirmPassword = confirmPassword;
    }
}

 
Класс  AppUserValidator используется для валидации (validate) информации, которую ввел пользовтель в Form. Таким образом  AppUserValidator валидирует (validate) значения полей (field) объектов  AppUserForm.
AppUserValidator.java
package org.o7planning.sbformvalidation.validator;

import org.apache.commons.validator.routines.EmailValidator;
import org.o7planning.sbformvalidation.dao.AppUserDAO;
import org.o7planning.sbformvalidation.formbean.AppUserForm;
import org.o7planning.sbformvalidation.model.AppUser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.validation.Errors;
import org.springframework.validation.ValidationUtils;
import org.springframework.validation.Validator;

@Component
public class AppUserValidator implements Validator {

	// common-validator library.
	private EmailValidator emailValidator = EmailValidator.getInstance();

	@Autowired
	private AppUserDAO appUserDAO;

	// The classes are supported by this validator.
	@Override
	public boolean supports(Class<?> clazz) {
		return clazz == AppUserForm.class;
	}

	@Override
	public void validate(Object target, Errors errors) {
		AppUserForm appUserForm = (AppUserForm) target;

		// Check the fields of AppUserForm.
		ValidationUtils.rejectIfEmptyOrWhitespace(errors, "userName", "NotEmpty.appUserForm.userName");
		ValidationUtils.rejectIfEmptyOrWhitespace(errors, "firstName", "NotEmpty.appUserForm.firstName");
		ValidationUtils.rejectIfEmptyOrWhitespace(errors, "lastName", "NotEmpty.appUserForm.lastName");
		ValidationUtils.rejectIfEmptyOrWhitespace(errors, "email", "NotEmpty.appUserForm.email");
		ValidationUtils.rejectIfEmptyOrWhitespace(errors, "password", "NotEmpty.appUserForm.password");
		ValidationUtils.rejectIfEmptyOrWhitespace(errors, "confirmPassword", "NotEmpty.appUserForm.confirmPassword");
		ValidationUtils.rejectIfEmptyOrWhitespace(errors, "gender", "NotEmpty.appUserForm.gender");
		ValidationUtils.rejectIfEmptyOrWhitespace(errors, "countryCode", "NotEmpty.appUserForm.countryCode");

		if (!this.emailValidator.isValid(appUserForm.getEmail())) {
			// Invalid email.
			errors.rejectValue("email", "Pattern.appUserForm.email");
		} else if (appUserForm.getUserId() == null) {
			AppUser dbUser = appUserDAO.findAppUserByEmail(appUserForm.getEmail());
			if (dbUser != null) {
				// Email has been used by another account.
				errors.rejectValue("email", "Duplicate.appUserForm.email");
			}
		}

		if (!errors.hasFieldErrors("userName")) {
			AppUser dbUser = appUserDAO.findAppUserByUserName(appUserForm.getUserName());
			if (dbUser != null) {
				// Username is not available.
				errors.rejectValue("userName", "Duplicate.appUserForm.userName");
			}
		}

		if (!errors.hasErrors()) {
			if (!appUserForm.getConfirmPassword().equals(appUserForm.getPassword())) {
				errors.rejectValue("confirmPassword", "Match.appUserForm.confirmPassword");
			}
		}
	}

}

7- Controller

MainController.java
package org.o7planning.sbformvalidation.controller;

import java.util.List;

import org.o7planning.sbformvalidation.dao.AppUserDAO;
import org.o7planning.sbformvalidation.dao.CountryDAO;
import org.o7planning.sbformvalidation.formbean.AppUserForm;
import org.o7planning.sbformvalidation.model.AppUser;
import org.o7planning.sbformvalidation.model.Country;
import org.o7planning.sbformvalidation.validator.AppUserValidator;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
// import org.springframework.transaction.annotation.Transactional;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.InitBinder;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;

@Controller
public class MainController {

   @Autowired
   private AppUserDAO appUserDAO;

   @Autowired
   private CountryDAO countryDAO;

   @Autowired
   private AppUserValidator appUserValidator;

   // Set a form validator
   @InitBinder
   protected void initBinder(WebDataBinder dataBinder) {
      // Form target
      Object target = dataBinder.getTarget();
      if (target == null) {
         return;
      }
      System.out.println("Target=" + target);

      if (target.getClass() == AppUserForm.class) {
         dataBinder.setValidator(appUserValidator);
      }
      // ...
   }

   @RequestMapping("/")
   public String viewHome(Model model) {

      return "welcomePage";
   }

   @RequestMapping("/members")
   public String viewMembers(Model model) {

      List<AppUser> list = appUserDAO.getAppUsers();

      model.addAttribute("members", list);

      return "membersPage";
   }

   @RequestMapping("/registerSuccessful")
   public String viewRegisterSuccessful(Model model) {

      return "registerSuccessfulPage";
   }

   // Show Register page.
   @RequestMapping(value = "/register", method = RequestMethod.GET)
   public String viewRegister(Model model) {

      AppUserForm form = new AppUserForm();
      List<Country> countries = countryDAO.getCountries();

      model.addAttribute("appUserForm", form);
      model.addAttribute("countries", countries);

      return "registerPage";
   }

   // This method is called to save the registration information.
   // @Validated: To ensure that this Form
   // has been Validated before this method is invoked.
   @RequestMapping(value = "/register", method = RequestMethod.POST)
   public String saveRegister(Model model, //
         @ModelAttribute("appUserForm") @Validated AppUserForm appUserForm, //
         BindingResult result, //
         final RedirectAttributes redirectAttributes) {

      // Validate result
      if (result.hasErrors()) {
         List<Country> countries = countryDAO.getCountries();
         model.addAttribute("countries", countries);
         return "registerPage";
      }
      AppUser newUser= null;
      try {
         newUser = appUserDAO.createAppUser(appUserForm);
      }
      // Other error!!
      catch (Exception e) {
         List<Country> countries = countryDAO.getCountries();
         model.addAttribute("countries", countries);
         model.addAttribute("errorMessage", "Error: " + e.getMessage());
         return "registerPage";
      }

      redirectAttributes.addFlashAttribute("flashUser", newUser);
      
      return "redirect:/registerSuccessful";
   }

}

8- Thymeleaf Template

_menu.html
<div xmlns:th="http://www.thymeleaf.org"
     style="border: 1px solid #ccc;padding:5px;margin-bottom:20px;">

  <a th:href="@{/}">Home</a>

     | &nbsp;

   <a th:href="@{/members}">Members</a>

     | &nbsp;

   <a th:href="@{/register}">Register</a>
  

</div>
membersPage.html
<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
   <head>
      <title th:utext="${title}"></title>
   </head>
   
   <style>
      table th, table td {
         padding: 5px;
      }
      .message {
         color: blue;
      }
   </style>
   
   <body>
   
      <!-- Include _menu.html -->
      <th:block th:include="/_menu"></th:block>  
      
      <h2>Members</h2>
      
   
      
      <table border="1">
            <tr>
               <th>User Name</th>
               <th>First Name</th>
               <th>Last Name</th>
               <th>Email</th>
               <th>Gender</th>
            </tr>
            <tr th:each ="member : ${members}">
               <td th:utext="${member.userName}">...</td>
               <td th:utext="${member.firstName}">...</td>
               <td th:utext="${member.lastName}">...</td>
               <td th:utext="${member.email}">...</td>
               <td th:utext="${member.gender}">...</td>
            </tr>
      </table>
      
   </body>
</html>

 
registerPage.html
<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
   <head>
      <title th:utext="${title}"></title>
      <style>
         th, td {
         padding: 5px;
         }
         td span  {
         font-size:90%;
         font-style: italic;
         color: red;
         }
         .error {
         color: red;
         font-style: italic;
         }
      </style>
   </head>
   <body>
      <!-- Include _menu.html -->
      <th:block th:include="/_menu"></th:block>
      
      <h2>Register</h2>
      
      <div th:if="${errorMessage != null}"
           th:utext="${errorMessage}" class="error">...</div>
      
      <form th:action="@{/register}" th:object="${appUserForm}" method="POST">
         <table>
            <tr>
               <td>User Name</td>
               <td><input type="text" th:field="*{userName}" /></td>
               <td>
                  <span th:if="${#fields.hasErrors('userName')}" th:errors="*{userName}">..</span>
               </td>
            </tr>
            <tr>
               <td>Password</td>
               <td><input type="password" th:field="*{password}" /> </td>
               <td>
                  <span th:if="${#fields.hasErrors('password')}" th:errors="*{password}">..</span>
               </td>
            </tr>
            <tr>
               <td>Confirm</td>
               <td><input type="password" th:field="*{confirmPassword}" /> </td>
               <td>
                  <span th:if="${#fields.hasErrors('confirmPassword')}" th:errors="*{confirmPassword}">..</span>
               </td>
            </tr>
            <tr>
               <td>Email</td>
               <td><input type="text" th:field="*{email}" /> </td>
               <td>
                  <span th:if="${#fields.hasErrors('email')}" th:errors="*{email}">..</span>
               </td>
            </tr>
            <tr>
               <td>First Name</td>
               <td><input type="text" th:field="*{firstName}" /> </td>
               <td>
                  <span th:if="${#fields.hasErrors('firstName')}" th:errors="*{firstName}">..</span>
               </td>
            </tr>
            <tr>
               <td>Last Name</td>
               <td><input type="text" th:field="*{lastName}" /> </td>
               <td>
                  <span th:if="${#fields.hasErrors('lastName')}" th:errors="*{lastName}">..</span>
               </td>
            </tr>
            <tr>
               <td>Gender</td>
               <td>
                  <select th:field="*{gender}">
                     <option value=""> -- </option>
                     <option value="M">Male</option>
                     <option value="F">Female</option>
                  </select>
               </td>
               <td>
                  <span th:if="${#fields.hasErrors('gender')}" th:errors="*{gender}">..</span>
               </td>
            </tr>
            <tr>
               <td>Country</td>
               <td>
                  <select th:field="*{countryCode}">
                     <option value=""> -- </option>
                     <option th:each="country : ${countries}"
                        th:value="${country.countryCode}"
                        th:utext="${country.countryName}"/>
                  </select>
               <td><span th:if="${#fields.hasErrors('countryCode')}" th:errors="*{countryCode}">..</span></td>
            </tr>
            <tr>
               <td>&nbsp;</td>
               <td>
                  <input type="submit" value="Submit" />
                  <a th:href="@{/}">Cancel</a>
               </td>
               <td>&nbsp;</td>
            </tr>
         </table>
      </form>
      
   </body>
</html>

 
registerSuccessfulPage.html
<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
   <head>
      <title>Successfully registered</title>
      <style>
        span {color: blue;}
      </style>
   </head>
   
   <body>
   
      <!-- Include _menu.html -->
      <th:block th:include="/_menu"></th:block>  
      
      <h2>You have successfully registered!</h2>
      
      <div th:if="${flashUser != null}">
         <ul>
            <li>User Name: <span th:utext="${flashUser.userName}">..</span></li>
            <li>Email: <span th:utext="${flashUser.email}">..</span></li>
         </ul>
      </div>
     
      
   </body>
</html>

 
welcomePage.html
<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
   <head>
      <title th:utext="${title}"></title>
   </head>
   
   <body>
   
      <!-- Include _menu.html -->
      <th:block th:include="/_menu"></th:block>  
      
      <h2>Home Page!</h2>
      
   </body>
</html>

 

9- Запуск приложения

Нажать на правую кнопку мыши на project выбрать:
  • Run As/Spring Boot App

View more categories: