Bir REST web hizmetinde HTTP durum kodlarını ayarlamak için birkaç kullanım durumu vardır ve en azından biri mevcut yanıtlarda yeterince belgelenmemiştir (yani, JAXB kullanarak otomatik büyülü JSON / XML serileştirme kullandığınızda ve bir serileştirilecek nesne, aynı zamanda varsayılan 200'den farklı bir durum kodu).
Şimdi her biri için farklı kullanım örneklerini ve çözümlerini sıralayayım:
1. Hata kodu (500, 404, ...)
Farklı bir durum kodu döndürmek istediğinizde en yaygın kullanım durumu 200 OK
, bir hata oluştuğunda ortaya çıkar.
Örneğin:
- bir varlık isteniyor ancak mevcut değil (404)
- istek anlamsal olarak yanlış (400)
- kullanıcı yetkili değil (401)
- veritabanı bağlantısıyla ilgili bir sorun var (500)
- vb..
a) İstisna atın
Bu durumda, sorunu ele almanın en temiz yolunun bir istisna atmak olduğunu düşünüyorum. Bu istisna ExceptionMapper
, istisnayı uygun hata koduyla bir yanıta çevirecek bir , tarafından ele alınacaktır .
ExceptionMapper
Jersey ile önceden yapılandırılmış olarak gelen varsayılanı kullanabilirsiniz (ve sanırım diğer uygulamalarla aynıdır) ve mevcut alt sınıflarından herhangi birini atarsınız javax.ws.rs.WebApplicationException
. Bunlar, farklı hata kodlarıyla önceden eşlenen önceden tanımlanmış istisna türleridir, örneğin:
- BadRequestException (400)
- InternalServerErrorException (500)
- NotFoundException (404)
Vb Listeyi burada bulabilirsiniz: API
Alternatif olarak, kendi özel istisnalarınızı ve ExceptionMapper
sınıflarınızı tanımlayabilir ve bu haritacıları @Provider
ek açıklama ortalamasıyla ( bu örneğin kaynağı ) Jersey'ye ekleyebilirsiniz :
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);
}
}
Sağlayıcı :
@Provider
public class MyApplicationExceptionHandler implements ExceptionMapper<MyApplicationException>
{
@Override
public Response toResponse(MyApplicationException exception)
{
return Response.status(Status.BAD_REQUEST).entity(exception.getMessage()).build();
}
}
Not: Kullandığınız mevcut istisna türleri için ExceptionMappers da yazabilirsiniz.
b) Yanıt oluşturucuyu kullanma
Durum kodu ayarlamanın başka bir yolu Response
, istenen kodla bir yanıt oluşturmak için bir oluşturucu kullanmaktır .
Bu durumda, yönteminizin dönüş türü olmalıdır javax.ws.rs.core.Response
. Bu, tarihçiliğin kabul edilen yanıtı gibi diğer çeşitli yanıtlarda açıklanır ve şöyle görünür:
@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. Başarı, ama 200 değil
Dönüş durumunu ayarlamak istediğiniz başka bir durum, işlemin başarılı olduğu durumdur, ancak gövdeye döndürdüğünüz içerikle birlikte 200'den farklı bir başarı kodu döndürmek istersiniz.
Sık kullanılan bir durum, yeni bir varlık ( POST
istek) oluşturduğunuzda ve bu yeni varlık veya belki de varlığın kendisi hakkında bir 201 Created
durum kodu ile birlikte bilgi döndürmek istediğiniz zamandır.
Bir yaklaşım, yanıt nesnesini yukarıda açıklandığı gibi kullanmak ve isteğin gövdesini kendiniz ayarlamaktır. Ancak bunu yaparak, JAXB tarafından sağlanan XML veya JSON'a otomatik serileştirmeyi kullanma yeteneğini kaybedersiniz.
JAXB tarafından JSON'a serileştirilecek varlık nesnesini döndüren orijinal yöntem budur:
@Path("/")
@POST
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public User addUser(User user){
User newuser = ... do something like DB insert ...
return newuser;
}
Bu, yeni oluşturulan kullanıcının JSON temsilini döndürür, ancak dönüş durumu 201 değil 200 olur.
Şimdi sorun Response
dönüş kodunu ayarlamak için Oluşturucu kullanmak istiyorsanız Response
, benim yöntem bir nesne döndürmek zorunda . User
Serileştirilecek nesneyi hala nasıl geri gönderebilirim?
a) Kodu sunucu uygulaması yanıtına ayarlayın
Bunu çözmek için bir yaklaşım, bir sunucu uygulaması istek nesnesi elde etmek ve Garett Wilson'ın cevabında gösterildiği gibi yanıt kodunu kendimiz manuel olarak ayarlamaktır:
@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;
}
Yöntem yine de bir varlık nesnesi döndürür ve durum kodu 201 olacaktır.
Çalışmasını sağlamak için yanıtı temizlemem gerektiğine dikkat edin. Bu, güzel JAX_RS kaynağımızda düşük seviyeli Servlet API kodunun hoş olmayan bir şekilde yeniden canlandırılması ve çok daha kötüsü, daha sonra kabloya gönderildikleri için başlıkların değiştirilememesine neden oluyor.
b) Yanıt nesnesini varlık ile birlikte kullanma
Bu durumda en iyi çözüm, Response nesnesini kullanmak ve varlığı bu yanıt nesnesi üzerinde serileştirilecek şekilde ayarlamaktır. Bu durumda, loadload varlığının türünü belirtmek için Response nesnesini genel yapmak iyi olur, ancak şu anda durum böyle değildir.
@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();
}
Bu durumda, durum kodunu 201 olarak ayarlamak için Response builder sınıfının oluşturulan yöntemini kullanırız. Obje nesnesini (kullanıcı), entity () yöntemi aracılığıyla yanıta iletiriz.
Sonuç, HTTP kodunun istediğimiz gibi 401 olması ve yanıtın gövdesinin, User nesnesini yeni döndüğümüzde sahip olduğumuzla aynı JSON olmasıdır. Ayrıca bir konum başlığı ekler.
Response sınıfı, farklı durumlar (stati?) İçin aşağıdakiler gibi bir dizi oluşturucu yöntemine sahiptir:
Response.accepted () Response.ok () Response.noContent () Response.notAcceptable ()
Not: hateoas nesnesi, kaynak URI'leri oluşturmaya yardımcı olmak için geliştirdiğim yardımcı bir sınıftır. Burada kendi mekanizmanızı bulmanız gerekecek;)
Bu kadar.
Umarım bu uzun yanıt birine yardımcı olur :)