Spring Boot, Spring Framework, Hibernate ORM ve Thymeleaf ile bir blog sitesi

Bütün detaylarına girersem bu yazı bir yazı dizisine dönüşür. :) Fakat 4 temel + 2 tamamlayıcı bileşen ile böyle bir web sitesini oluşturmak için kendi tecrübelerime dayanarak birkaç kilometre taşını belirtebilir ve açıklayabilirim. İlerleyen günlerde Yazılım kategorisinde bazı konularda detaylı yazılar da paylaşabilirim. Şimdilik ilk adımı atalım. Ben bir yazılımcıyım ve güncel ve yaygın teknolojiler kullanarak bir web sitesi hazırlamak istiyorum diyorsanız buyurun.

#1. Proje çatısı (Spring Boot + Spring Framework)

Günümüzde çok yaygın kullanılan spring framework yazılım geliştirme metodolojisini değiştirmekte ve spring boot altyapısı ile hızlandırmaktadır. İlk aşamada bize lazım olan bir spring boot projesidir. Bunun için Spring Initilizr adresine gidip aşağıdaki resimdeki gibi bir template oluşturabilirsiniz.

Bu ekranda sol taraftakiler tamamlayıcı teknolojilerden birisi olan maven için gerekli. Bu bilgiler sayesinde maven projenize bir hiyerarşik yapı verecek ve paketleyecek. Proje çıktısı jar olabilir çünkü spring boot aslında içinde bir main class olan uygulamadır.

#2. Bağımlılıklar (Dependencies)

İlk sıradaki dependency devtools sayesinde projeniz güncellediğinizde hemen derlenir ve kendi içindeki sunucuya deploy edilir. Bu yüzden ekstra bir tomcat gibi bir sunucu ihtiyacınız olmaz. Run as spring boot application seçeneği ile projeniz ayağa kalkar ve localhost://8080 'de çalışmaya başlar.

İkinci sıradaki Lombok şart olmayan bir kütüphanedir. Kodunuz içerisinde entitiy 'leriniz olacak ve bu entity 'ler getter setter ve constructor metodları içermek zorunda kalacak. Lombok sayesinde bu kodları tekrar tekrar yazmak zorunda kalmazsınız. Eclipse ile çalışabilmesi için Web Sitesinden bir eklenti indirip kurmanız gerekmektedir.

Sonraki Spring Web az önce söylediğim web uygulaması olarak çalışmasını sağlıyor. İçerisinde tomcat otomatik olarak geliyor ve devtools ile buraya deploy ediliyor. Run on server yerine run as spring boot aplication ile ayağa kalkıyor. Spring boot bu şekilde sizi tembelleştirerek işleri hallediyor. :)

Thymeleaf ise MVC dizaynı ile kullanabileceğiniz güzel bir html etikek kütüphanesi yani tag library. Önyüze aktarılan bilgileri çeşitli yapılarda html verisine dönüştürüyorsunuz mesela th:each gibi bir komut ile bir elemanı for döngüsü gibi çoğaltabiliyorsunuz. Spring framework ile iç içe çok verimli çalışabiliyorlar. Detaylar burada.

Bir sonraki ise Spring Security ile erişim kontrolü, şifre koruması veya cross site script koruması gibi işlevleri olabiliyor. Bu konuda derinlemesine bilgim yok fakat spring securty 'yi sitenizin admin sayfası için kullanacaksınız muhtemelen. :)

Spring data JPA ise veritabanı işlemlerinizi native sql ifadeleri yazmadan gerçekleştirebilmenizi sağlıyor. Aynı zamanda veri modellerinizi (entity) kodunuz içerisinde yazdığınız sınıflarla tanımlamanızı ve güncellemenizi de sağlayarak geliştirme sürecini anlaşılır ve hızlı hale getirebiliyor.

MS SQL Server Driver yerine farklı veritabanları (MySql, Oracle, PostgreSql gibi) kullanılabilir. Bu dependency örnek olması açısından burada. Fakat bir veritabanına bağlanmak için bu teknolojilerden herhangi birini kullanmanız şart.

#3. Backend tamam, arayüz nerede?

Arayüz için thymeleaf kütüphanesinin özelliklerinden yararlanacağız fakat profesyonel css javascript arayüzleri yazamıyorsanız veya angular react gibi kütüphaneler konusunda bilginiz yoksa (benim gibi) internette hazır çok sayıda template bulunuyor. Tabi bir link ile tasarımı yapan siteye atıfta bulunarak. Ben ColorLib ile template bulup üzerine kod ile geliştirme yapmayı tercih ettim. Çoğunlukla wordpress temaları olsa da html + bootsrap (yani css) ile hazırlanmış şablonları da var.

#4. Proje geliştirmeye hazır

Bir tema bulup veya hazırlayıp projeye dahil ettikten sonra (templates altındaki index.html sayfası mesela) projenin eclipse 'de aşağıdakine benzer bir yapıda görünmesi lazım. Eclipse 'de Import Existing Maven Project işlemi ile tabi.

