Spring Boot MVC Uygulama Örneği: Kullanıcı Kayıt Formu Giriş Çıkış İşlemleri
Spring Boot Dersleri ve Spring Uygulama Örnekleri‘ne devam ediyoruz.
Spring Boot ile Thymeleaf kullanarak bir örnek uygulama geliştireceğiz. Uygulama örneğinde;
- Kullanıcı Kayıt Formu Sayfası
- Kullanıcı Giriş Formu Sayfası
- Giriş Sonrası Karşılama Sayfası
- Çıkış İşlemleri
olacaktır.
Spring Boot ile yapacağımız uygulamamızda kullanacağımız bağımlılıklar ve teknolojiler
- Spring Boot
- Spring Security
- Spring MVC
- Spring Data JPA
- Thymeleaf
- Bootstrap 4
- Java 9
- H2 Veritabanı
- Maven
şeklindedir.
Spring Boot Uygulaması yaparken kullanacağım Ide IntelliJ IDEA Ultimate 2018.3.4.
Uygulamamızı bitirdikten sonra kullanımı aşağıdaki gibi olacaktır.
Projemizi IDE yardımı ile oluşturmaya başlayalım.
Yukarıdaki resimdeki gibi gerekli bağımlılıkları ekleyerek indirme işleminin tamamlanmasını bekliyoruz ve projemizi oluşturmaya hazır hale geliyor.
Maven bağımlılığımıza bakalım.
<?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>com.burakkutbay</groupId> <artifactId>springkayitgirisuygulamasi</artifactId> <version>0.0.1-SNAPSHOT</version> <name>springkayitgirisuygulamasi</name> <description>Spring Boot</description> <packaging>jar</packaging> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.5.10.RELEASE</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-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.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <scope>runtime</scope> </dependency> <dependency> <groupId>com.h2database</groupId> <artifactId>h2</artifactId> <scope>runtime</scope> </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> <dependency> <groupId>org.webjars</groupId> <artifactId>bootstrap</artifactId> <version>3.3.7-1</version> </dependency> <dependency> <groupId>org.webjars</groupId> <artifactId>jquery</artifactId> <version>3.3.1-1</version> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
Şimdi Modellerimizi oluşturalım.
User modelimizi oluşturuyoruz.
/** * Created by burakkutbay on 14.02.2019. */ @Entity @Table(name = "personal") public class User { @Id @GeneratedValue(strategy = GenerationType.AUTO) private long id; @Column(name = "email", nullable = false) private String email; @Column(name = "password") private String password; @Column(name = "first_name") private String firstName; @Column(name = "last_name") private String lastName; @Column(name = "enabled") private boolean enabled; @Column(name = "username") private String username; @ManyToMany(fetch = FetchType.EAGER) @JoinTable(joinColumns = @JoinColumn(name = "user_id"), inverseJoinColumns = @JoinColumn(name = "role_id")) private Collection<Role> roles; public long getId() { return id; } public void setId(long id) { this.id = id; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } 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 getUsername() { return username; } public void setUsername(String username) { this.username = username; } public Collection<Role> getRoles() { return roles; } public void setRoles(Collection<Role> roles) { this.roles = roles; } }
Her kullanıcının bir rol yetkisi olacak bu rol yetkisi ile giriş işlemi sağlanacağı için Rol modeli oluşturuyoruz. User class’ı ile Rol ilişkisi ManyToMany bir ilişkidir.
Rol entitymizi oluşturalım.
/** * Created by burakkutbay on 14.02.2019. */ @Entity public class Role { @Id @GeneratedValue(strategy = GenerationType.AUTO) private long id; @Column(unique = true) private String role; @ManyToMany(mappedBy = "roles", fetch = FetchType.LAZY) private Collection<User> users; public long getId() { return id; } public void setId(long id) { this.id = id; } public String getRole() { return role; } public void setRole(String role) { this.role = role; } public Collection<User> getUsers() { return users; } public void setUsers(Collection<User> users) { this.users = users; } }
Rol entitymizi de oluşturduk.
JPA Repository’mizi oluşturalım. JPA Repository sayesinde veritabanı ile iletişimin sağlanacağı bir interface yaratmış olacağız. Bu interface’i extend ederek veritabanı entitylerimizin interfacelerini yazacağız. UserRepository ve RoleRepositroy oluşturacağız ve bu iki class da JpaRepository’den extend olacak.
UserRepository oluşturalım.
/** * Created by burakkutbay on 14.02.2019. */ public interface UserRepository extends CrudRepository<User, Long> { User findByUsername(String username); User findByEmail(String email); }
RoleRepository oluşturalım.
/** * Created by burakkutbay on 14.02.2019. */ public interface RoleRepository extends CrudRepository<Role, Long> { Role findByRole(String role); }
Spring Data sayesinde repository classlarımızdaki alanları yazarak sorgu işlemi yapabiliyoruz.
Servis Katmanına geldi sıra. Servis katmanında yapılacak işlemlerin amacı veritabanındaki kullanıcı bilgileri ile kullanıcı formu tarafından gelecek olan bilgilerin karşılaştırılması, kullanıcı kayıt sayfasından gelecek bilgilerin ise kayıt edilmesi sağlamaktadır.
/** * Created by burakkutbay on 14.02.2019. */ @Service public class UserService { @Autowired UserRepository userRepository; @Autowired RoleRepository roleRepository; @Autowired public UserService(UserRepository userRepository) { this.userRepository = userRepository; } public User findByEmail(String email) { return userRepository.findByEmail(email); } public User findByUsername(String username) { return userRepository.findByUsername(username); } public void saveUser(User user) { user.setRoles(Arrays.asList(roleRepository.findByRole("USER"))); user.setEnabled(true); userRepository.save(user); } }
Servis katmanında kullancı kaydederken UserRepository’den faydalanılıyor. Kullanıcının rolleri için ise RoleRepository kullanılmakta.
Oluşturacağımız diğer bir Servis ise kullanıcı giriş yapmak istediğinde yetkilendirme işlemin gerçekleşeceği classtır. Bu class UserDetailsService Spring Security kütüphanesinden implement edilerek metodları Override ederek kullanılıyor. Yetkilendirme işlemlerini ve kullanıcı yönetim işlemlerini Spring Security’e veriyoruz. loadUserByUsername Sadece kullanıcı sorgulayıcı metodunda userRepository.findByUsername ile kullanıcıyı bulunuyor. getAuthorities metodu ile de kullanıcıya ait rollerin veritabanından alınmasını sağlayarak Spring’e verilmesi sağlanmış oluyor.
/** * Created by burakkutbay on 14.02.2019. */ @Transactional @Service public class SSUserDetailsService implements UserDetailsService { private UserRepository userRepository; public SSUserDetailsService(UserRepository userRepository) { this.userRepository = userRepository; } @Override public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { try { User user = userRepository.findByUsername(username); if (user == null) { return null; } return new org.springframework.security.core.userdetails.User( user.getUsername(), user.getPassword(), getAuthorities(user)); } catch (Exception e) { throw new UsernameNotFoundException("User not found"); } } private Set<GrantedAuthority> getAuthorities(User user) { Set<GrantedAuthority> authorities = new HashSet<GrantedAuthority>(); for (Role role : user.getRoles()) { GrantedAuthority grantedAuthority = new SimpleGrantedAuthority(role.getRole()); authorities.add(grantedAuthority); } return authorities; } }
@Service ve @Transactional anotasyonlarını ekleyerek servis katmanı olduğu ve Transaction işlemlerini Spring’in yönetmesini sağlamaktayız. İlgini Çekebilir: @Component, @Service, @Repository, @Controller Anotasyonu
İlgini Çekebilir: Spring Component, Service, Repository, Controller Uygulama Örneği
Web sayfamız ile Java sınıflarımız arasında iletişim sağlayacak, köprü olacak sınıfımıza geldi sıra. Controller sınıfımızı oluşturacağız.
Controller sınıfımız web sayfalarımızın hangi url’de hangi sayfalara gideceğini, POST, GET işlemlerinde yapılacak işlemleri yapıyoruz.
/** * Created by burakkutbay on 14.02.2019. */ @Controller public class UserController { @Autowired UserService userService; @RequestMapping(value="/register" ,method= RequestMethod.GET) public String registerPage(Model model){ model.addAttribute("user", new User()); return "register"; } @RequestMapping(value="/register" ,method= RequestMethod.POST) public String saveRegisterPage(@Valid @ModelAttribute("user") User user, BindingResult result, Model model){ model.addAttribute("user", user); if (result.hasErrors()){ return "register"; } else { userService.saveUser(user); } return "index"; } @RequestMapping("/") public String index(){ return "index"; } @RequestMapping("/index") public String index2(){ return "index"; } @RequestMapping("/login") public String login(){ return "login"; } @RequestMapping("/secure") public String secure(){ return "secure"; } }
Controller sayfamızda, registerPage kayıt sayfamızı gösterir. saveRegisterPage ise kullanıcı kayıt sayfasından gelen verileri alarak service üzerinden kaydeder. Kullanıcı kayıt işleminde gelen veride bir sorun var ise if (result.hasErrors()) kontrol ederek kayıt işleminde geçmeden kayıt sayfasında tekrar yönlendirerek işlemlerin kaldığı yerden devam etmesi sağlanmaktadır.
Ek olarak H2 veritabanında kendinize özel değişiklik yapmak ya da h2-console açmak istebilirsiniz. Eğer bu gibi işlemleri yapmak isterseniz aşağıdaki bağlantıya bakmanızı öneririm.
İlgini Çekebilir: Spring Boot H2 Gömülü Veritabanı Kullanmak
Backend tarafını bitirdik. Şimdi geldi sıra web sayfalarını yapacağız. Thymeleaf + Bootstrap ile sayfalarımızı yapcağız.
Index.html sayfamızı yapağız ve ekran görüntüsü aşağıdaki gibi olacak.
index sayfamız ise şöyle;
<html> <head> <title>BurakKUTBAY.com Spring Örnek Uygulama</title> <meta charset="utf-8"/> <meta name="viewport" content="width=device-width, initial-scale=1"/> <link rel="stylesheet" href="/webjars/bootstrap/3.3.7-1/css/bootstrap.min.css"/> <script src="/webjars/jquery/3.3.1-1/jquery.min.js"></script> <script src="/webjars/bootstrap/3.3.7-1/js/bootstrap.min.js"></script> </head> <body> <div class="container"> <h2>Hoşgeldiniz</h2> <a href="/secure" class="btn btn-default"> Giriş Yap</a> </div> </body> </html>
Kullancı kayıt sayfamızın görüntüsü aşağıdaki gibi olacak.
Üye kayıt sayfamızın kodlarına bakalım.
<html xmlns:th="http://www.w3.org/1999/xhtml"> <head> <title>BurakKUTBAY.com Spring Örnek Uygulama</title> <meta charset="utf-8"/> <meta name="viewport" content="width=device-width, initial-scale=1"/> <link rel="stylesheet" href="/webjars/bootstrap/3.3.7-1/css/bootstrap.min.css"/> <script src="/webjars/jquery/3.3.1-1/jquery.min.js"></script> <script src="/webjars/bootstrap/3.3.7-1/js/bootstrap.min.js"></script> </head> <body> <div class="container"> <h1 class="h3 mb-3 font-weight-normal">Üye Kaydı</h1> <form autocomplete="off" action="#" th:action="@{/register}" th:object="${user}" method="post"> <label>Adnız </label> <input type="text" id="firstName" placeholder="First Name" th:field="*{firstName}" class="form-control"/><br/> <label>Soyadınız</label> <input type="text" id="lastName" placeholder="Last Name" th:field="*{lastName}" class="form-control"/><br/> <label>Eposta</label> <input type="text" id="email" placeholder=" Email" th:field="*{email}" class="form-control"/><br/> <label>Kullanıcı Adınız</label> <input type="text" id="username" placeholder=" Username" th:field="*{username}" class="form-control"/><br/> <label>Parolanız </label> <input type="text" id="password" placeholder=" Password" th:field="*{password}" class="form-control"/><br/> <button type="submit" class="btn btn-success text-center form-control">Kaydet</button> </form> <div class="margin-top20 text-center"><a th:href="@{/login}">Giriş Sayfasına Git</a></div> </div> </body> </html>
Kullanıcı Giriş Sayfası aşağıdaki gibi olacak.
Giriş kayıt ekranımızın kodları aşağıdaki gibidir.
<html xmlns:th="http://www.w3.org/1999/xhtml"> <head> <title>BurakKUTBAY.com Spring Örnek Uygulama</title> <meta charset="utf-8"/> <meta name="viewport" content="width=device-width, initial-scale=1"/> <link rel="stylesheet" href="/webjars/bootstrap/3.3.7-1/css/bootstrap.min.css"/> <script src="/webjars/jquery/3.3.1-1/jquery.min.js"></script> <script src="/webjars/bootstrap/3.3.7-1/js/bootstrap.min.js"></script> </head> <body> <div class="container"> <div class="alert alert-danger" role="alert" th:if="${param.error}"> Kullanıcı Adı veya Şifre yanlış. </div> <form th:action="@{/login}" method="post"> <h1 class="h3 mb-3 font-weight-normal">Giriş Yap</h1> <label>Kullanıcı Adınız</label> <input type="text" name="username" class="form-control"/> <label>Şifreniz</label> <input type="password" id="password" name="password" class="form-control"/> <br/> <button class="btn btn-lg btn-primary btn-block" type="submit">Giriş Yap</button> <br/> <div class="margin-top20 text-center"><a th:href="@{/register}">Üye Olma Sayfasına Git</a> </div> </form> </div> </body> </html>
Kullanıcı üye olduktan sonra karşılanacak ekran aşağıdaki gibi olacak.
Kodları ise;
<html> <head> <title>BurakKUTBAY.com Spring Örnek Uygulama</title> <meta charset="utf-8"/> <meta name="viewport" content="width=device-width, initial-scale=1"/> <link rel="stylesheet" href="/webjars/bootstrap/3.3.7-1/css/bootstrap.min.css"/> <script src="/webjars/jquery/3.3.1-1/jquery.min.js"></script> <script src="/webjars/bootstrap/3.3.7-1/js/bootstrap.min.js"></script> </head> <body> <div class="container"> <h2>Giriş Yapıldı. Hoşgeldiniz.</h2> <a href="/logout" class="btn btn-danger">Çıkış Yapın</a> </div> </body> </html>
Ve projemizin web sayfalarını da yaptıktan sonra projemiz tamamlamış olmaktadır.
Güzel kodlamalar dilerim.
Önceki Ders: HATEOAS Nedir? HATEOAS Uygulama Örneği Kullanımı |
Spring Boot Dersleri |
Sonraki Ders: Spring Boot Uygulamalarında Webjars Kullanımı |
Selamlar bu uygulama da alınan veriler database e kaydediliyor mu ?
Evet.
Database de tabloları nasıl oluşturdunuz ? sql kodları var mı? veya görsel?
Admin girişi yapmış olsaydık nasıl yapardık
Selamlar,
Hocam projeyi çalıştırdım fakat sizin ki gibi değil ilkel formda geldi sayfalar.Bunların css dosyaları yok mu ?
Bu yaptığın projeyi çalıştırmak için “3” senedir uğraşıyorum, takıntı yaptım 🙂
Thymeleaf sorunu olabilir ama login ekranı gözükürken diğer ekranlar neden basit yapıda görünüyor.
Bu proje beni deli edecek, bence yardım etmelisin bana 🙂
Arkadaşlar çalıştırırken nerede sorun yaşadınız tam olarak yardımcı olmaya çalışayım