{"id":35419,"date":"2025-11-29T12:40:55","date_gmt":"2025-11-29T09:40:55","guid":{"rendered":"https:\/\/fatihsoysal.com\/blog\/?p=35419"},"modified":"2025-11-29T12:40:55","modified_gmt":"2025-11-29T09:40:55","slug":"spring-restcontroller-restful-web-servisleri-gelistirmede-temel-tas","status":"publish","type":"post","link":"https:\/\/fatihsoysal.com\/blog\/spring-restcontroller-restful-web-servisleri-gelistirmede-temel-tas\/","title":{"rendered":"Spring RestController: RESTful Web Servisleri Geli\u015ftirmede Temel Ta\u015f"},"content":{"rendered":"<p><body><\/p>\n<h2>Spring RestController: RESTful Web Servisleri Geli\u015ftirmede Temel Ta\u015f<\/h2>\n<h3>Giri\u015f: REST ve Spring Boot Ekosisteminde Yeri<\/h3>\n<p>G\u00fcn\u00fcm\u00fcz\u00fcn da\u011f\u0131t\u0131k sistem mimarilerinde, farkl\u0131 uygulamalar\u0131n birbirleriyle etkile\u015fim kurmas\u0131 ka\u00e7\u0131n\u0131lmaz bir gerekliliktir. Bu etkile\u015fimi sa\u011flaman\u0131n en yayg\u0131n ve etkili yollar\u0131ndan biri de REST (Representational State Transfer) mimari stilini kullanan web servisleridir. REST, web&#8217;in temel prensiplerine dayanarak, kaynaklar\u0131n (resources) HTTP metodlar\u0131 (GET, POST, PUT, DELETE vb.) ve durum kodlar\u0131 (200 OK, 404 Not Found vb.) arac\u0131l\u0131\u011f\u0131yla y\u00f6netilmesini sa\u011flayan hafif, esnek ve \u00f6l\u00e7eklenebilir bir yakla\u015f\u0131md\u0131r. Mikroservis mimarilerinin y\u00fckseli\u015fiyle birlikte RESTful servisler, modern yaz\u0131l\u0131m geli\u015ftirmede adeta bir standart haline gelmi\u015ftir.<\/p>\n<p>Java ekosisteminde RESTful servisler geli\u015ftirmek i\u00e7in bir\u00e7ok framework ve k\u00fct\u00fcphane bulunsa da, Spring Framework ve \u00f6zellikle Spring Boot, bu alandaki en pop\u00fcler ve g\u00fc\u00e7l\u00fc ara\u00e7lardan biridir. Spring Boot, geli\u015ftiricilerin h\u0131zl\u0131ca ba\u011f\u0131ms\u0131z, \u00fcretime haz\u0131r Spring tabanl\u0131 uygulamalar olu\u015fturmas\u0131na olanak tan\u0131r. &#8220;Convention over configuration&#8221; (yap\u0131land\u0131rma yerine kural) felsefesiyle, karma\u015f\u0131k yap\u0131land\u0131rmalar\u0131 basitle\u015ftirerek geli\u015ftirme s\u00fcrecini h\u0131zland\u0131r\u0131r. Spring Boot&#8217;un RESTful servis geli\u015ftirme yeteneklerinin kalbinde ise <code>@RestController<\/code> anotasyonu yer al\u0131r. Bu anotasyon, Spring MVC&#8217;nin t\u00fcm g\u00fcc\u00fcn\u00fc REST&#8217;in basitli\u011fiyle birle\u015ftirerek, Java geli\u015ftiricilerinin g\u00fc\u00e7l\u00fc ve \u00f6l\u00e7eklenebilir API&#8217;ler olu\u015fturmas\u0131n\u0131 son derece kolayla\u015ft\u0131r\u0131r. Bu makalede, <code>@RestController<\/code>&#8216;\u0131n ne oldu\u011funu, nas\u0131l \u00e7al\u0131\u015ft\u0131\u011f\u0131n\u0131, temel \u00f6zelliklerini ve RESTful servisler geli\u015ftirirken dikkat edilmesi gereken en iyi uygulamalar\u0131 detayl\u0131 bir \u015fekilde inceleyece\u011fiz.<\/p>\n<h3>@RestController Anotasyonu: Temeller ve \u0130\u015fleyi\u015f<\/h3>\n<p>Spring Framework&#8217;te, gelen HTTP isteklerini i\u015flemek ve uygun yan\u0131tlar\u0131 d\u00f6nd\u00fcrmek i\u00e7in <code>Controller<\/code> bile\u015fenleri kullan\u0131l\u0131r. Geleneksel Spring MVC uygulamalar\u0131nda, HTML sayfalar\u0131 d\u00f6nd\u00fcren bir kontrolc\u00fc <code>@Controller<\/code> anotasyonu ile i\u015faretlenirken, bir RESTful serviste veri (genellikle JSON veya XML) d\u00f6nd\u00fcren bir kontrolc\u00fcye ihtiya\u00e7 duyar\u0131z. \u0130\u015fte bu noktada <code>@RestController<\/code> devreye girer.<\/p>\n<p><code>@RestController<\/code> asl\u0131nda iki temel Spring anotasyonunun birle\u015fimidir:<br \/>\n1.  <strong><code>@Controller<\/code><\/strong>: Bu anotasyon, bir s\u0131n\u0131f\u0131 Spring MVC&#8217;nin bir kontrolc\u00fc bile\u015feni olarak i\u015faretler. Spring&#8217;in bile\u015fen taramas\u0131 (component scanning) s\u0131ras\u0131nda bu s\u0131n\u0131f\u0131 bulmas\u0131n\u0131 ve istek i\u015fleme yetenekleri i\u00e7in kaydetmesini sa\u011flar.<br \/>\n2.  <strong><code>@ResponseBody<\/code><\/strong>: Bu anotasyon, bir metodun d\u00f6n\u00fc\u015f de\u011ferinin do\u011frudan HTTP yan\u0131t g\u00f6vdesine yaz\u0131lmas\u0131 gerekti\u011fini belirtir. Varsay\u0131lan olarak, Spring bu d\u00f6n\u00fc\u015f de\u011ferini uygun bir HTTP mesaj d\u00f6n\u00fc\u015ft\u00fcr\u00fcc\u00fcs\u00fc (HTTP Message Converter) kullanarak JSON veya XML gibi bir formata d\u00f6n\u00fc\u015ft\u00fcr\u00fcr.<\/p>\n<p>Dolay\u0131s\u0131yla, bir s\u0131n\u0131f\u0131 <code>@RestController<\/code> ile i\u015faretledi\u011finizde, Spring bu s\u0131n\u0131f\u0131n hem bir kontrolc\u00fc oldu\u011funu anlar hem de bu s\u0131n\u0131ftaki t\u00fcm metodlar\u0131n d\u00f6n\u00fc\u015f de\u011ferlerinin otomatik olarak HTTP yan\u0131t g\u00f6vdesine d\u00f6n\u00fc\u015ft\u00fcr\u00fcl\u00fcp g\u00f6nderilece\u011fini varsayar. Bu, her metoda ayr\u0131 ayr\u0131 <code>@ResponseBody<\/code> anotasyonu ekleme ihtiyac\u0131n\u0131 ortadan kald\u0131rarak kodu daha temiz ve okunabilir hale getirir.<\/p>\n<p><strong>\u00d6rnek:<\/strong><\/p>\n<pre><code class=\"language-java\">import org.springframework.web.bind.annotation.GetMapping;\nimport org.springframework.web.bind.annotation.RestController;\n\n@RestController\npublic class MerhabaController {\n\n    @GetMapping(\"\/merhaba\")\n    public String merhabaDunya() {\n        return \"Merhaba D\u00fcnya!\";\n    }\n\n    @GetMapping(\"\/api\/kullanici\")\n    public Kullanici getKullanici() {\n        return new Kullanici(1L, \"Ali Can\", \"ali.can@example.com\");\n    }\n}\n\nclass Kullanici {\n    private Long id;\n    private String adSoyad;\n    private String email;\n\n    public Kullanici(Long id, String adSoyad, String email) {\n        this.id = id;\n        this.adSoyad = adSoyad;\n        this.email = email;\n    }\n\n    \/\/ Getter ve Setter metodlar\u0131\n    public Long getId() { return id; }\n    public void setId(Long id) { this.id = id; }\n    public String getAdSoyad() { return adSoyad; }\n    public void setAdSoyad(String adSoyad) { this.adSoyad = adSoyad; }\n    public String getEmail() { return email; }\n    public void setEmail(String email) { this.email = email; }\n}<\/code><\/pre>\n<p>Yukar\u0131daki \u00f6rnekte, <code>\/merhaba<\/code> adresine yap\u0131lan bir GET iste\u011fi &#8220;Merhaba D\u00fcnya!&#8221; metnini, <code>\/api\/kullanici<\/code> adresine yap\u0131lan bir GET iste\u011fi ise <code>Kullanici<\/code> nesnesini JSON format\u0131nda d\u00f6nd\u00fcrecektir (e\u011fer projenizde Jackson veya Gson gibi bir JSON k\u00fct\u00fcphanesi varsa). Bu otomatik d\u00f6n\u00fc\u015f\u00fcm, geli\u015ftiricilerin veri serile\u015ftirme\/deserile\u015ftirme detaylar\u0131yla u\u011fra\u015fmak zorunda kalmamas\u0131n\u0131 sa\u011flar.<\/p>\n<h3>HTTP Metodlar\u0131 ve @RequestMapping<\/h3>\n<p>RESTful servislerin temelini, kaynaklar \u00fczerindeki i\u015flemleri temsil eden HTTP metodlar\u0131 olu\u015fturur. <code>@RestController<\/code> s\u0131n\u0131flar\u0131 i\u00e7inde, belirli HTTP isteklerini belirli metodlara y\u00f6nlendirmek i\u00e7in <code>@RequestMapping<\/code> anotasyonu veya onun k\u0131salt\u0131lm\u0131\u015f versiyonlar\u0131 kullan\u0131l\u0131r.<\/p>\n<h4>@RequestMapping Anotasyonu<\/h4>\n<p><code>@RequestMapping<\/code> anotasyonu, bir iste\u011fin URI&#8217;s\u0131n\u0131 (Uniform Resource Identifier) ve HTTP metodunu bir kontrolc\u00fc metoduna e\u015fle\u015ftirmek i\u00e7in kullan\u0131l\u0131r. Hem s\u0131n\u0131f seviyesinde hem de metod seviyesinde uygulanabilir.<\/p>\n<p>*   <strong><code>value<\/code> veya <code>path<\/code> \u00f6zniteli\u011fi<\/strong>: \u0130ste\u011fin e\u015fle\u015fece\u011fi URI yolunu belirtir.<br \/>\n*   <strong><code>method<\/code> \u00f6zniteli\u011fi<\/strong>: \u0130ste\u011fin e\u015fle\u015fece\u011fi HTTP metodunu belirtir (\u00f6rn. <code>RequestMethod.GET<\/code>, <code>RequestMethod.POST<\/code>).<br \/>\n*   <strong><code>consumes<\/code> \u00f6zniteli\u011fi<\/strong>: \u0130ste\u011fin HTTP g\u00f6vdesinde kabul edilebilir medya tiplerini belirtir (\u00f6rn. <code>application\/json<\/code>).<br \/>\n*   <strong><code>produces<\/code> \u00f6zniteli\u011fi<\/strong>: Yan\u0131t\u0131n HTTP g\u00f6vdesinde \u00fcretilebilecek medya tiplerini belirtir (\u00f6rn. <code>application\/xml<\/code>).<\/p>\n<p><strong>\u00d6rnek:<\/strong><\/p>\n<pre><code class=\"language-java\">import org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.bind.annotation.RequestMethod;\nimport org.springframework.web.bind.annotation.RestController;\n\n@RestController\n@RequestMapping(\"\/api\/urunler\") \/\/ S\u0131n\u0131f seviyesinde temel URI\npublic class UrunController {\n\n    @RequestMapping(method = RequestMethod.GET) \/\/ GET \/api\/urunler\n    public String getAllProducts() {\n        return \"T\u00fcm \u00fcr\u00fcnler listeleniyor...\";\n    }\n\n    @RequestMapping(method = RequestMethod.POST, consumes = \"application\/json\") \/\/ POST \/api\/urunler\n    public String createProduct() {\n        return \"Yeni \u00fcr\u00fcn olu\u015fturuluyor...\";\n    }\n}<\/code><\/pre>\n<h4>K\u0131saltma Anotasyonlar\u0131<\/h4>\n<p><code>@RequestMapping<\/code>&#8216;in HTTP metoduna \u00f6zel k\u0131saltmalar\u0131, kodu daha okunakl\u0131 ve \u00f6zl\u00fc hale getirir. Bunlar, <code>@RequestMapping(method = RequestMethod.GET)<\/code> yerine do\u011frudan kullan\u0131labilecek anotasyonlard\u0131r:<\/p>\n<p>*   <strong><code>@GetMapping<\/code><\/strong>: HTTP GET istekleri i\u00e7in.<br \/>\n*   <strong><code>@PostMapping<\/code><\/strong>: HTTP POST istekleri i\u00e7in.<br \/>\n*   <strong><code>@PutMapping<\/code><\/strong>: HTTP PUT istekleri i\u00e7in.<br \/>\n*   <strong><code>@DeleteMapping<\/code><\/strong>: HTTP DELETE istekleri i\u00e7in.<br \/>\n*   <strong><code>@PatchMapping<\/code><\/strong>: HTTP PATCH istekleri i\u00e7in.<\/p>\n<p>Bu k\u0131saltmalar, modern Spring Boot uygulamalar\u0131nda en \u00e7ok tercih edilen y\u00f6ntemdir.<\/p>\n<p><strong>\u00d6rnek:<\/strong><\/p>\n<pre><code class=\"language-java\">import org.springframework.web.bind.annotation.*; \/\/ T\u00fcm anotasyonlar\u0131 i\u00e7e aktar\u0131r\n\n@RestController\n@RequestMapping(\"\/api\/urunler\")\npublic class UrunControllerModern {\n\n    @GetMapping \/\/ GET \/api\/urunler\n    public String getAllProducts() {\n        return \"T\u00fcm \u00fcr\u00fcnler listeleniyor (modern)...\";\n    }\n\n    @PostMapping(consumes = \"application\/json\") \/\/ POST \/api\/urunler\n    public String createProduct() {\n        return \"Yeni \u00fcr\u00fcn olu\u015fturuluyor (modern)...\";\n    }\n\n    @PutMapping(\"\/{id}\") \/\/ PUT \/api\/urunler\/{id}\n    public String updateProduct(@PathVariable Long id) {\n        return id + \" numaral\u0131 \u00fcr\u00fcn g\u00fcncelleniyor...\";\n    }\n\n    @DeleteMapping(\"\/{id}\") \/\/ DELETE \/api\/urunler\/{id}\n    public String deleteProduct(@PathVariable Long id) {\n        return id + \" numaral\u0131 \u00fcr\u00fcn siliniyor...\";\n    }\n}<\/code><\/pre>\n<p>Bu k\u0131saltmalar, kodun amac\u0131n\u0131 an\u0131nda belli etti\u011fi i\u00e7in okunabilirli\u011fi b\u00fcy\u00fck \u00f6l\u00e7\u00fcde art\u0131r\u0131r.<\/p>\n<h3>Parametre \u0130\u015fleme: \u0130stemciden Gelen Verileri Yakalama<\/h3>\n<p>RESTful servisler, istemciden \u00e7e\u015fitli yollarla veri alabilir. Spring <code>@RestController<\/code>&#8216;lar, bu verileri yakalamak ve Java metod parametrelerine ba\u011flamak i\u00e7in g\u00fc\u00e7l\u00fc anotasyonlar sunar.<\/p>\n<h4>@PathVariable<\/h4>\n<p>Bu anotasyon, URI&#8217;n\u0131n bir par\u00e7as\u0131 olarak g\u00f6nderilen de\u011fi\u015fkenleri (path variables) yakalamak i\u00e7in kullan\u0131l\u0131r. \u00d6zellikle bir kayna\u011f\u0131n kimli\u011fini belirtmek i\u00e7in idealdir.<\/p>\n<p><strong>\u00d6rnek:<\/strong><\/p>\n<pre><code class=\"language-java\">@GetMapping(\"\/{id}\") \/\/ GET \/api\/urunler\/123\npublic String getProductById(@PathVariable Long id) {\n    return \"ID'si \" + id + \" olan \u00fcr\u00fcn getiriliyor.\";\n}\n\n@GetMapping(\"\/{kategori}\/{id}\") \/\/ GET \/api\/urunler\/elektronik\/456\npublic String getProductByCategoryAndId(@PathVariable String kategori, @PathVariable Long id) {\n    return kategori + \" kategorisinden ID'si \" + id + \" olan \u00fcr\u00fcn getiriliyor.\";\n}<\/code><\/pre>\n<h4>@RequestParam<\/h4>\n<p>Bu anotasyon, sorgu parametrelerini (query parameters) yakalamak i\u00e7in kullan\u0131l\u0131r. Genellikle filtreleme, s\u0131ralama veya sayfalama gibi opsiyonel parametreler i\u00e7in tercih edilir.<\/p>\n<p><strong>\u00d6rnek:<\/strong><\/p>\n<pre><code class=\"language-java\">@GetMapping\npublic String getProductsFiltered(\n    @RequestParam(required = false) String ad, \/\/ ad parametresi opsiyonel\n    @RequestParam(defaultValue = \"0\") int sayfa\n) {\n    String response = \"\u00dcr\u00fcnler listeleniyor.\";\n    if (ad != null) {\n        response += \" Ad\u0131: \" + ad;\n    }\n    response += \" Sayfa: \" + sayfa;\n    return response;\n}\n\/\/ \u00d6rnek istekler: \/api\/urunler?ad=kalem, \/api\/urunler?sayfa=2, \/api\/urunler?ad=defter&sayfa=1<\/code><\/pre>\n<h4>@RequestBody<\/h4>\n<p>Bu anotasyon, HTTP iste\u011finin g\u00f6vdesini (request body) bir Java nesnesine d\u00f6n\u00fc\u015ft\u00fcrmek i\u00e7in kullan\u0131l\u0131r. Genellikle POST ve PUT isteklerinde, istemciden JSON veya XML format\u0131nda g\u00f6nderilen verileri yakalamak i\u00e7in kullan\u0131l\u0131r. Spring, otomatik olarak uygun HTTP mesaj d\u00f6n\u00fc\u015ft\u00fcr\u00fcc\u00fcs\u00fcn\u00fc kullanarak bu serile\u015ftirmeyi\/deserile\u015ftirmeyi yapar.<\/p>\n<p><strong>\u00d6rnek:<\/strong><\/p>\n<pre><code class=\"language-java\">@PostMapping\npublic Urun createProduct(@RequestBody Urun yeniUrun) {\n    \/\/ yeniUrun nesnesi, gelen JSON verisinden otomatik olarak olu\u015fturulur.\n    System.out.println(\"Yeni \u00fcr\u00fcn olu\u015fturuldu: \" + yeniUrun.getAd());\n    \/\/ \u00dcr\u00fcn\u00fc kaydetme mant\u0131\u011f\u0131 burada olurdu.\n    yeniUrun.setId(999L); \/\/ \u00d6rnek ID atamas\u0131\n    return yeniUrun;\n}\n\n\/\/ Urun s\u0131n\u0131f\u0131 (POJO)\nclass Urun {\n    private Long id;\n    private String ad;\n    private double fiyat;\n\n    \/\/ Constructor, Getter ve Setter metodlar\u0131\n    public Urun() {}\n    public Urun(Long id, String ad, double fiyat) {\n        this.id = id;\n        this.ad = ad;\n        this.fiyat = fiyat;\n    }\n    public Long getId() { return id; }\n    public void setId(Long id) { this.id = id; }\n    public String getAd() { return ad; }\n    public void setAd(String ad) { this.ad = ad; }\n    public double getFiyat() { return fiyat; }\n    public void setFiyat(double fiyat) { this.fiyat = fiyat; }\n}<\/code><\/pre>\n<h4>@RequestHeader<\/h4>\n<p>Bu anotasyon, HTTP iste\u011fi ba\u015fl\u0131klar\u0131ndaki (request headers) belirli de\u011ferleri yakalamak i\u00e7in kullan\u0131l\u0131r. \u00d6rne\u011fin, kimlik do\u011frulama tokenlar\u0131n\u0131 veya dil tercihlerini okumak i\u00e7in faydal\u0131d\u0131r.<\/p>\n<p><strong>\u00d6rnek:<\/strong><\/p>\n<pre><code class=\"language-java\">@GetMapping(\"\/basliklar\")\npublic String getHeaders(@RequestHeader(\"User-Agent\") String userAgent,\n                         @RequestHeader(value = \"Authorization\", required = false) String authorizationHeader) {\n    String response = \"User-Agent: \" + userAgent;\n    if (authorizationHeader != null) {\n        response += \", Authorization: \" + authorizationHeader;\n    }\n    return response;\n}<\/code><\/pre>\n<h3>Cevap D\u00f6n\u00fc\u015f\u00fc: \u0130stemciye Veri G\u00f6nderme<\/h3>\n<p>RESTful servisler sadece istekleri almakla kalmaz, ayn\u0131 zamanda istemcilere anlaml\u0131 ve yap\u0131land\u0131r\u0131lm\u0131\u015f yan\u0131tlar da g\u00f6nderir. <code>@RestController<\/code> metodlar\u0131, \u00e7e\u015fitli yollarla yan\u0131t \u00fcretebilir ve HTTP yan\u0131t\u0131n\u0131n t\u00fcm y\u00f6nleri \u00fczerinde kontrol sa\u011flayabilir.<\/p>\n<h4>Basit Java Nesneleri (POJO) D\u00f6nd\u00fcrme<\/h4>\n<p>Daha \u00f6nce de belirtildi\u011fi gibi, <code>@RestController<\/code> metodlar\u0131 bir Java nesnesi (POJO) d\u00f6nd\u00fcrd\u00fc\u011f\u00fcnde, Spring bu nesneyi otomatik olarak (genellikle JSON format\u0131na) serile\u015ftirir ve HTTP yan\u0131t g\u00f6vdesine yazar. Bu, en basit ve en yayg\u0131n kullan\u0131m senaryosudur.<\/p>\n<p><strong>\u00d6rnek:<\/strong><\/p>\n<pre><code class=\"language-java\">@GetMapping(\"\/detay\/{id}\")\npublic Urun getProductDetails(@PathVariable Long id) {\n    \/\/ Veritaban\u0131ndan \u00fcr\u00fcn\u00fc getirme sim\u00fclasyonu\n    return new Urun(id, \"\u00d6rnek \u00dcr\u00fcn\", 19.99);\n}<\/code><\/pre>\n<p>Bu durumda, Spring varsay\u0131lan olarak 200 OK HTTP durum kodunu kullan\u0131r.<\/p>\n<h4>ResponseEntity ile Tam Kontrol<\/h4>\n<p><code>ResponseEntity<\/code> s\u0131n\u0131f\u0131, geli\u015ftiricilere HTTP yan\u0131t\u0131 \u00fczerinde tam kontrol sa\u011flar. Yan\u0131t\u0131n g\u00f6vdesini, HTTP durum kodunu ve HTTP ba\u015fl\u0131klar\u0131n\u0131 belirlemenize olanak tan\u0131r. Bu, \u00f6zellikle ba\u015far\u0131l\u0131 bir i\u015flemde 201 Created veya kaynak bulunamad\u0131\u011f\u0131nda 404 Not Found gibi \u00f6zel durum kodlar\u0131 d\u00f6nd\u00fcrmeniz gerekti\u011finde \u00e7ok kullan\u0131\u015fl\u0131d\u0131r.<\/p>\n<p><strong>\u00d6rnek:<\/strong><\/p>\n<pre><code class=\"language-java\">import org.springframework.http.HttpStatus;\nimport org.springframework.http.ResponseEntity;\n\n@PostMapping(\"\/olustur\")\npublic ResponseEntity<Urun> createNewProduct(@RequestBody Urun yeniUrun) {\n    \/\/ \u00dcr\u00fcn\u00fc kaydetme mant\u0131\u011f\u0131\n    yeniUrun.setId(100L); \/\/ \u00d6rnek ID\n    return new ResponseEntity<>(yeniUrun, HttpStatus.CREATED); \/\/ 201 Created d\u00f6nd\u00fcr\u00fcr\n}\n\n@GetMapping(\"\/ara\/{id}\")\npublic ResponseEntity<Urun> findProduct(@PathVariable Long id) {\n    \/\/ \u00dcr\u00fcn\u00fc bulma mant\u0131\u011f\u0131\n    if (id == 1L) { \/\/ \u00d6rnek kontrol\n        Urun bulunanUrun = new Urun(1L, \"Kitap\", 25.50);\n        return ResponseEntity.ok(bulunanUrun); \/\/ 200 OK d\u00f6nd\u00fcr\u00fcr\n    } else {\n        return ResponseEntity.notFound().build(); \/\/ 404 Not Found d\u00f6nd\u00fcr\u00fcr\n    }\n}\n\n@DeleteMapping(\"\/sil\/{id}\")\npublic ResponseEntity<Void> deleteProduct(@PathVariable Long id) {\n    \/\/ \u00dcr\u00fcn\u00fc silme mant\u0131\u011f\u0131\n    boolean deleted = true; \/\/ Sim\u00fclasyon\n    if (deleted) {\n        return ResponseEntity.noContent().build(); \/\/ 204 No Content d\u00f6nd\u00fcr\u00fcr\n    } else {\n        return ResponseEntity.status(HttpStatus.BAD_REQUEST).build(); \/\/ 400 Bad Request d\u00f6nd\u00fcr\u00fcr\n    }\n}<\/code><\/pre>\n<p><code>ResponseEntity<\/code> kullanmak, API&#8217;nizin daha anlaml\u0131 ve standartlara uygun HTTP yan\u0131tlar\u0131 vermesini sa\u011flar.<\/p>\n<h4>HTTP Durum Kodlar\u0131n\u0131n \u00d6nemi<\/h4>\n<p>HTTP durum kodlar\u0131, istemciye bir iste\u011fin sonucunu bildiren standartla\u015ft\u0131r\u0131lm\u0131\u015f sinyallerdir. Do\u011fru durum kodlar\u0131n\u0131 kullanmak, API&#8217;nizin anla\u015f\u0131labilirli\u011fini ve kullan\u0131labilirli\u011fini art\u0131r\u0131r.<\/p>\n<p>*   <strong>2xx (Ba\u015far\u0131l\u0131)<\/strong>: \u0130stek ba\u015far\u0131yla al\u0131nd\u0131, anla\u015f\u0131ld\u0131 ve kabul edildi.<br \/>\n    *   <code>200 OK<\/code>: Standart ba\u015far\u0131l\u0131 yan\u0131t.<br \/>\n    *   <code>201 Created<\/code>: Yeni bir kaynak ba\u015far\u0131yla olu\u015fturuldu. POST metodunda s\u0131k\u00e7a kullan\u0131l\u0131r.<br \/>\n    *   <code>204 No Content<\/code>: \u0130stek ba\u015far\u0131yla i\u015flendi, ancak yan\u0131t g\u00f6vdesinde d\u00f6nd\u00fcr\u00fclecek i\u00e7erik yok (\u00f6rn. DELETE iste\u011fi).<br \/>\n*   <strong>4xx (\u0130stemci Hatas\u0131)<\/strong>: \u0130stek ge\u00e7ersiz s\u00f6zdizimi nedeniyle veya ba\u015fka bir nedenden dolay\u0131 yerine getirilemedi.<br \/>\n    *   <code>400 Bad Request<\/code>: \u0130stemci taraf\u0131ndan g\u00f6nderilen istek ge\u00e7ersiz veya hatal\u0131.<br \/>\n    *   <code>401 Unauthorized<\/code>: Kimlik do\u011frulama gereklidir ve sa\u011flanmam\u0131\u015ft\u0131r veya ge\u00e7ersizdir.<br \/>\n    *   <code>403 Forbidden<\/code>: \u0130stemcinin kayna\u011fa eri\u015fim izni yok.<br \/>\n    *   <code>404 Not Found<\/code>: \u0130stenen kaynak sunucuda bulunamad\u0131.<br \/>\n    *   <code>405 Method Not Allowed<\/code>: \u0130stek yap\u0131lan HTTP metodu, kayna\u011fa uygulanamaz.<br \/>\n    *   <code>409 Conflict<\/code>: Kaynakta bir \u00e7ak\u0131\u015fma nedeniyle istek tamamlanamad\u0131 (\u00f6rn. ayn\u0131 ID ile tekrar olu\u015fturma).<br \/>\n*   <strong>5xx (Sunucu Hatas\u0131)<\/strong>: Sunucu, ge\u00e7erli bir iste\u011fi yerine getirirken beklenmeyen bir durumla kar\u015f\u0131la\u015ft\u0131.<br \/>\n    *   <code>500 Internal Server Error<\/code>: Sunucuda beklenmeyen bir hata olu\u015ftu.<\/p>\n<h4>@ResponseStatus<\/h4>\n<p>Bazen bir metodun her zaman belirli bir HTTP durum kodu d\u00f6nd\u00fcrmesi gerekti\u011fini belirtmek isteyebilirsiniz. Bu durumda <code>@ResponseStatus<\/code> anotasyonu kullan\u0131labilir.<\/p>\n<p><strong>\u00d6rnek:<\/strong><\/p>\n<pre><code class=\"language-java\">import org.springframework.http.HttpStatus;\nimport org.springframework.web.bind.annotation.ResponseStatus;\n\n@PostMapping(\"\/kaydet\")\n@ResponseStatus(HttpStatus.CREATED) \/\/ Her zaman 201 Created d\u00f6nd\u00fcr\u00fcr\npublic Urun saveProduct(@RequestBody Urun urun) {\n    \/\/ \u00dcr\u00fcn\u00fc kaydetme mant\u0131\u011f\u0131\n    urun.setId(200L);\n    return urun;\n}<\/code><\/pre>\n<p>Ancak, <code>@ResponseStatus<\/code> sadece ba\u015far\u0131l\u0131 durumlar veya belirli hata durumlar\u0131 i\u00e7in sabit bir kod atamak istedi\u011finizde kullan\u0131\u015fl\u0131d\u0131r. Dinamik durum kodlar\u0131 i\u00e7in <code>ResponseEntity<\/code> daha esnektir.<\/p>\n<h3>Veri Do\u011frulama (Validation)<\/h3>\n<p>Gelen istemci verilerinin ge\u00e7erlili\u011fini kontrol etmek, sa\u011flam bir API geli\u015ftirmenin kritik bir par\u00e7as\u0131d\u0131r. Spring Boot, Bean Validation API&#8217;si (JSR 380) ve Hibernate Validator gibi referans uygulamalarla entegrasyon sayesinde kolay ve g\u00fc\u00e7l\u00fc veri do\u011frulama imkanlar\u0131 sunar.<\/p>\n<h4>@Valid Anotasyonu<\/h4>\n<p>Bir <code>@RequestBody<\/code> veya <code>@ModelAttribute<\/code> parametresiyle gelen veriyi do\u011frulamak i\u00e7in, parametrenin \u00f6n\u00fcne <code>@Valid<\/code> anotasyonunu eklemeniz yeterlidir. Spring, bu nesne \u00fczerindeki k\u0131s\u0131tlamalar\u0131 (constraints) otomatik olarak kontrol eder.<\/p>\n<p><strong>\u00d6rnek:<\/strong><\/p>\n<pre><code class=\"language-java\">import jakarta.validation.Valid;\nimport jakarta.validation.constraints.*; \/\/ Jakarta EE 9+ i\u00e7in\n\/\/ import javax.validation.Valid;\n\/\/ import javax.validation.constraints.*; \/\/ Java EE 8 i\u00e7in\n\n\/\/ Urun s\u0131n\u0131f\u0131 g\u00fcncelleniyor\nclass Urun {\n    private Long id;\n\n    @NotBlank(message = \"\u00dcr\u00fcn ad\u0131 bo\u015f olamaz.\")\n    @Size(min = 3, max = 50, message = \"\u00dcr\u00fcn ad\u0131 3 ile 50 karakter aras\u0131nda olmal\u0131d\u0131r.\")\n    private String ad;\n\n    @Min(value = 0, message = \"Fiyat negatif olamaz.\")\n    @NotNull(message = \"Fiyat bo\u015f olamaz.\")\n    private Double fiyat;\n\n    \/\/ ... Constructor, Getter, Setter\n}\n\n@RestController\n@RequestMapping(\"\/api\/urunler\")\npublic class UrunValidationController {\n\n    @PostMapping(\"\/valid\")\n    public ResponseEntity<Urun> createValidProduct(@Valid @RequestBody Urun yeniUrun) {\n        \/\/ E\u011fer do\u011frulama ba\u015far\u0131s\u0131z olursa, bu metoda gelinmez.\n        \/\/ Hata yakalama mekanizmas\u0131 devreye girer.\n        yeniUrun.setId(300L);\n        return new ResponseEntity<>(yeniUrun, HttpStatus.CREATED);\n    }\n}<\/code><\/pre>\n<p>Bu \u00f6rnekte, <code>Urun<\/code> s\u0131n\u0131f\u0131ndaki <code>@NotBlank<\/code>, <code>@Size<\/code>, <code>@Min<\/code> ve <code>@NotNull<\/code> gibi anotasyonlar, gelen <code>yeniUrun<\/code> nesnesinin belirli kurallara uymas\u0131n\u0131 sa\u011flar. E\u011fer bu kurallar ihlal edilirse, Spring otomatik olarak bir <code>MethodArgumentNotValidException<\/code> f\u0131rlat\u0131r.<\/p>\n<h4>BindingResult ve Hata Mesajlar\u0131<\/h4>\n<p>Do\u011frulama hatalar\u0131n\u0131 daha detayl\u0131 y\u00f6netmek isterseniz, <code>@Valid<\/code> anotasyonlu parametrenin hemen arkas\u0131na bir <code>BindingResult<\/code> parametresi ekleyebilirsiniz. Bu, hatalar\u0131 manuel olarak kontrol etmenizi ve \u00f6zel hata yan\u0131tlar\u0131 olu\u015fturman\u0131z\u0131 sa\u011flar.<\/p>\n<p><strong>\u00d6rnek:<\/strong><\/p>\n<pre><code class=\"language-java\">import org.springframework.validation.BindingResult;\nimport org.springframework.validation.FieldError;\n\n@PostMapping(\"\/valid-manual\")\npublic ResponseEntity<?> createProductManualValidation(@Valid @RequestBody Urun yeniUrun, BindingResult result) {\n    if (result.hasErrors()) {\n        Map<String, String> errors = new HashMap<>();\n        for (FieldError error : result.getFieldErrors()) {\n            errors.put(error.getField(), error.getDefaultMessage());\n        }\n        return new ResponseEntity<>(errors, HttpStatus.BAD_REQUEST); \/\/ 400 Bad Request\n    }\n    yeniUrun.setId(301L);\n    return new ResponseEntity<>(yeniUrun, HttpStatus.CREATED);\n}<\/code><\/pre>\n<p>Genellikle, <code>BindingResult<\/code>&#8216;\u0131 her metodda manuel olarak kontrol etmek yerine, global hata y\u00f6netimi mekanizmalar\u0131 (bir sonraki b\u00f6l\u00fcmde a\u00e7\u0131klanacak) kullan\u0131larak bu hatalar merkezi olarak ele al\u0131n\u0131r.<\/p>\n<h3>Hata Y\u00f6netimi ve \u0130stisna \u0130\u015fleme<\/h3>\n<p>API&#8217;lerin g\u00fcvenilirli\u011fi i\u00e7in hata y\u00f6netimi hayati \u00f6neme sahiptir. \u0130stisnalar\u0131n do\u011fru bir \u015fekilde yakalanmas\u0131 ve istemciye anlaml\u0131 hata yan\u0131tlar\u0131 d\u00f6nd\u00fcr\u00fclmesi, API&#8217;nin kullan\u0131labilirli\u011fini art\u0131r\u0131r. Spring, hata y\u00f6netimini kolayla\u015ft\u0131rmak i\u00e7in \u00e7e\u015fitli mekanizmalar sunar.<\/p>\n<h4>@ExceptionHandler<\/h4>\n<p><code>@ExceptionHandler<\/code> anotasyonu, bir kontrolc\u00fc s\u0131n\u0131f\u0131 i\u00e7inde belirli istisna tiplerini yakalamak i\u00e7in kullan\u0131l\u0131r. Bir metodun \u00fczerine <code>@ExceptionHandler<\/code> ekleyerek, o metodun sadece belirli bir kontrolc\u00fc i\u00e7indeki belirli istisnalar\u0131 ele almas\u0131n\u0131 sa\u011flayabilirsiniz.<\/p>\n<p><strong>\u00d6rnek:<\/strong><\/p>\n<pre><code class=\"language-java\">import org.springframework.web.bind.annotation.ExceptionHandler;\nimport org.springframework.web.bind.annotation.ResponseStatus;\nimport org.springframework.http.HttpStatus;\n\nclass KaynakBulunamadiException extends RuntimeException {\n    public KaynakBulunamadiException(String message) {\n        super(message);\n    }\n}\n\n@RestController\n@RequestMapping(\"\/api\/ornek\")\npublic class HataOrnekController {\n\n    @GetMapping(\"\/kaynak\/{id}\")\n    public String getResource(@PathVariable Long id) {\n        if (id == 0) {\n            throw new KaynakBulunamadiException(\"ID'si 0 olan kaynak bulunamad\u0131.\");\n        }\n        return \"Kaynak bulundu: \" + id;\n    }\n\n    @ExceptionHandler(KaynakBulunamadiException.class)\n    @ResponseStatus(HttpStatus.NOT_FOUND) \/\/ 404 Not Found d\u00f6nd\u00fcr\u00fcr\n    public String handleResourceNotFound(KaynakBulunamadiException ex) {\n        return ex.getMessage();\n    }\n}<\/code><\/pre>\n<p>Bu yakla\u015f\u0131m, kontrolc\u00fcye \u00f6zg\u00fc istisnalar i\u00e7in kullan\u0131\u015fl\u0131d\u0131r. Ancak, bir\u00e7ok kontrolc\u00fcde ayn\u0131 istisna tipini yakalaman\u0131z gerekiyorsa, kodu tekrarlaman\u0131za neden olabilir.<\/p>\n<h4>@ControllerAdvice \/ @RestControllerAdvice<\/h4>\n<p>T\u00fcm uygulama genelindeki istisnalar\u0131 merkezi bir yerden ele almak i\u00e7in <code>@ControllerAdvice<\/code> veya <code>@RestControllerAdvice<\/code> anotasyonlar\u0131 kullan\u0131l\u0131r. Bu, istisna y\u00f6netimini DRY (Don&#8217;t Repeat Yourself) prensibine uygun hale getirir. <code>@RestControllerAdvice<\/code>, <code>@ControllerAdvice<\/code>&#8216;\u0131n <code>@ResponseBody<\/code> i\u00e7eren bir versiyonudur, yani hata yan\u0131tlar\u0131 otomatik olarak JSON\/XML&#8217;e d\u00f6n\u00fc\u015ft\u00fcr\u00fcl\u00fcr.<\/p>\n<p><strong>\u00d6rnek:<\/strong><\/p>\n<pre><code class=\"language-java\">import org.springframework.web.bind.annotation.ControllerAdvice;\nimport org.springframework.web.bind.annotation.ExceptionHandler;\nimport org.springframework.web.bind.annotation.ResponseStatus;\nimport org.springframework.http.HttpStatus;\nimport org.springframework.http.ResponseEntity;\nimport org.springframework.web.bind.MethodArgumentNotValidException;\nimport java.util.HashMap;\nimport java.util.Map;\n\n@RestControllerAdvice\npublic class GlobalExceptionHandler {\n\n    @ExceptionHandler(KaynakBulunamadiException.class)\n    @ResponseStatus(HttpStatus.NOT_FOUND)\n    public Map<String, String> handleKaynakBulunamadi(KaynakBulunamadiException ex) {\n        Map<String, String> errorResponse = new HashMap<>();\n        errorResponse.put(\"error\", \"Kaynak Bulunamad\u0131\");\n        errorResponse.put(\"message\", ex.getMessage());\n        return errorResponse;\n    }\n\n    @ExceptionHandler(MethodArgumentNotValidException.class)\n    @ResponseStatus(HttpStatus.BAD_REQUEST)\n    public Map<String, String> handleValidationExceptions(MethodArgumentNotValidException ex) {\n        Map<String, String> errors = new HashMap<>();\n        ex.getBindingResult().getAllErrors().forEach((error) -> {\n            String fieldName = ((org.springframework.validation.FieldError) error).getField();\n            String errorMessage = error.getDefaultMessage();\n            errors.put(fieldName, errorMessage);\n        });\n        return errors;\n    }\n\n    @ExceptionHandler(Exception.class)\n    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)\n    public Map<String, String> handleGeneralExceptions(Exception ex) {\n        Map<String, String> errorResponse = new HashMap<>();\n        errorResponse.put(\"error\", \"Sunucu Hatas\u0131\");\n        errorResponse.put(\"message\", \"Beklenmeyen bir hata olu\u015ftu: \" + ex.getMessage());\n        return errorResponse;\n    }\n}<\/code><\/pre>\n<p>Bu global hata i\u015fleyici, <code>KaynakBulunamadiException<\/code>&#8216;lar\u0131 404 olarak, <code>@Valid<\/code> do\u011frulamas\u0131 ba\u015far\u0131s\u0131z oldu\u011funda f\u0131rlat\u0131lan <code>MethodArgumentNotValidException<\/code>&#8216;lar\u0131 400 olarak ve di\u011fer t\u00fcm istisnalar\u0131 500 olarak ele al\u0131r. Bu sayede, kontrolc\u00fc metodlar\u0131 sadece i\u015f mant\u0131\u011f\u0131na odaklanabilir.<\/p>\n<h4>ProblemDetail (Spring 6+)<\/h4>\n<p>Spring Framework 6 ile birlikte, RFC 7807 standard\u0131na uygun hata yan\u0131tlar\u0131 olu\u015fturmak i\u00e7in <code>ProblemDetail<\/code> s\u0131n\u0131f\u0131 tan\u0131t\u0131lm\u0131\u015ft\u0131r. Bu, hata yan\u0131tlar\u0131n\u0131 daha standart ve istemciler taraf\u0131ndan daha kolay i\u015flenebilir hale getirir.<\/p>\n<p><strong>\u00d6rnek (Spring 6+):<\/strong><\/p>\n<pre><code class=\"language-java\">\/\/ Sadece \u00f6rnek ama\u00e7l\u0131, ProblemDetail kullan\u0131m\u0131 Spring 6+ gerektirir.\n\/\/ import org.springframework.http.ProblemDetail;\n\/\/ import java.net.URI;\n\/\/\n\/\/ @RestControllerAdvice\n\/\/ public class GlobalExceptionHandlerProblemDetail {\n\/\/\n\/\/     @ExceptionHandler(KaynakBulunamadiException.class)\n\/\/     public ProblemDetail handleKaynakBulunamadi(KaynakBulunamadiException ex) {\n\/\/         ProblemDetail pd = ProblemDetail.forStatusAndDetail(HttpStatus.NOT_FOUND, ex.getMessage());\n\/\/         pd.setTitle(\"Kaynak Bulunamad\u0131\");\n\/\/         pd.setType(URI.create(\"https:\/\/example.com\/errors\/resource-not-found\"));\n\/\/         return pd;\n\/\/     }\n\/\/ }<\/code><\/pre>\n<p><code>ProblemDetail<\/code> kullan\u0131m\u0131, API&#8217;nizin hata yan\u0131tlar\u0131n\u0131 daha profesyonel ve standartlara uygun hale getirir.<\/p>\n<h3>RESTful Servis Tasar\u0131m\u0131nda En \u0130yi Uygulamalar<\/h3>\n<p><code>@RestController<\/code> ile g\u00fc\u00e7l\u00fc API&#8217;ler geli\u015ftirmek, sadece anotasyonlar\u0131 do\u011fru kullanmakla kalmaz, ayn\u0131 zamanda RESTful tasar\u0131m prensiplerine uymay\u0131 da gerektirir.<\/p>\n<p>1.  <strong>Kaynak Odakl\u0131 URI&#8217;lar<\/strong>: URI&#8217;lar, i\u015flenen kaynaklar\u0131 temsil etmeli ve isim (\u00e7o\u011ful) i\u00e7ermelidir, fiil de\u011fil.<br \/>\n    *   <strong>K\u00f6t\u00fc<\/strong>: <code>\/getAllProducts<\/code>, <code>\/createProduct<\/code><br \/>\n    *   <strong>\u0130yi<\/strong>: <code>\/products<\/code><br \/>\n2.  <strong>HTTP Metodlar\u0131n\u0131 Do\u011fru Kullanma<\/strong>: Her HTTP metodu (GET, POST, PUT, DELETE, PATCH) belirli bir anlamsal amaca hizmet eder. Bu ama\u00e7lara uygun kullan\u0131lmal\u0131d\u0131r.<br \/>\n    *   GET: Kaynaklar\u0131 almak i\u00e7in (idempotent ve safe).<br \/>\n    *   POST: Yeni kaynak olu\u015fturmak i\u00e7in (non-idempotent).<br \/>\n    *   PUT: Mevcut bir kayna\u011f\u0131 tamamen g\u00fcncellemek veya yoksa olu\u015fturmak i\u00e7in (idempotent).<br \/>\n    *   PATCH: Mevcut bir kayna\u011f\u0131n k\u0131smi g\u00fcncellemesi i\u00e7in (non-idempotent).<br \/>\n    *   DELETE: Kaynak silmek i\u00e7in (idempotent).<br \/>\n3.  <strong>Durumsuzluk (Statelessness)<\/strong>: Her istek, sunucunun iste\u011fi i\u015flemek i\u00e7in ihtiya\u00e7 duydu\u011fu t\u00fcm bilgiyi i\u00e7ermelidir. Sunucu, istemciden gelen \u00f6nceki isteklerle ilgili herhangi bir &#8220;durum&#8221; bilgisini saklamamal\u0131d\u0131r. Bu, API&#8217;nin \u00f6l\u00e7eklenebilirli\u011fini ve g\u00fcvenilirli\u011fini art\u0131r\u0131r.<br \/>\n4.  <strong>HTTP Durum Kodlar\u0131n\u0131 Anlaml\u0131 Kullanma<\/strong>: \u0130stemciye i\u015flemin sonucunu bildirmek i\u00e7in do\u011fru HTTP durum kodlar\u0131 kullan\u0131lmal\u0131d\u0131r (2xx, 4xx, 5xx).<br \/>\n5.  <strong>Versiyonlama<\/strong>: API&#8217;niz zamanla de\u011fi\u015fece\u011fi i\u00e7in versiyonlama \u00f6nemlidir. URI versiyonlama (<code>\/v1\/products<\/code>), header versiyonlama veya sorgu parametresi versiyonlama (<code>\/products?version=1<\/code>) gibi y\u00f6ntemler kullan\u0131labilir.<br \/>\n6.  <strong>HATEOAS (Hypermedia as the Engine of Application State)<\/strong>: Kaynak yan\u0131tlar\u0131na, ilgili kaynaklara veya i\u015flemlere y\u00f6nelik ba\u011flant\u0131lar ekleyerek istemcinin API&#8217;yi dinamik olarak ke\u015ffetmesine olanak tan\u0131r. Spring HATEOAS k\u00fct\u00fcphanesi bu konuda yard\u0131mc\u0131 olur. (Daha ileri seviye bir konudur.)<br \/>\n7.  <strong>G\u00fcvenlik<\/strong>: API&#8217;ler, kimlik do\u011frulama (Authentication) ve yetkilendirme (Authorization) mekanizmalar\u0131yla korunmal\u0131d\u0131r (\u00f6rn. OAuth2, JWT).<\/p>\n<h3>\u00d6rnek Uygulama: Basit Bir \u00dcr\u00fcn API&#8217;si<\/h3>\n<p>\u015eimdiye kadar \u00f6\u011frendiklerimizi bir araya getirerek, basit bir CRUD (Create, Read, Update, Delete) operasyonlar\u0131n\u0131 destekleyen bir \u00dcr\u00fcn API&#8217;si olu\u015ftural\u0131m.<\/p>\n<pre><code class=\"language-java\">\/\/ src\/main\/java\/com\/example\/demo\/model\/Product.java\npackage com.example.demo.model;\n\nimport jakarta.validation.constraints.Min;\nimport jakarta.validation.constraints.NotBlank;\nimport jakarta.validation.constraints.NotNull;\nimport jakarta.validation.constraints.Size;\n\npublic class Product {\n    private Long id;\n\n    @NotBlank(message = \"Product name cannot be empty\")\n    @Size(min = 3, max = 50, message = \"Product name must be between 3 and 50 characters\")\n    private String name;\n\n    @Min(value = 0, message = \"Price cannot be negative\")\n    @NotNull(message = \"Price cannot be null\")\n    private Double price;\n\n    public Product() {}\n\n    public Product(Long id, String name, Double price) {\n        this.id = id;\n        this.name = name;\n        this.price = price;\n    }\n\n    \/\/ Getters and Setters\n    public Long getId() { return id; }\n    public void setId(Long id) { this.id = id; }\n    public String getName() { return name; }\n    public void setName(String name) { this.name = name; }\n    public Double getPrice() { return price; }\n    public void setPrice(Double price) { this.price = price; }\n}\n\n\/\/ src\/main\/java\/com\/example\/demo\/service\/ProductService.java\npackage com.example.demo.service;\n\nimport com.example.demo.model.Product;\nimport org.springframework.stereotype.Service;\nimport java.util.ArrayList;\nimport java.util.List;\nimport java.util.Optional;\nimport java.util.concurrent.atomic.AtomicLong;\n\n@Service\npublic class ProductService {\n    private final List<Product> products = new ArrayList<>();\n    private final AtomicLong counter = new AtomicLong();\n\n    public ProductService() {\n        products.add(new Product(counter.incrementAndGet(), \"Laptop\", 1200.0));\n        products.add(new Product(counter.incrementAndGet(), \"Mouse\", 25.0));\n        products.add(new Product(counter.incrementAndGet(), \"Keyboard\", 75.0));\n    }\n\n    public List<Product> findAll() {\n        return new ArrayList<>(products);\n    }\n\n    public Optional<Product> findById(Long id) {\n        return products.stream().filter(p -> p.getId().equals(id)).findFirst();\n    }\n\n    public Product save(Product product) {\n        product.setId(counter.incrementAndGet());\n        products.add(product);\n        return product;\n    }\n\n    public Optional<Product> update(Long id, Product updatedProduct) {\n        return findById(id).map(existingProduct -> {\n            existingProduct.setName(updatedProduct.getName());\n            existingProduct.setPrice(updatedProduct.getPrice());\n            return existingProduct;\n        });\n    }\n\n    public boolean deleteById(Long id) {\n        return products.removeIf(p -> p.getId().equals(id));\n    }\n}\n\n\/\/ src\/main\/java\/com\/example\/demo\/controller\/ProductController.java\npackage com.example.demo.controller;\n\nimport com.example.demo.model.Product;\nimport com.example.demo.service.ProductService;\nimport jakarta.validation.Valid;\nimport org.springframework.http.HttpStatus;\nimport org.springframework.http.ResponseEntity;\nimport org.springframework.web.bind.annotation.*;\n\nimport java.util.List;\n\n@RestController\n@RequestMapping(\"\/api\/v1\/products\")\npublic class ProductController {\n\n    private final ProductService productService;\n\n    public ProductController(ProductService productService) {\n        this.productService = productService;\n    }\n\n    \/\/ GET \/api\/v1\/products - T\u00fcm \u00fcr\u00fcnleri getir\n    @GetMapping\n    public ResponseEntity<List<Product>> getAllProducts() {\n        return ResponseEntity.ok(productService.findAll());\n    }\n\n    \/\/ GET \/api\/v1\/products\/{id} - Belirli bir \u00fcr\u00fcn\u00fc getir\n    @GetMapping(\"\/{id}\")\n    public ResponseEntity<Product> getProductById(@PathVariable Long id) {\n        return productService.findById(id)\n                .map(ResponseEntity::ok)\n                .orElse(ResponseEntity.notFound().build());\n    }\n\n    \/\/ POST \/api\/v1\/products - Yeni \u00fcr\u00fcn olu\u015ftur\n    @PostMapping\n    public ResponseEntity<Product> createProduct(@Valid @RequestBody Product product) {\n        Product savedProduct = productService.save(product);\n        return new ResponseEntity<>(savedProduct, HttpStatus.CREATED);\n    }\n\n    \/\/ PUT \/api\/v1\/products\/{id} - Mevcut \u00fcr\u00fcn\u00fc g\u00fcncelle\n    @PutMapping(\"\/{id}\")\n    public ResponseEntity<Product> updateProduct(@PathVariable Long id, @Valid @RequestBody Product product) {\n        return productService.update(id, product)\n                .map(ResponseEntity::ok)\n                .orElse(ResponseEntity.notFound().build());\n    }\n\n    \/\/ DELETE \/api\/v1\/products\/{id} - \u00dcr\u00fcn\u00fc sil\n    @DeleteMapping(\"\/{id}\")\n    public ResponseEntity<Void> deleteProduct(@PathVariable Long id) {\n        if (productService.deleteById(id)) {\n            return ResponseEntity.noContent().build();\n        } else {\n            return ResponseEntity.notFound().build();\n        }\n    }\n}<\/code><\/pre>\n<p>Bu \u00f6rnek, <code>@RestController<\/code>&#8216;\u0131n temel CRUD operasyonlar\u0131 i\u00e7in nas\u0131l kullan\u0131laca\u011f\u0131n\u0131, <code>@Valid<\/code> ile veri do\u011frulamas\u0131n\u0131 ve <code>ResponseEntity<\/code> ile HTTP durum kodlar\u0131n\u0131n nas\u0131l y\u00f6netilece\u011fini g\u00f6stermektedir. <code>ProductService<\/code> s\u0131n\u0131f\u0131 basit bir <code>List<\/code> kullanarak veritaban\u0131 i\u015flemlerini sim\u00fcle eder.<\/p>\n<h3>Sonu\u00e7 ve Gelecek Trendler<\/h3>\n<p><code>@RestController<\/code> anotasyonu, Spring Framework ve Spring Boot&#8217;un RESTful web servisleri geli\u015ftirme konusundaki merkezi ve en g\u00fc\u00e7l\u00fc ara\u00e7lar\u0131ndan biridir. Geli\u015ftiricilere, HTTP metodlar\u0131, URI e\u015fle\u015ftirmeleri, parametre ba\u011flama, otomatik serile\u015ftirme\/deserile\u015ftirme, veri do\u011frulama ve kapsaml\u0131 hata y\u00f6netimi gibi alanlarda zengin bir \u00f6zellik seti sunar. Bu sayede, Spring geli\u015ftiricileri h\u0131zl\u0131, verimli ve standartlara uygun API&#8217;ler olu\u015fturabilirler.<\/p>\n<p>Spring Boot&#8217;un <code>@RestController<\/code> ile sundu\u011fu bu kolayl\u0131klar, mikroservis mimarilerinin yayg\u0131nla\u015fmas\u0131nda \u00f6nemli bir rol oynam\u0131\u015ft\u0131r. Geli\u015ftiricilerin, altyap\u0131 detaylar\u0131yla u\u011fra\u015fmak yerine i\u015f mant\u0131\u011f\u0131na odaklanmas\u0131n\u0131 sa\u011flayarak \u00fcretkenli\u011fi art\u0131r\u0131r.<\/p>\n<p>Gelecekte, REST&#8217;in taht\u0131n\u0131 sallayan GraphQL veya gRPC gibi alternatifler ortaya \u00e7\u0131ksa da, REST&#8217;in basitli\u011fi, yayg\u0131nl\u0131\u011f\u0131 ve HTTP&#8217;nin temel prensiplerine olan ba\u011fl\u0131l\u0131\u011f\u0131 sayesinde hala modern web servislerinin \u00f6nemli bir par\u00e7as\u0131 olmaya devam edecektir. Spring ekosistemi de bu geli\u015fmelere ayak uydurarak, <code>@RestController<\/code>&#8216;\u0131 Spring WebFlux ile reaktif programlama paradigmalar\u0131na uyarlam\u0131\u015f ve <code>ProblemDetail<\/code> gibi yeni \u00f6zelliklerle hata y\u00f6netimini daha da standartla\u015ft\u0131rm\u0131\u015ft\u0131r.<\/p>\n<p>Sonu\u00e7 olarak, Spring <code>@RestController<\/code>, Java d\u00fcnyas\u0131nda RESTful API geli\u015ftirmek isteyen her geli\u015ftiricinin ara\u00e7 kutusunda bulunmas\u0131 gereken vazge\u00e7ilmez bir bile\u015fendir. Onun sundu\u011fu kolayl\u0131klar ve entegrasyonlar sayesinde, karma\u015f\u0131k sistemler i\u00e7in bile sa\u011flam ve \u00f6l\u00e7eklenebilir API&#8217;ler olu\u015fturmak art\u0131k \u00e7ok daha eri\u015filebilir hale gelmi\u015ftir.<\/body><\/p>\n","protected":false},"excerpt":{"rendered":"Spring RestController: RESTful Web Servisleri Geli\u015ftirmede Temel Ta\u015f\nGiri\u015f: REST ve Spring Boot Ekosisteminde Yeri\nG\u00fcn\u00fcm\u00fcz\u00fcn da\u011f\u0131t\u0131k siste","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"csco_page_header_type":"","csco_page_load_nextpost":"","csco_page_subscribe_form":"","csco_page_contact_form":"","footnotes":""},"categories":[1],"tags":[],"class_list":{"0":"post-35419","1":"post","2":"type-post","3":"status-publish","4":"format-standard","6":"category-genel","7":"cs-entry","8":"cs-video-wrap"},"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v20.5 (Yoast SEO v25.3.1) - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Spring RestController: RESTful Web Servisleri Geli\u015ftirmede Temel Ta\u015f - Kodlar\u0131n Gizemli D\u00fcnyas\u0131<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/fatihsoysal.com\/blog\/spring-restcontroller-restful-web-servisleri-gelistirmede-temel-tas\/\" \/>\n<meta property=\"og:locale\" content=\"tr_TR\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Spring RestController: RESTful Web Servisleri Geli\u015ftirmede Temel Ta\u015f\" \/>\n<meta property=\"og:description\" content=\"Spring RestController: RESTful Web Servisleri Geli\u015ftirmede Temel Ta\u015f Giri\u015f: REST ve Spring Boot Ekosisteminde Yeri G\u00fcn\u00fcm\u00fcz\u00fcn da\u011f\u0131t\u0131k siste\" \/>\n<meta property=\"og:url\" content=\"https:\/\/fatihsoysal.com\/blog\/spring-restcontroller-restful-web-servisleri-gelistirmede-temel-tas\/\" \/>\n<meta property=\"og:site_name\" content=\"Kodlar\u0131n Gizemli D\u00fcnyas\u0131\" \/>\n<meta property=\"article:published_time\" content=\"2025-11-29T09:40:55+00:00\" \/>\n<meta name=\"author\" content=\"Fatih Soysal\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Yazan:\" \/>\n\t<meta name=\"twitter:data1\" content=\"Fatih Soysal\" \/>\n\t<meta name=\"twitter:label2\" content=\"Tahmini okuma s\u00fcresi\" \/>\n\t<meta name=\"twitter:data2\" content=\"21 dakika\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/fatihsoysal.com\/blog\/spring-restcontroller-restful-web-servisleri-gelistirmede-temel-tas\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/fatihsoysal.com\/blog\/spring-restcontroller-restful-web-servisleri-gelistirmede-temel-tas\/\"},\"author\":{\"name\":\"Fatih Soysal\",\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/002a254750921dcfd568a99e48240dd1\"},\"headline\":\"Spring RestController: RESTful Web Servisleri Geli\u015ftirmede Temel Ta\u015f\",\"datePublished\":\"2025-11-29T09:40:55+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/fatihsoysal.com\/blog\/spring-restcontroller-restful-web-servisleri-gelistirmede-temel-tas\/\"},\"wordCount\":2497,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/002a254750921dcfd568a99e48240dd1\"},\"inLanguage\":\"tr\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/fatihsoysal.com\/blog\/spring-restcontroller-restful-web-servisleri-gelistirmede-temel-tas\/#respond\"]}],\"copyrightYear\":\"2025\",\"copyrightHolder\":{\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#organization\"}},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/fatihsoysal.com\/blog\/spring-restcontroller-restful-web-servisleri-gelistirmede-temel-tas\/\",\"url\":\"https:\/\/fatihsoysal.com\/blog\/spring-restcontroller-restful-web-servisleri-gelistirmede-temel-tas\/\",\"name\":\"Spring RestController: RESTful Web Servisleri Geli\u015ftirmede Temel Ta\u015f - Kodlar\u0131n Gizemli D\u00fcnyas\u0131\",\"isPartOf\":{\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#website\"},\"datePublished\":\"2025-11-29T09:40:55+00:00\",\"breadcrumb\":{\"@id\":\"https:\/\/fatihsoysal.com\/blog\/spring-restcontroller-restful-web-servisleri-gelistirmede-temel-tas\/#breadcrumb\"},\"inLanguage\":\"tr\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/fatihsoysal.com\/blog\/spring-restcontroller-restful-web-servisleri-gelistirmede-temel-tas\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/fatihsoysal.com\/blog\/spring-restcontroller-restful-web-servisleri-gelistirmede-temel-tas\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Anasayfa\",\"item\":\"https:\/\/fatihsoysal.com\/blog\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Spring RestController: RESTful Web Servisleri Geli\u015ftirmede Temel Ta\u015f\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#website\",\"url\":\"https:\/\/fatihsoysal.com\/blog\/\",\"name\":\"Fatihsoysal.com\",\"description\":\"Blog - Yaz\u0131l\u0131m D\u00fcnyas\u0131 Tecr\u00fcbelerim\",\"publisher\":{\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/002a254750921dcfd568a99e48240dd1\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/fatihsoysal.com\/blog\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"tr\"},{\"@type\":[\"Person\",\"Organization\"],\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/002a254750921dcfd568a99e48240dd1\",\"name\":\"Fatih Soysal\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"tr\",\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/fatihsoysal.com\/blog\/wp-content\/uploads\/2024\/04\/cropped-replicate-prediction-3kgg1hgjn5rgp0cf0p5tr0jw7w-1.png\",\"contentUrl\":\"https:\/\/fatihsoysal.com\/blog\/wp-content\/uploads\/2024\/04\/cropped-replicate-prediction-3kgg1hgjn5rgp0cf0p5tr0jw7w-1.png\",\"width\":512,\"height\":512,\"caption\":\"Fatih Soysal\"},\"logo\":{\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/image\/\"},\"description\":\"Kullan\u0131m ve kodlama m\u00fckemmeliyetini odak alan uygulamalar olu\u015fturma deneyimine sahip, profesyonel olarak 15+ y\u0131l \u00fczeri deneyime sahip bir yaz\u0131l\u0131m m\u00fchendisi.\",\"url\":\"https:\/\/fatihsoysal.com\/blog\/author\/fatihsoysal\/\"}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"Spring RestController: RESTful Web Servisleri Geli\u015ftirmede Temel Ta\u015f - Kodlar\u0131n Gizemli D\u00fcnyas\u0131","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/fatihsoysal.com\/blog\/spring-restcontroller-restful-web-servisleri-gelistirmede-temel-tas\/","og_locale":"tr_TR","og_type":"article","og_title":"Spring RestController: RESTful Web Servisleri Geli\u015ftirmede Temel Ta\u015f","og_description":"Spring RestController: RESTful Web Servisleri Geli\u015ftirmede Temel Ta\u015f Giri\u015f: REST ve Spring Boot Ekosisteminde Yeri G\u00fcn\u00fcm\u00fcz\u00fcn da\u011f\u0131t\u0131k siste","og_url":"https:\/\/fatihsoysal.com\/blog\/spring-restcontroller-restful-web-servisleri-gelistirmede-temel-tas\/","og_site_name":"Kodlar\u0131n Gizemli D\u00fcnyas\u0131","article_published_time":"2025-11-29T09:40:55+00:00","author":"Fatih Soysal","twitter_card":"summary_large_image","twitter_misc":{"Yazan:":"Fatih Soysal","Tahmini okuma s\u00fcresi":"21 dakika"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/fatihsoysal.com\/blog\/spring-restcontroller-restful-web-servisleri-gelistirmede-temel-tas\/#article","isPartOf":{"@id":"https:\/\/fatihsoysal.com\/blog\/spring-restcontroller-restful-web-servisleri-gelistirmede-temel-tas\/"},"author":{"name":"Fatih Soysal","@id":"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/002a254750921dcfd568a99e48240dd1"},"headline":"Spring RestController: RESTful Web Servisleri Geli\u015ftirmede Temel Ta\u015f","datePublished":"2025-11-29T09:40:55+00:00","mainEntityOfPage":{"@id":"https:\/\/fatihsoysal.com\/blog\/spring-restcontroller-restful-web-servisleri-gelistirmede-temel-tas\/"},"wordCount":2497,"commentCount":0,"publisher":{"@id":"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/002a254750921dcfd568a99e48240dd1"},"inLanguage":"tr","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/fatihsoysal.com\/blog\/spring-restcontroller-restful-web-servisleri-gelistirmede-temel-tas\/#respond"]}],"copyrightYear":"2025","copyrightHolder":{"@id":"https:\/\/fatihsoysal.com\/blog\/#organization"}},{"@type":"WebPage","@id":"https:\/\/fatihsoysal.com\/blog\/spring-restcontroller-restful-web-servisleri-gelistirmede-temel-tas\/","url":"https:\/\/fatihsoysal.com\/blog\/spring-restcontroller-restful-web-servisleri-gelistirmede-temel-tas\/","name":"Spring RestController: RESTful Web Servisleri Geli\u015ftirmede Temel Ta\u015f - Kodlar\u0131n Gizemli D\u00fcnyas\u0131","isPartOf":{"@id":"https:\/\/fatihsoysal.com\/blog\/#website"},"datePublished":"2025-11-29T09:40:55+00:00","breadcrumb":{"@id":"https:\/\/fatihsoysal.com\/blog\/spring-restcontroller-restful-web-servisleri-gelistirmede-temel-tas\/#breadcrumb"},"inLanguage":"tr","potentialAction":[{"@type":"ReadAction","target":["https:\/\/fatihsoysal.com\/blog\/spring-restcontroller-restful-web-servisleri-gelistirmede-temel-tas\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/fatihsoysal.com\/blog\/spring-restcontroller-restful-web-servisleri-gelistirmede-temel-tas\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Anasayfa","item":"https:\/\/fatihsoysal.com\/blog\/"},{"@type":"ListItem","position":2,"name":"Spring RestController: RESTful Web Servisleri Geli\u015ftirmede Temel Ta\u015f"}]},{"@type":"WebSite","@id":"https:\/\/fatihsoysal.com\/blog\/#website","url":"https:\/\/fatihsoysal.com\/blog\/","name":"Fatihsoysal.com","description":"Blog - Yaz\u0131l\u0131m D\u00fcnyas\u0131 Tecr\u00fcbelerim","publisher":{"@id":"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/002a254750921dcfd568a99e48240dd1"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/fatihsoysal.com\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"tr"},{"@type":["Person","Organization"],"@id":"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/002a254750921dcfd568a99e48240dd1","name":"Fatih Soysal","image":{"@type":"ImageObject","inLanguage":"tr","@id":"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/image\/","url":"https:\/\/fatihsoysal.com\/blog\/wp-content\/uploads\/2024\/04\/cropped-replicate-prediction-3kgg1hgjn5rgp0cf0p5tr0jw7w-1.png","contentUrl":"https:\/\/fatihsoysal.com\/blog\/wp-content\/uploads\/2024\/04\/cropped-replicate-prediction-3kgg1hgjn5rgp0cf0p5tr0jw7w-1.png","width":512,"height":512,"caption":"Fatih Soysal"},"logo":{"@id":"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/image\/"},"description":"Kullan\u0131m ve kodlama m\u00fckemmeliyetini odak alan uygulamalar olu\u015fturma deneyimine sahip, profesyonel olarak 15+ y\u0131l \u00fczeri deneyime sahip bir yaz\u0131l\u0131m m\u00fchendisi.","url":"https:\/\/fatihsoysal.com\/blog\/author\/fatihsoysal\/"}]}},"yoast_meta":{"yoast_wpseo_title":"","yoast_wpseo_metadesc":"","yoast_wpseo_canonical":""},"amp_enabled":true,"_links":{"self":[{"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/posts\/35419","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/comments?post=35419"}],"version-history":[{"count":1,"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/posts\/35419\/revisions"}],"predecessor-version":[{"id":35420,"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/posts\/35419\/revisions\/35420"}],"wp:attachment":[{"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/media?parent=35419"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/categories?post=35419"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/tags?post=35419"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}