Eclipse için marketten Spring Tools Suite eklentisini de kurmayı unutmamalısınız.

Üstteki MysiteApplication.java main class 'tır ve spring boot 'u harekete geçirir. Resources altındaki static klasörü içinde resim, css, javascript dosyaları yer almalıdır. Thymeleaf ve spring boot ikilisi bu klasörü yapısı ile çalışır. Templates klasörü ise web sayfalarınız olacaktır. Index.html burada mesela. application.properties uygulamanın kullanacağı esas bilgileri içerecektir. Veritabanı bağlantıları loglama seviyesi mail sunucusu ...vs gibi. En alttaki pom.xml ise bağımlılıkları ve derleme işlemin yöneten xml konfigürasyonudur.

Bu proje şu anda run as -> spring boot application şeklinde çalıştırılmaya hazırdır teknik olarak fakat spring boot ayağa kalkarken mssql driver yüzünden veritabanı bağlantı bilgileri isteyecektir. Örnek olarak mssql için application.properties dosyasında aşağıdaki gibi bilgiler gerekecektir:

		
spring.datasource.url = jdbc://adres:port; databaseName=mysitedatabase;
spring.datasource.driverClassName = com.microsoft.sqlserver.jdbc.SQLServerDriver
spring.datasource.username = username
spring.datasource.password = password
spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.SQLServer2012Dialect
spring.security.user.name = admin
spring.security.user.password = password
spring.jpa.hibernate.ddl-auto = update
spring.jpa.properties.hibernate.current_session_context_class = org.springframework.orm.hibernate5.SpringSessionContext
		
	

Bu şekilde kullandığınız veritabanı bilgilerini yazdıktan sonra http://localhost:8080/index.html adresine gittiğinizde karşınıza kapı gibi spring security çıkar ve kullanıcı adı şifre ister. Properties 'deki gibi spring.security.user.name ve password ile geçebilirsiniz. (Evet 404 gibi bir hata alacaksınız geçince ama o sonra)

Security 'yi tabi sadece admin sayfası gibi alanlarda yapacaksınız muhtemelen. Bunun için aşağıdaki gibi bir sınıfı projeye dahil etmelisiniz. /admin sayfası kullanıcı adı şifre isteyecek ve geri kalan sayfalar direkt olarak açılacaktır.

			
@Configuration
@EnableWebSecurity
public class CustomSecurityConfig extends WebSecurityConfigurerAdapter
{
	@Override
	protected void configure(HttpSecurity http) throws Exception
	{
		http.authorizeRequests().antMatchers("/admin").authenticated().and().formLogin();
		http.authorizeRequests().antMatchers("/**").permitAll();
		http.csrf().csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse());
	}
}
			
		

@Configuration sayesinde spring framework bu sınıfı konfigürasyon sınıfı olarak görür ve örneğin spring security 'yi ayağa kaldırırken bu annotation ile işaretlenmiş sınıflar arar. WebSecurityConfigurerAdapter sınıfından extend edildiği için güvenlik için kullanılacağı anlaşılır. Daha doğrusu spring security 'nin kullanabileceği bir bean olduğu anlaşılır.

Bu şekilde security ayarını basic seviyede yapmış oluyoruz ve anasayfamızı yani index sayfasını hazırlamaya geçiyoruz. Veritabanında tutacağınız hibernate entity 'lerini yani nesnelerini (tabloları) tanımlamak gerekiyor öncelikle. Çünkü açılan sayfada bir sorgu yapıp ekrana sonuç getireceğiz en basit anlamda. Bunun için bir örnek aşağıdaki gibi olabilir:

		
@Entity
@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
@Table(name = "POST")
public class Post
{
	@Id
	@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "post_seq")
	@SequenceGenerator(name = "post_seq", sequenceName = "post_seq", allocationSize = 1)
	@Column(name = "ID", nullable = false)
	private int id;

	@Nationalized
	@Column(name = "TITLE", nullable = false, length = 1500)
	private String title;

	@Nationalized
	@Column(name = "CONTENT", nullable = false, length = 1000)
	private String content;

	@Nationalized
	@Column(name = "SUMMARY", nullable = false, length = 2000)
	private String summary;

	@ManyToOne(fetch = FetchType.EAGER)
	@JoinColumn(name = "CATEGORY", referencedColumnName = "ID", nullable = false)
	private Category category;

	@OneToMany(fetch = FetchType.LAZY, mappedBy = "post")
	@Where(clause = "active = 1")
	private List<Comment> comments;

	@ManyToMany(fetch = FetchType.LAZY)
	@JoinTable(name = "post_tags", joinColumns = @JoinColumn(name = "post_ID"), inverseJoinColumns = @JoinColumn(name = "TAG_ID"))
	private List<Tag> tags;

	@Column(name = "PUB_DATE", nullable = false)
	private Date publish_date = new Date();
}
		
	

