Saya sedang menulis aplikasi web REST (NetBeans 6.9, JAX-RS, TopLink Essentials) dan mencoba mengembalikan kode status JSON dan HTTP. Saya memiliki kode yang siap dan berfungsi yang mengembalikan JSON ketika metode HTTP GET dipanggil dari klien. Pada dasarnya:
@Path("get/id")
@GET
@Produces("application/json")
public M_機械 getMachineToUpdate(@PathParam("id") String id) {
// some code to return JSON ...
return myJson;
}
Tetapi saya juga ingin mengembalikan kode status HTTP (500, 200, 204, dll.) Bersama dengan data JSON.
Saya mencoba menggunakan HttpServletResponse
:
response.sendError("error message", 500);
Tapi ini membuat browser berpikir itu "nyata" 500 sehingga halaman web output adalah halaman kesalahan HTTP 500 biasa.
Saya ingin mengembalikan kode status HTTP sehingga JavaScript sisi klien saya dapat menangani beberapa logika tergantung padanya (untuk misalnya menampilkan kode kesalahan dan pesan pada halaman HTML). Apakah ini mungkin atau haruskah kode status HTTP tidak digunakan untuk hal seperti itu?
sumber
Jawaban:
Ini sebuah contoh:
Lihatlah kelas Respon .
Perhatikan bahwa Anda harus selalu menentukan jenis konten, terutama jika Anda melewati beberapa jenis konten, tetapi jika setiap pesan akan direpresentasikan sebagai JSON, Anda bisa membuat anotasi metode dengan
@Produces("application/json")
sumber
return Response.status(Response.Status.Forbidden).entity(myPOJO).build();
Pekerjaan seolah-olah Anda maureturn myPOJO;
, tetapi dengan pengaturan tambahan kode Status-HTTP.Ada beberapa kasus penggunaan untuk mengatur kode status HTTP di layanan web REST, dan setidaknya satu tidak cukup didokumentasikan dalam jawaban yang ada (yaitu ketika Anda menggunakan JSON / XML serialisasi otomatis menggunakan JAXB, dan Anda ingin mengembalikan objek menjadi serial, tetapi juga kode status berbeda dari standar 200).
Jadi izinkan saya mencoba dan menyebutkan berbagai kasus penggunaan dan solusi untuk masing-masingnya:
1. Kode kesalahan (500, 404, ...)
Kasus penggunaan paling umum ketika Anda ingin mengembalikan kode status berbeda dari pada
200 OK
saat kesalahan terjadi.Sebagai contoh:
a) Melempar pengecualian
Dalam hal itu, saya berpikir bahwa cara terbersih untuk menangani masalah adalah dengan melemparkan pengecualian. Pengecualian ini akan ditangani oleh
ExceptionMapper
, yang akan menerjemahkan pengecualian menjadi respons dengan kode kesalahan yang sesuai.Anda dapat menggunakan default
ExceptionMapper
yang datang dengan pra-konfigurasi dengan Jersey (dan saya kira itu sama dengan implementasi lainnya) dan membuang salah satu dari sub-kelas yang adajavax.ws.rs.WebApplicationException
. Ini adalah tipe pengecualian yang ditentukan sebelumnya yang dipetakan ke kode kesalahan yang berbeda, misalnya:Dll. Anda dapat menemukan daftar di sini: API
Atau, Anda dapat menentukan pengecualian dan
ExceptionMapper
kelas khusus Anda sendiri , dan menambahkan pemetaan ini ke Jersey dengan cara@Provider
anotasi ( sumber contoh ini ):Pemberi :
Catatan: Anda juga bisa menulis ExceptionMappers untuk jenis pengecualian yang ada yang Anda gunakan.
b) Gunakan pembuat Respons
Cara lain untuk menetapkan kode status adalah menggunakan
Response
pembangun untuk membangun respons dengan kode yang dimaksud.Dalam hal itu, jenis pengembalian metode Anda harus
javax.ws.rs.core.Response
. Ini dijelaskan dalam berbagai tanggapan lain seperti jawaban diterima hisdrewness dan terlihat seperti ini:2. Sukses, tetapi tidak 200
Kasus lain ketika Anda ingin mengatur status pengembalian adalah ketika operasi berhasil, tetapi Anda ingin mengembalikan kode sukses yang berbeda dari 200, bersama dengan konten yang Anda kembalikan di badan.
Kasus penggunaan yang sering terjadi adalah ketika Anda membuat entitas baru (
POST
permintaan) dan ingin mengembalikan info tentang entitas baru ini atau mungkin entitas itu sendiri, bersama dengan201 Created
kode status.Salah satu pendekatan adalah dengan menggunakan objek respons seperti dijelaskan di atas dan mengatur tubuh permintaan sendiri. Namun, dengan melakukan ini, Anda kehilangan kemampuan untuk menggunakan serialisasi otomatis ke XML atau JSON yang disediakan oleh JAXB.
Ini adalah metode asli yang mengembalikan objek entitas yang akan diserialisasi ke JSON oleh JAXB:
Ini akan mengembalikan representasi JSON dari pengguna yang baru dibuat, tetapi status pengembalian akan 200, bukan 201.
Sekarang masalahnya adalah jika saya ingin menggunakan
Response
pembangun untuk mengatur kode kembali, saya harus mengembalikanResponse
objek dalam metode saya. Bagaimana saya masih mengembalikanUser
objek yang akan diserialisasi?a) Tetapkan kode pada respons servlet
Salah satu pendekatan untuk mengatasi ini adalah dengan mendapatkan objek permintaan servlet dan mengatur sendiri kode respons secara manual, seperti yang ditunjukkan dalam jawaban Garett Wilson:
Metode ini masih mengembalikan objek entitas dan kode statusnya adalah 201.
Perhatikan bahwa untuk membuatnya berfungsi, saya harus memadamkan respons. Ini adalah kebangkitan kode API Servlet tingkat rendah yang tidak menyenangkan di sumber daya JAX_RS kami yang bagus, dan jauh lebih buruk, hal itu menyebabkan tajuk tidak dapat dimodifikasi setelah ini karena mereka sudah dikirim melalui telepon.
b) Gunakan objek respons dengan entitas
Solusi terbaik, dalam hal ini, adalah dengan menggunakan objek Respons dan mengatur entitas untuk diserialisasi pada objek respons ini. Akan menyenangkan untuk membuat objek Respons generik untuk menunjukkan jenis entitas payload dalam kasus itu, tetapi saat ini tidak demikian.
Dalam hal itu, kami menggunakan metode yang dibuat dari kelas pembuat respons untuk menetapkan kode status ke 201. Kami meneruskan objek entitas (pengguna) ke respons melalui metode entitas ().
Hasilnya adalah bahwa kode HTTP adalah 401 seperti yang kita inginkan, dan isi dari respons adalah JSON yang sama persis seperti yang kita miliki sebelumnya ketika kita baru saja mengembalikan objek Pengguna. Itu juga menambahkan header lokasi.
Kelas Respons memiliki sejumlah metode pembangun untuk status yang berbeda (stati?) Seperti:
Response.accepted () Response.ok () Response.noContent () Response.notAcceptable ()
NB: objek hateoas adalah kelas pembantu yang saya kembangkan untuk membantu menghasilkan sumber daya URI. Anda harus membuat mekanisme sendiri di sini;)
Itu saja.
Saya harap tanggapan panjang ini membantu seseorang :)
sumber
flush
memang kotor.Jawaban oleh hisdrewness akan bekerja, tetapi memodifikasi seluruh pendekatan untuk membiarkan penyedia seperti Jackson + JAXB secara otomatis mengkonversi objek Anda kembali ke beberapa format output seperti JSON. Terinspirasi oleh pos Apache CXF (yang menggunakan kelas khusus-CXF) Saya telah menemukan satu cara untuk mengatur kode respons yang harus bekerja dalam implementasi JAX-RS: menyuntikkan konteks HttpServletResponse dan secara manual mengatur kode respons. Misalnya, berikut adalah cara mengatur kode respons
CREATED
bila perlu.Perbaikan: Setelah menemukan jawaban terkait lainnya , saya belajar bahwa seseorang dapat menyuntikkan
HttpServletResponse
sebagai variabel anggota, bahkan untuk kelas layanan singleton (setidaknya di RESTEasy) !! Ini adalah pendekatan yang jauh lebih baik daripada mencemari API dengan detail implementasi. Akan terlihat seperti ini:sumber
@Produces
, dan jangan menentukan jenis media di finalResponse.ok
, dan Anda akan mendapatkan objek kembali dengan benar JAXB-serial ke dalam jenis media yang sesuai untuk mencocokkan permintaan. (Saya baru saja mencoba ini dengan metode tunggal yang dapat mengembalikan XML atau JSON: metode itu sendiri tidak perlu menyebutkan, kecuali dalam@Produces
anotasi.)MessageBodyWriter
danProvider
memungkinkan untuk negosiasi konten implisit, meskipun tampaknya contoh Anda kehilangan beberapa kode. Inilah jawaban lain yang saya berikan yang menggambarkan hal ini: stackoverflow.com/questions/5161466/…response.setStatus()
. Satu-satunya cara untuk mengirim misalnya 404 Tidak Ditemukan tanggapan adalah dengan mengatur kode status tanggapanresponse.setStatus(404)
dan kemudian menutup aliran outputresponse.getOutputStream().close()
sehingga JAX-RS tidak dapat mengatur ulang status saya.response.flushBuffer()
untuk menghindari kerangka kerja yang menimpa kode respons saya. Tidak terlalu bersih.404 Not Found
, mungkin lebih mudah digunakanthrow new NotFoundException()
.Jika Anda ingin menjaga lapisan sumber daya Anda bersih dari
Response
objek, maka saya sarankan Anda menggunakan@NameBinding
dan mengikat implementasiContainerResponseFilter
.Inilah daging anotasi:
Inilah daging saringannya:
Dan kemudian implementasi sumber daya Anda menjadi:
sumber
StatusFilter
dengan@Status
: Anda baik perlu menyediakan default untuk penjelasan inivalue
lapangan, atau menyatakan satu ketika annotating kelas (ex:@Status(200)
). Ini jelas tidak ideal.Jika Anda ingin mengubah kode status karena pengecualian, dengan JAX-RS 2.0 Anda dapat mengimplementasikan ExceptionMapper seperti ini. Ini menangani pengecualian semacam ini untuk seluruh aplikasi.
sumber
Jika WS-RS Anda perlu meningkatkan kesalahan mengapa tidak hanya menggunakan WebApplicationException?
sumber
JAX-RS memiliki dukungan untuk kode HTTP standar / khusus. Lihat ResponseBuilder dan ResponseStatus, misalnya:
http://jackson.codehaus.org/javadoc/jax-rs/1.0/javax/ws/rs/core/Response.ResponseBuilder.html#status%28javax.ws.rs.core.Response.Status%29
Perlu diingat bahwa informasi JSON lebih tentang data yang terkait dengan sumber daya / aplikasi. Kode HTTP lebih lanjut tentang status operasi CRUD yang diminta. (setidaknya begitulah seharusnya dalam sistem REST-ful)
sumber
Saya merasa sangat berguna untuk membangun juga pesan json dengan kode berulang, seperti ini:
sumber
Silakan lihat contoh di sini, yang terbaik menggambarkan masalah dan bagaimana menyelesaikannya di Jersey versi terbaru (2.3.1).
https://jersey.java.net/documentation/latest/representations.html#d0e3586
Ini pada dasarnya melibatkan mendefinisikan Pengecualian khusus dan menjaga jenis pengembalian sebagai entitas. Ketika ada kesalahan, pengecualian dilemparkan, jika tidak, Anda mengembalikan POJO.
sumber
Response
. Cari sajaCustomNotFoundException
kelasnya dan mungkin salin ke posting Anda.Saya tidak menggunakan JAX-RS, tapi saya punya skenario serupa di mana saya menggunakan:
sumber
Juga, perhatikan bahwa Jersey default akan menimpa badan respons jika kode http 400 atau lebih.
Untuk mendapatkan entitas yang Anda tentukan sebagai badan respons, cobalah untuk menambahkan init-param berikut ke Jersey Anda di file konfigurasi web.xml Anda:
sumber
Kode berikut ini berfungsi untuk saya. Menyuntikkan messageContext melalui setter beranotasi dan mengatur kode status dalam metode "add" saya.
sumber
Memperluas pada jawaban dari Nthalk dengan Microprofile OpenAPI Anda dapat menyelaraskan kode kembali dengan dokumentasi Anda menggunakan @APIResponse penjelasan.
Ini memungkinkan menandai metode JAX-RS seperti
Anda dapat menguraikan anotasi standar ini dengan ContainerResponseFilter
Peringatan terjadi ketika Anda menaruh beberapa anotasi pada metode Anda
sumber
Saya menggunakan jersey 2.0 dengan pembaca dan penulis isi pesan. Saya memiliki tipe metode pengembalian sebagai entitas spesifik yang juga digunakan dalam implementasi penulis badan pesan dan saya mengembalikan pojo yang sama, SkuListDTO. @Dapatkan @Konsumen ({"application / xml", "application / json"}) @Produces ({"application / xml", "application / json"}) @Path ("/ skuResync")
yang saya ubah adalah ini, saya meninggalkan implementasi penulis sendiri dan itu masih berfungsi.
sumber