Menggunakan Spring ResponseEntity untuk Memanipulasi Respon HTTP

1. Perkenalan

Dengan menggunakan Spring, kami biasanya memiliki banyak cara untuk mencapai tujuan yang sama, termasuk menyesuaikan respons HTTP.

Dalam tutorial singkat ini, kita akan melihat cara mengatur isi, status, dan header dari respons HTTP menggunakan ResponseEntity .

2. ResponEntity

ResponseEntity mewakili seluruh respons HTTP: kode status, header, dan isi . Hasilnya, kita dapat menggunakannya untuk mengonfigurasi respons HTTP sepenuhnya.

Jika kita ingin menggunakannya, kita harus mengembalikannya dari titik akhir; Musim semi mengurus sisanya.

ResponseEntity adalah tipe generik. Akibatnya, kita dapat menggunakan tipe apa pun sebagai isi respons:

@GetMapping("/hello") ResponseEntity hello() { return new ResponseEntity("Hello World!", HttpStatus.OK); }

Karena kami menentukan status respons secara terprogram, kami dapat kembali dengan kode status berbeda untuk skenario berbeda:

@GetMapping("/age") ResponseEntity age( @RequestParam("yearOfBirth") int yearOfBirth) { if (isInFuture(yearOfBirth)) { return new ResponseEntity( "Year of birth cannot be in the future", HttpStatus.BAD_REQUEST); } return new ResponseEntity( "Your age is " + calculateAge(yearOfBirth), HttpStatus.OK); }

Selain itu, kita dapat mengatur header HTTP:

@GetMapping("/customHeader") ResponseEntity customHeader() { HttpHeaders headers = new HttpHeaders(); headers.add("Custom-Header", "foo"); return new ResponseEntity( "Custom header set", headers, HttpStatus.OK); }

Selanjutnya, ResponseEntity menyediakan dua antarmuka pembangun bersarang : HeadersBuilder dan subinterface-nya, BodyBuilder . Oleh karena itu, kami dapat mengakses kapabilitas mereka melalui metode statis ResponseEntity .

Kasus paling sederhana adalah respons dengan isi dan kode respons HTTP 200:

@GetMapping("/hello") ResponseEntity hello() { return ResponseEntity.ok("Hello World!"); }

Untuk kode status HTTP paling populer, kami mendapatkan metode statis:

BodyBuilder accepted(); BodyBuilder badRequest(); BodyBuilder created(java.net.URI location); HeadersBuilder noContent(); HeadersBuilder notFound(); BodyBuilder ok();

Selain itu, kita dapat menggunakan status BodyBuilder (status HttpStatus) dan metode status BodyBuilder (status int) untuk menetapkan status HTTP apa pun.

Akhirnya, dengan ResponseEntity BodyBuilder.body (T body) kita dapat mengatur isi respons HTTP:

@GetMapping("/age") ResponseEntity age(@RequestParam("yearOfBirth") int yearOfBirth) { if (isInFuture(yearOfBirth)) { return ResponseEntity.badRequest() .body("Year of birth cannot be in the future"); } return ResponseEntity.status(HttpStatus.OK) .body("Your age is " + calculateAge(yearOfBirth)); }

Kami juga dapat mengatur tajuk khusus:

@GetMapping("/customHeader") ResponseEntity customHeader() { return ResponseEntity.ok() .header("Custom-Header", "foo") .body("Custom header set"); }

Karena BodyBuilder.body () mengembalikan ResponseEntity alih-alih BodyBuilder, ini harus menjadi panggilan terakhir.

Perhatikan bahwa dengan HeaderBuilder kami tidak dapat menyetel properti apa pun dari isi respons.

Ketika kembali ResponseEntity objek dari controller, kita mungkin mendapatkan pengecualian atau kesalahan saat memproses permintaan dan ingin kembali informasi kesalahan-terkait dengan pengguna direpresentasikan sebagai beberapa jenis lain, katakanlah E .

Spring 3.2 menghadirkan dukungan untuk @ExceptionHandler global dengan anotasi @ControllerAdvice baru , yang menangani jenis skenario ini. Untuk detail yang lebih mendalam, lihat artikel kami yang ada di sini.

Meskipun ResponseEntity sangat kuat, kita tidak boleh terlalu sering menggunakannya. Dalam kasus sederhana, ada opsi lain yang memenuhi kebutuhan kita dan menghasilkan kode yang jauh lebih bersih.

3. Alternatif

3.1. @Tokopedia

Dalam aplikasi klasik Spring MVC, endpoint biasanya mengembalikan halaman HTML yang telah dirender. Terkadang kita hanya perlu mengembalikan data yang sebenarnya; misalnya, saat kita menggunakan endpoint dengan AJAX.

Dalam kasus seperti itu, kita dapat menandai metode penangan permintaan dengan @ResponseBody , dan Spring memperlakukan nilai hasil dari metode tersebut sebagai isi respons HTTP itu sendiri.

Untuk informasi lebih lanjut, artikel ini adalah tempat yang baik untuk memulai.

3.2. @Tokopedia

Saat titik akhir berhasil dikembalikan, Spring memberikan respons HTTP 200 (OK). Jika endpoint melontarkan pengecualian, Spring mencari penangan pengecualian yang memberi tahu status HTTP mana yang akan digunakan.

Kita dapat menandai metode ini dengan @ResponseStatus, dan oleh karena itu, Spring kembali dengan status HTTP khusus .

Untuk contoh lainnya, kunjungi artikel kami tentang kode status ubahsuaian.

3.3. Memanipulasi Respon Secara Langsung

Spring juga memungkinkan kita mengakses objek javax.servlet.http.HttpServletResponse secara langsung; kita hanya perlu mendeklarasikannya sebagai argumen metode:

@GetMapping("/manual") void manual(HttpServletResponse response) throws IOException { response.setHeader("Custom-Header", "foo"); response.setStatus(200); response.getWriter().println("Hello World!"); }

Karena Spring menyediakan abstraksi dan kemampuan tambahan di atas implementasi yang mendasarinya, kita tidak boleh memanipulasi respons dengan cara ini .

4. Kesimpulan

Dalam artikel ini, kami membahas beberapa cara untuk memanipulasi respons HTTP di Spring, dan memeriksa manfaat dan kekurangannya.

Seperti biasa, contoh tersedia di GitHub.