@Entity tabi ki entity yani tablo olduğunu belirtiyor. @Getter, @Setter, @AllArgsConstructor, @NoArgsConstructor sayesinde Lombok kodları var sayıyor ve inject ediyor. Biz de boşuna tekrar tekrar yazmıyoruz. @Table ile veritabanındaki tablo ismini best practice olması adına belirtiyoruz.

Tabi buradaki join 'lerle ilgili söylenebilecek çok şey var ben örnek olarak n-1 Category, n-n Tag ve 1-n Comment sınıflarını da yazdım. Siz kendi sitenizde kendi veritabanı yapınızı geliştireceğiniz için detaylandırmanın mantığı olmayacak. Ama buna benzer ilişkiler mutlaka kuracaksınız.

@Nationalized ile MSSQL 'de türkçe karakter sorununu da çözüyorsunuz. Bu nesneleri yöneten veritabanı erişim sınıfı yazacaksınız tabi CRUD işlemleri için. İlk yazınızı yani post 'unuzu veritabanına manuel olarak eklediğinizi farz edersek basit bir örnek:

		
@Repository
public class SiteRepository
{
	private EntityManager em;

	@Autowired
	public SiteRepository(EntityManagerFactory factory)
	{
		this.em = factory.createEntityManager();
	}
	public List<Post> get_all_posts()
	{
		List<Post> res = null;
		Session session = em.unwrap(Session.class);
		CriteriaBuilder builder = session.getCriteriaBuilder();
		CriteriaQuery<Post> criteria_query = builder.createQuery(Post.class);
		Root<Post> root = criteria_query.from(Post.class);
		criteria_query.orderBy(builder.desc(root.get("publish_date")));
		Query<Post> query = session.createQuery(criteria_query);
		res = query.getResultList();
		return res;
	}
}
		
	

@Repository de @Component yada @Service gibi bir spring anotasyonudur. Veritabanına erişim yapan sınıflar için best practice olarak kullanılmaktadır. @CriteriaQuery ile Post sınıfından where koşulu olmadan sorgu çekiyor bu örnek. Ayrıca publish_date sütununua göre büyküten küçüğe sıralıyor. Criteria API deprecated olunca criteria query hayata geçti hibernate tarafında. Session nesneleri de EntityManager 'dan unwrap metodu ile kullanılıyor.

Sonrasında /index.html ile browser 'a gitmeye çalıştığınızda index sayfasını bulamadım hatası alacaksınız. Burada bir yönlendirme yapılması gerekiyor ve bunun için spring framework 'ün controller yapısını kullanacaksınız. Burada veritabanı işlemleri de var tabi repository ve entity sınıflarımız hazır. ModelAndView nesnesi ile index view 'unu döndürüyor ve içerisine post listesini ekliyoruz. Örnek:

		
@Controller
public class Maincontroller
{
	private SiteRepository repository;

	private List<Post> all_posts;

	@Autowired
	public Maincontroller(SiteRepository post_repository)
	{
		this.repository = post_repository;
		this.all_posts = this.repository.get_all_posts();
	}
	@GetMapping(path =
	{ "", "index", "index.html" })
	public ModelAndView home()
	{
		ModelAndView modelAndView = new ModelAndView("index");
		modelAndView.addObject("posts", this.all_posts);
		return modelAndView;
	}
}
		
	

@Controller sayesinde spring boot ayağa kalkarken bu sınıfı ayağa kaldırır ve web isteklerini bu sınıfa yönlendirir. @Autowired ile repository sınıfımız da spring boot ile ayağa kaldırılıp bu sınıfa constructor aracılığı ile dahil edilir. @GetMapping ise bu controller 'ın home metodunun / veya /index veya /index.html şeklinde gelen GET isteklerine cevap vereceğini belirtir. Bu şekilde template 'in index sayfasını geitirmek için gereken back-end kodu hazır olmuş olur.

Bu post 'ları veritabanından çektikten sonra thymeleaf th:each yardımı ile ekranda listelemek için ise aşağıdakine benzer bir kod kullanabilirsiniz belki:

			
<div th:each="post: ${posts}">
	<a th:href="@{'post?id=' + ${post.id}}" th:text="${post.title}"></a>
</div>
			
		

#5. Balık tutabiliyorsunuz artık

Blog yazılarınızı listeleyeceğiniz ilk ekranınız bu kadar kod ile hazır hale gelebiliyor. Bu noktadan sonra kendi isterlerinize göre kendi konfigürasyonunuzu yapmalısınız. Yukarıdaki kod örneklerini 1 gün içerisinde hayata geçirmeniz mümkün. Eğer yapacağınız yazılımı analiz etmişseniz bundan sonraki kısım tamamen bu yazılımı buna benzer kodlar ile geliştirmeye, spring, hibernate ve thymeleaf 'in özelliklerini kullanmaya kalıyor. Controller sınıfınız zamanla büyüyecektir. Veritabanında tuttuğunuz bilgiler ve repository sınıfınız değişecektir. Bu yazının amacı temel çerçeveyi oturtmaktı. Sizlere hatasız kodlamalar diliyorum ve bir sonraki yazıda görüşmek üzere :)


Bir yorum yazabilirsiniz