> system ready.
../

Spring Boot ile Modern Bir Todo Uygulaması Geliştirme

Syslog Metadata2025-12-18
Context:BackendEnv:ProductionNote:Field notes from active development.

Modern bir backend uygulaması geliştirmek istiyorsanız, doğru yerdesiniz! Bu yazıda Spring Boot framework'ü kullanarak tam teşekküllü bir Todo uygulaması geliştireceğiz. Projemizde JWT tabanlı kimlik doğrulama, PostgreSQL veritabanı ve Docker container kullanacağız.

Neler Öğreneceğiz?

  • Spring Boot 3.2 ile proje kurulumu
  • PostgreSQL veritabanı entegrasyonu
  • JPA/Hibernate ile veritabanı işlemleri
  • JWT tabanlı kimlik doğrulama
  • RESTful API tasarımı
  • Docker ile containerization
  • Unit ve Integration testleri
  • Swagger ile API dokümantasyonu

Proje Yapısı

terminal - plaintext
todo-app/ ├── src/ │ ├── main/ │ │ ├── java/ │ │ │ └── com/ │ │ │ └── mbkayihan/ │ │ │ └── todoapp/ │ │ │ ├── TodoApplication.java │ │ │ ├── config/ │ │ │ ├── controller/ │ │ │ ├── model/ │ │ │ ├── repository/ │ │ │ └── service/ │ │ └── resources/ │ │ └── application.yml │ └── test/ ├── pom.xml └── Dockerfile

Gerekli Bağımlılıklar

terminal - xml
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <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.postgresql</groupId> <artifactId>postgresql</artifactId> </dependency> <dependency> <groupId>io.jsonwebtoken</groupId> <artifactId>jjwt</artifactId> <version>0.9.1</version> </dependency> </dependencies>

Veritabanı Modeli

terminal - java
@Entity @Table(name = "todos") public class Todo { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @Column(nullable = false) private String title; private String description; @Column(nullable = false) private boolean completed; @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "user_id", nullable = false) private User user; // Getter ve Setter metodları }

JWT Kimlik Doğrulama

Güvenli bir API için JWT tabanlı kimlik doğrulama sistemi kuracağız:

terminal - java
@Service public class JwtTokenProvider { @Value("${jwt.secret}") private String jwtSecret; @Value("${jwt.expiration}") private int jwtExpiration; public String generateToken(Authentication authentication) { UserDetails userPrincipal = (UserDetails) authentication.getPrincipal(); return Jwts.builder() .setSubject(userPrincipal.getUsername()) .setIssuedAt(new Date()) .setExpiration(new Date(new Date().getTime() + jwtExpiration)) .signWith(SignatureAlgorithm.HS512, jwtSecret) .compact(); } public String getUsernameFromToken(String token) { Claims claims = Jwts.parser() .setSigningKey(jwtSecret) .parseClaimsJws(token) .getBody(); return claims.getSubject(); } public boolean validateToken(String token) { try { Jwts.parser().setSigningKey(jwtSecret).parseClaimsJws(token); return true; } catch (SignatureException ex) { // Token imzası geçersiz } catch (MalformedJwtException ex) { // Token formatı geçersiz } catch (ExpiredJwtException ex) { // Token süresi dolmuş } catch (UnsupportedJwtException ex) { // Token desteklenmiyor } catch (IllegalArgumentException ex) { // Token boş } return false; } }

Controller Katmanı

RESTful API endpoint'lerimizi tanımlayalım:

terminal - java
@RestController @RequestMapping("/api/todos") public class TodoController { private final TodoService todoService; public TodoController(TodoService todoService) { this.todoService = todoService; } @GetMapping public List<TodoDTO> getAllTodos() { return todoService.getAllTodos(); } @PostMapping public TodoDTO createTodo(@Valid @RequestBody TodoRequest request) { return todoService.createTodo(request); } @PutMapping("/{id}") public TodoDTO updateTodo(@PathVariable Long id, @Valid @RequestBody TodoRequest request) { return todoService.updateTodo(id, request); } @DeleteMapping("/{id}") public void deleteTodo(@PathVariable Long id) { todoService.deleteTodo(id); } @PatchMapping("/{id}/complete") public TodoDTO completeTodo(@PathVariable Long id) { return todoService.completeTodo(id); } }

Service Katmanı

İş mantığımızı service katmanında yönetelim:

terminal - java
@Service @Transactional public class TodoService { private final TodoRepository todoRepository; private final UserService userService; public TodoService(TodoRepository todoRepository, UserService userService) { this.todoRepository = todoRepository; this.userService = userService; } public List<TodoDTO> getAllTodos() { User currentUser = userService.getCurrentUser(); return todoRepository.findByUser(currentUser) .stream() .map(this::convertToDTO) .collect(Collectors.toList()); } public TodoDTO createTodo(TodoRequest request) { User currentUser = userService.getCurrentUser(); Todo todo = new Todo(); todo.setTitle(request.getTitle()); todo.setDescription(request.getDescription()); todo.setCompleted(false); todo.setUser(currentUser); return convertToDTO(todoRepository.save(todo)); } private TodoDTO convertToDTO(Todo todo) { return TodoDTO.builder() .id(todo.getId()) .title(todo.getTitle()) .description(todo.getDescription()) .completed(todo.isCompleted()) .build(); } }

Docker ile Deployment

Uygulamamızı container'da çalıştırmak için Dockerfile:

terminal - dockerfile
FROM openjdk:17-jdk-slim WORKDIR /app COPY target/*.jar app.jar EXPOSE 8080 ENTRYPOINT ["java", "-jar", "app.jar"]

Ve docker-compose.yml:

terminal - yaml
version: '3.8' services: app: build: . ports: - "8080:8080" depends_on: - db environment: - SPRING_DATASOURCE_URL=jdbc:postgresql://db:5432/tododb - SPRING_DATASOURCE_USERNAME=postgres - SPRING_DATASOURCE_PASSWORD=password db: image: postgres:14-alpine ports: - "5432:5432" environment: - POSTGRES_DB=tododb - POSTGRES_USER=postgres - POSTGRES_PASSWORD=password volumes: - postgres_data:/var/lib/postgresql/data volumes: postgres_data:

Unit Test Örneği

Service katmanı için bir test örneği:

terminal - java
@ExtendWith(MockitoExtension.class) class TodoServiceTest { @Mock private TodoRepository todoRepository; @Mock private UserService userService; @InjectMocks private TodoService todoService; @Test void createTodo_ShouldReturnTodoDTO() { // Given User user = new User(); TodoRequest request = new TodoRequest("Test Todo", "Test Description"); Todo todo = new Todo(); todo.setId(1L); todo.setTitle(request.getTitle()); todo.setDescription(request.getDescription()); todo.setCompleted(false); todo.setUser(user); when(userService.getCurrentUser()).thenReturn(user); when(todoRepository.save(any(Todo.class))).thenReturn(todo); // When TodoDTO result = todoService.createTodo(request); // Then assertNotNull(result); assertEquals(request.getTitle(), result.getTitle()); assertEquals(request.getDescription(), result.getDescription()); assertFalse(result.isCompleted()); } }

Swagger Dokümantasyonu

API'mizi dokümante etmek için OpenAPI 3.0 kullanacağız:

terminal - java
@Configuration public class SwaggerConfig { @Bean public OpenAPI customOpenAPI() { return new OpenAPI() .info(new Info() .title("Todo API") .version("1.0") .description("Modern bir Todo uygulaması API dokümantasyonu")); } }

Sonuç

Bu yazıda modern bir Spring Boot uygulamasının temel bileşenlerini inceledik:

  • JWT tabanlı güvenlik sistemi
  • Katmanlı mimari (Controller, Service, Repository)
  • PostgreSQL veritabanı entegrasyonu
  • Docker ile containerization
  • Unit testler
  • API dokümantasyonu

Sonraki Adımlar

  • Frontend uygulaması geliştirme (React/Angular)
  • CI/CD pipeline kurulumu
  • Kubernetes deployment
  • Performans optimizasyonları
  • Monitoring ve logging

Sorularınız veya önerileriniz varsa, yorum bırakabilirsiniz. Bir sonraki yazıda görüşmek üzere!