1. Özet
Bu yazı boyunca bir spring boot uygulamasını Thymeleaf ve Jpa kullanarak gerçekleştireceğiz. Projemizi oluşturmak için Gradle kullanıcağız.
2. Uygulama Dosyaları
build.gradle
buildscript {
ext {
springBootVersion = '2.0.2.RELEASE'
}
repositories {
mavenCentral()
}
dependencies {
classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
}
}
apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'org.springframework.boot'
apply plugin: 'io.spring.dependency-management'
group = 'com.dogukanhan'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = 1.8
repositories {
mavenCentral()
}
dependencies {
compile('org.springframework.boot:spring-boot-starter-data-jpa')
compile('org.springframework.boot:spring-boot-starter-security')
compile('org.springframework.boot:spring-boot-starter-thymeleaf')
compile('org.springframework.boot:spring-boot-starter-web')
runtime('org.springframework.boot:spring-boot-devtools')
runtime('mysql:mysql-connector-java')
testCompile('org.springframework.boot:spring-boot-starter-test')
testCompile('org.springframework.security:spring-security-test')
}
settings.gradle
rootProject.name = 'spring101'
Dosyaları oluşturduktan sonra “gradle build” komutunu girelim
Proje yapısı ve src klasörünün içeriği şekildeki gibi olucaktır. Oluşturulmayan klasörleri ve dosyaları kendimiz oluşturalım veya yazının sonunda yer alan linkten indirebilirsiniz.


WebApp.java
package com.dogukanhan.spring101;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ComponentScan;
@SpringBootApplication
@ComponentScan("com.dogukanhan.spring101*")
public class WebApp {
public static void main(String[] args) {
SpringApplication.run(WebApp.class, args);
}
}
WebMvcConfig.java
package com.dogukanhan.spring101.configuration;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ViewResolverRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.thymeleaf.spring5.SpringTemplateEngine;
import org.thymeleaf.spring5.templateresolver.SpringResourceTemplateResolver;
import org.thymeleaf.spring5.view.ThymeleafViewResolver;
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
@Autowired
private ApplicationContext applicationContext;
@Bean
public SpringResourceTemplateResolver templateResolver() {
SpringResourceTemplateResolver templateResolver = new SpringResourceTemplateResolver();
templateResolver.setApplicationContext(applicationContext);
templateResolver.setPrefix("/WEB-INF/views/");
templateResolver.setSuffix(".html");
templateResolver.setCacheable(false);
return templateResolver;
}
/*
* STEP 2 - Create SpringTemplateEngine
* */
@Bean
public SpringTemplateEngine templateEngine() {
SpringTemplateEngine templateEngine = new SpringTemplateEngine();
templateEngine.setTemplateResolver(templateResolver());
templateEngine.setEnableSpringELCompiler(true);
return templateEngine;
}
/*
* STEP 3 - Register ThymeleafViewResolver
* */
@Override
public void configureViewResolvers(ViewResolverRegistry registry) {
ThymeleafViewResolver resolver = new ThymeleafViewResolver();
resolver.setTemplateEngine(templateEngine());
registry.viewResolver(resolver);
}
}
PersistenceJPAConfig.java
package com.dogukanhan.spring101.configuration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.JpaVendorAdapter;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import javax.persistence.EntityManagerFactory;
import javax.sql.DataSource;
import java.util.Properties;
@Configuration
@EnableTransactionManagement
public class PersistenceJPAConfig {
@Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
LocalContainerEntityManagerFactoryBean em
= new LocalContainerEntityManagerFactoryBean();
em.setDataSource(dataSource());
em.setPackagesToScan(new String[]{"com.dogukanhan.spring101.entity"});
JpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
em.setJpaVendorAdapter(vendorAdapter);
em.setJpaProperties(additionalProperties());
return em;
}
@Bean
public DataSource dataSource() {
DriverManagerDataSource ds = new DriverManagerDataSource();
ds.setDriverClassName("com.mysql.jdbc.Driver");
ds.setUrl("jdbc:mysql://172.17.0.1:3306/spring101");
ds.setUsername("root");
ds.setPassword("my-secret-pw");
return ds;
}
@Bean
public PlatformTransactionManager transactionManager(
EntityManagerFactory emf) {
JpaTransactionManager transactionManager = new JpaTransactionManager();
transactionManager.setEntityManagerFactory(emf);
return transactionManager;
}
@Bean
public PersistenceExceptionTranslationPostProcessor exceptionTranslation() {
return new PersistenceExceptionTranslationPostProcessor();
}
Properties additionalProperties() {
Properties properties = new Properties();
properties.setProperty("hibernate.hbm2ddl.auto", "create-drop");
properties.setProperty(
"hibernate.dialect", "org.hibernate.dialect.MySQL5Dialect");
return properties;
}
}
HomeController.java
package com.dogukanhan.spring101.controller;
import com.dogukanhan.spring101.FormCommand;
import com.dogukanhan.spring101.entity.Post;
import com.dogukanhan.spring101.repository.PostRepository;
import org.springframework.beans.factory.annotation.Autowired;
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 java.util.List;
@Controller
public class HomeController {
@Autowired
private PostRepository postRepository;
@ModelAttribute("formCommand")
public FormCommand formCommand() {
return new FormCommand();
}
@GetMapping("/")
public String index(Model model) {
List<Post> posts = postRepository.findAll();
model.addAttribute("posts", posts);
return "index";
}
@GetMapping("/new")
public String newpost(Model model) {
List<Post> posts = postRepository.findAll();
model.addAttribute("posts", posts);
return "new";
}
@PostMapping("/new")
public String processSubmit(Model model,@ModelAttribute FormCommand formCommand) {
Post post = new Post();
post.setContent(formCommand.getContent());
post.setTitle(formCommand.getTitle());
post.setSender(formCommand.getSender());
postRepository.save(post);
model.addAttribute("post",post);
return "new";
}
@GetMapping("/delete/{id}")
public String newpost(Model model, @PathVariable long id) {
postRepository.deleteById(id);
return "delete";
}
}
FormCommand.java
package com.dogukanhan.spring101;
public class FormCommand {
private String sender, title, content;
public String getSender() {
return sender;
}
public void setSender(String sender) {
this.sender = sender;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
}
index.html
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Spring Example</title>
</head>
<body>
<a th:href="@{/new}"> Create New Post </a>
<h2>Posts</h2>
<ul>
<li th:each="post: ${posts}">
<div th:text="${post.title} +' | ' + ${post.sender} "> Post List</div>
<a th:href="@{/delete/}+${post.ID}"> Del </a>
</li>
</ul>
</body>
</html>
new.html
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Spring Example</title>
</head>
<body>
<div th:if="${post}">
<div th:text="'Post is created id = ' + ${post.ID}"> Post is created </div>
</div>
<div th:unless="${post}">
<form action="#" th:action="@{/new}" th:object="${formCommand}" method="post">
<p>Sender: <input type="text" th:field="*{sender}" /></p>
<p>Title: <input type="text" th:field="*{title}" /></p>
<p>Content: <textarea th:field="*{content}" ></textarea></p>
<input type="submit"/>
</form>
</div>
</body>
</html>

