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:
- suatu entitas diminta tetapi tidak ada (404)
- permintaan itu secara semantik salah (400)
- pengguna tidak diotorisasi (401)
- ada masalah dengan koneksi database (500)
- dll ..
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 ada javax.ws.rs.WebApplicationException
. Ini adalah tipe pengecualian yang ditentukan sebelumnya yang dipetakan ke kode kesalahan yang berbeda, misalnya:
- BadRequestException (400)
- InternalServerErrorException (500)
- NotFoundException (404)
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 ):
public class MyApplicationException extends Exception implements Serializable
{
private static final long serialVersionUID = 1L;
public MyApplicationException() {
super();
}
public MyApplicationException(String msg) {
super(msg);
}
public MyApplicationException(String msg, Exception e) {
super(msg, e);
}
}
Pemberi :
@Provider
public class MyApplicationExceptionHandler implements ExceptionMapper<MyApplicationException>
{
@Override
public Response toResponse(MyApplicationException exception)
{
return Response.status(Status.BAD_REQUEST).entity(exception.getMessage()).build();
}
}
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:
@GET
@Path("myresource({id}")
public Response retrieveSomething(@PathParam("id") String id) {
...
Entity entity = service.getById(uuid);
if(entity == null) {
return Response.status(Response.Status.NOT_FOUND).entity("Resource not found for ID: " + uuid).build();
}
...
}
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 dengan 201 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:
@Path("/")
@POST
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public User addUser(User user){
User newuser = ... do something like DB insert ...
return newuser;
}
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 mengembalikan Response
objek dalam metode saya. Bagaimana saya masih mengembalikan User
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:
@Path("/")
@POST
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public User addUser(User user, @Context final HttpServletResponse response){
User newUser = ...
//set HTTP code to "201 Created"
response.setStatus(HttpServletResponse.SC_CREATED);
try {
response.flushBuffer();
}catch(Exception e){}
return newUser;
}
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.
@Path("/")
@POST
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public Response addUser(User user){
User newUser = ...
return Response.created(hateoas.buildLinkUri(newUser, "entity")).entity(restResponse).build();
}
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 :)