MVC Mimarisi
MVC, yazılım mühendisliğinin en önemli ve en yaygın kullanılan mimari desenlerinden biridir. Adını üç temel bileşenden alır: Model, View ve Controller. Bu desen, bir uygulamanın iş mantığını (business logic), kullanıcı arayüzünü (presentation) ve kullanıcı girdisi yönetimini (input handling) birbirinden ayırmayı hedefler. Böylece kodun bakımı, test edilmesi ve genişletilmesi çok daha kolay hale gelir.
Günlük hayattan bir analoji yapalım: Bir restoran düşünün. Garson (Controller) müşteriden siparişi alır ve mutfağa iletir. Şef (Model) yemeği hazırlar — tüm iş mantığı burada gerçekleşir. Tabak ve sunum (View) yemeğin müşteriye nasıl gösterildiğidir. Garson şefin tarifini bilmez, şef tabağın rengini umursamaz — herkesin net bir sorumluluğu vardır.
Üç Bileşenin Detaylı Açıklaması
Model: Uygulamanın veri katmanını ve iş kurallarını temsil eder. Veritabanı ile etkileşim, veri doğrulama (validation), hesaplama mantığı ve iş kuralları Model'de bulunur. Model, View ve Controller'dan tamamen bağımsızdır — verinin nasıl gösterildiğini veya kullanıcının ne yaptığını bilmez. Sadece veri ve kurallarla ilgilenir. Spring Boot'ta bu katman genellikle @Entity, @Service ve @Repository sınıflarıyla temsil edilir.
View: Kullanıcıya sunulan arayüzdür. HTML sayfası, JSON yanıtı, XML çıktısı veya PDF belgesi olabilir. View, Model'den aldığı verileri belirli bir formatta kullanıcıya gösterir. View'ın iş mantığı barındırması beklenmez — sadece veriyi sunmak onun görevidir. Spring MVC'de View, Thymeleaf template'i, JSP sayfası veya doğrudan JSON serializasyonu olabilir.
Controller: Model ile View arasındaki köprüdür. Kullanıcıdan gelen istekleri (HTTP request) alır, gerekli Model işlemlerini tetikler ve sonuçları uygun View'a yönlendirir. Controller'ın kendisi iş mantığı barındırmamalıdır — sadece koordinasyon yapar. Spring'de bu katman @Controller veya @RestController ile işaretlenen sınıflardır.
MVC Akışı Adım Adım
Tipik bir MVC web uygulamasında bir HTTP isteği şu adımlardan geçer:
Kullanıcı (Browser)
│
▼ HTTP Request (GET /products/5)
┌─────────────────────────────┐
│ DispatcherServlet │ ← Front Controller
│ (tüm istekleri karşılar) │
└──────────┬──────────────────┘
│
▼
┌─────────────────────────────┐
│ HandlerMapping │ ← URL → Controller eşleştirme
│ (/products/{id} → ProductController.getProduct)
└──────────┬──────────────────┘
│
▼
┌─────────────────────────────┐
│ Controller (Handler) │ ← İsteği işler, Model'i çağırır
│ ProductController │
└──────────┬──────────────────┘
│
▼
┌─────────────────────────────┐
│ Model │ ← Veri ve iş mantığı
│ ProductService → Repository│
└──────────┬──────────────────┘
│ (veriler)
▼
┌─────────────────────────────┐
│ ViewResolver │ ← View adı → gerçek View dosyası
│ "product-detail" → product-detail.html
└──────────┬──────────────────┘
│
▼
┌─────────────────────────────┐
│ View │ ← Yanıtı oluşturur
│ (Thymeleaf / JSON / XML) │
└──────────┬──────────────────┘
│
▼ HTTP Response
Kullanıcı (Browser)DispatcherServlet — Front Controller Pattern
Spring MVC'nin kalbi DispatcherServlet'tir. Bu, Java Servlet API'si üzerine inşa edilmiş özel bir servlet'tir ve Front Controller tasarım desenini uygular. Tüm HTTP istekleri önce DispatcherServlet'e gelir — hangi controller'ın bu isteği karşılayacağına DispatcherServlet karar verir.
DispatcherServlet'in görevleri şunlardır:
İsteği almak: Tüm HTTP istekleri (
/pattern ile) DispatcherServlet'e yönlendirilir.HandlerMapping ile controller bulmak: URL pattern'ine göre hangi controller metodunun çağrılacağını belirler.
HandlerAdapter ile metodu çağırmak: Controller metodunu uygun parametrelerle çağırır.
ViewResolver ile view'ı çözmek: Controller'ın döndüğü view adını gerçek bir View nesnesine dönüştürür.
Yanıtı oluşturmak: View'ın ürettiği içeriği HTTP yanıtı olarak gönderir.
// Spring Boot'ta DispatcherServlet otomatik olarak yapılandırılır.
// application.properties ile özelleştirme:
spring.mvc.servlet.path=/api // DispatcherServlet'in dinlediği path
server.servlet.context-path=/myapp // Uygulama bağlam yoluSpring Boot'ta DispatcherServlet'i manuel olarak yapılandırmanıza gerek yoktur — spring-boot-starter-web dependency'si eklediğinizde otomatik olarak ayarlanır. Bu, Spring Boot'un auto-configuration özelliğinin güzel bir örneğidir.
HandlerMapping — URL Eşleştirme
HandlerMapping, gelen HTTP isteğinin URL'ini bir controller metoduyla eşleştiren bileşendir. Spring MVC'de birkaç HandlerMapping implementasyonu bulunur:
RequestMappingHandlerMapping:
@RequestMappingve türevi annotation'larla (@GetMapping,@PostMappingvb.) eşleştirme yapar. En yaygın kullanılan.SimpleUrlHandlerMapping: URL → Handler eşleştirmesini programatik olarak yapılandırmanıza olanak tanır.
BeanNameUrlHandlerMapping: Bean adı URL olarak kullanılır.
// @RequestMapping ile eşleştirme örnekleri
@GetMapping("/products") // GET /products
@GetMapping("/products/{id}") // GET /products/5
@PostMapping("/products") // POST /products
@GetMapping("/products/search") // GET /products/search?q=laptopViewResolver — View Çözümleme
ViewResolver, controller'ın döndüğü mantıksal view adını (logical view name) gerçek bir View nesnesine çevirir. Örneğin controller "product-detail" string'ini döndürdüğünde, ViewResolver bunu templates/product-detail.html dosyasına eşleştirir.
Spring MVC'deki yaygın ViewResolver'lar:
ThymeleafViewResolver: Thymeleaf template engine'i kullanarak HTML üretir.
InternalResourceViewResolver: JSP sayfaları için kullanılır.
ContentNegotiatingViewResolver: Accept header'a göre farklı view'lar seçer.
BeanNameViewResolver: Bean adıyla view çözer.
// Thymeleaf yapılandırması (application.properties)
spring.thymeleaf.prefix=classpath:/templates/
spring.thymeleaf.suffix=.html
spring.thymeleaf.cache=false // Geliştirme ortamı için
// Controller'da view döndürme
@Controller
public class ProductController {
@GetMapping("/products/{id}")
public String getProduct(@PathVariable Long id, Model model) {
Product product = productService.findById(id);
model.addAttribute("product", product);
return "product-detail"; // → templates/product-detail.html
}
}Spring MVC vs Geleneksel Servlet Yaklaşımı
Java web geliştirmenin tarihi Servlet API ile başlar. Servlet'ler HTTP isteklerini karşılayan ve yanıt üreten Java sınıflarıdır. Ancak saf servlet ile geliştirme yapmak oldukça zahmetlidir:
// Geleneksel Servlet yaklaşımı — zahmetli ve karmaşık
@WebServlet("/products")
public class ProductServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
String idParam = req.getParameter("id");
// Manuel parametre parse, null kontrolü...
// Manuel JSON serializasyon...
// Manuel hata yönetimi...
resp.setContentType("application/json");
resp.getWriter().write("{\"name\": \"Laptop\"}");
}
}Spring MVC tüm bu karmaşıklığı ortadan kaldırır:
// Spring MVC yaklaşımı — temiz ve deklaratif
@RestController
@RequestMapping("/products")
public class ProductController {
@GetMapping("/{id}")
public Product getProduct(@PathVariable Long id) {
return productService.findById(id);
// JSON serializasyon otomatik!
}
}Temel farklar şunlardır:
| Özellik | Servlet | Spring MVC |
|---|---|---|
| URL eşleştirme | web.xml veya @WebServlet | @RequestMapping ailesi |
| Parametre alma | request.getParameter() | @PathVariable, @RequestParam |
| JSON dönüşümü | Manuel (Gson, Jackson) | Otomatik (Jackson entegre) |
| Bağımlılık yönetimi | Manuel | Dependency Injection |
| Hata yönetimi | try-catch + error page | @ExceptionHandler |
| Test edilebilirlik | Zor (HttpServletRequest mock) | Kolay (MockMvc) |
Model-View-Controller Akışının Tam Yaşam Döngüsü
Bir HTTP isteği geldiğinde Spring MVC'de şu sırayla olaylar gerçekleşir:
Filter Chain: Güvenlik filtreleri, encoding filtreleri vb. çalışır.
DispatcherServlet: İsteği alır.
HandlerMapping: URL'e uygun controller metodu bulunur.
HandlerInterceptor.preHandle(): İstek öncesi interceptor'lar çalışır.
Controller metodu çağrılır: İş mantığı çalışır, sonuç üretilir.
HandlerInterceptor.postHandle(): İstek sonrası interceptor'lar çalışır.
ViewResolver: View çözümlenir (eğer view name döndüyse).
View render: Yanıt HTML/JSON olarak oluşturulur.
HandlerInterceptor.afterCompletion(): Tamamlanma interceptor'ları çalışır.
HTTP Response: Yanıt istemciye gönderilir.
💡 İpucu: REST API geliştirirken genellikle ViewResolver kullanılmaz.
@RestControllerkullanıldığında dönüş değeri doğrudan HTTP yanıt gövdesine Jackson ile serializasyon yapılarak yazılır.
İlk Spring MVC Uygulamanız
Spring Boot ile basit bir MVC uygulaması oluşturmak son derece kolaydır:
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
@RestController
public class HelloController {
@GetMapping("/hello")
public String hello() {
return "Merhaba Spring MVC!";
}
@GetMapping("/hello/{name}")
public Map<String, String> helloWithName(@PathVariable String name) {
return Map.of("message", "Merhaba " + name + "!");
}
}Bu uygulamayı çalıştırdığınızda http://localhost:8080/hello adresine gittiğinizde Merhaba Spring MVC! yanıtını alırsınız. Spring Boot, DispatcherServlet'i, HandlerMapping'i ve Jackson konfigürasyonunu otomatik olarak ayarlamıştır.
💡 Özet: Spring MVC, Model-View-Controller desenini uygulayan, DispatcherServlet tabanlı bir web framework'üdür. Geleneksel servlet yaklaşımındaki tüm karmaşıklığı soyutlar ve annotation-tabanlı temiz bir API sunar.
AI Asistan
Sorularını yanıtlamaya hazır