JSON ve HTTP durum kodu birlikte nasıl döndürülür?


248

Bir REST web uygulaması (NetBeans 6.9, JAX-RS, TopLink Essentials) yazıyorum ve JSON ve HTTP durum kodu döndürmeye çalışıyorum . Kod hazır ve HTTP GET yöntemi istemciden çağrıldığında JSON döndüren çalışma var. esasen:

@Path("get/id")
@GET
@Produces("application/json")
public M_機械 getMachineToUpdate(@PathParam("id") String id) {

    // some code to return JSON ...

    return myJson;
}

Ama aynı zamanda JSON verileriyle birlikte bir HTTP durum kodu (500, 200, 204, vs.) dönmek istiyorum.

Kullanmaya çalıştım HttpServletResponse:

response.sendError("error message", 500);

Ancak bu, tarayıcının "gerçek" bir 500 olduğunu düşünmesini sağladı, böylece çıktı web sayfası normal bir HTTP 500 hata sayfasıydı.

İstemci tarafındaki JavaScript'in buna bağlı olarak bazı mantığı işleyebilmesi için bir HTTP durum kodu döndürmek istiyorum (örneğin hata kodunu ve mesajı bir HTML sayfasında görüntülemek için). Bu mümkün mü veya HTTP durum kodları böyle bir şey için kullanılmamalıdır mı?


2
İstediğiniz 500 (gerçek dışı? :)) ve gerçek 500 arasındaki fark nedir?
jilet

@razor İşte gerçek 500, JSON yanıtı yerine bir HTML hata sayfası anlamına gelir
Nupur

web tarayıcısı JSON ile değil, HTML sayfalarıyla çalışacak şekilde tasarlanmıştır, bu nedenle 500 (ve hatta bazı mesaj gövdesi) ile yanıt verirseniz, tarayıcı size sadece bir hata mesajı gösterebilir (gerçekten tarayıcı uygulamasına bağlıdır). normal bir kullanıcı.
jilet

Yanıtlar:


347

İşte bir örnek:

@GET
@Path("retrieve/{uuid}")
public Response retrieveSomething(@PathParam("uuid") String uuid) {
    if(uuid == null || uuid.trim().length() == 0) {
        return Response.serverError().entity("UUID cannot be blank").build();
    }
    Entity entity = service.getById(uuid);
    if(entity == null) {
        return Response.status(Response.Status.NOT_FOUND).entity("Entity not found for UUID: " + uuid).build();
    }
    String json = //convert entity to json
    return Response.ok(json, MediaType.APPLICATION_JSON).build();
}

Response sınıfına bir göz atın .

Her zaman bir içerik türü belirtmeniz gerektiğini unutmayın, özellikle birden fazla içerik türü geçiriyorsanız, ancak her mesaj JSON olarak temsil edilecekse, yalnızca @Produces("application/json")


12
Çalışıyor, ancak Yanıt dönüş değeri hakkında sevmediğim şey, bence kodunuzu kirletiyor, özellikle onu kullanmaya çalışan herhangi bir müşteriyle ilgili. Üçüncü bir tarafa Yanıt döndüren bir arabirim sağlarsanız, gerçekten ne tür bir geri dönüş yaptığınızı bilmez. Spring, bir açıklama ile daha açık hale getirir, her zaman bir durum kodu döndürürseniz çok kullanışlıdır (yani HTTP 204)
Guido

19
Bu sınıfı jenerik yapmak (Response <T>), her iki alternatifin de avantajlarına sahip olmak için jax-rs için ilginç bir gelişme olacaktır.
Guido

41
Varlığı bir şekilde json'a dönüştürmeye gerek yoktur. Sen yapabilirsin return Response.status(Response.Status.Forbidden).entity(myPOJO).build();sen olur sanki Works return myPOJO;, ancak HTTP-Durum ek kod ayarı ile.
kratenko

1
İş mantığını ayrı bir hizmet sınıfına ayırmanın iyi işlediğini düşünüyorum. Uç nokta, Yanıt'ı dönüş türü olarak kullanır ve yöntemleri çoğunlukla yalnızca hizmet yöntemlerinin yanı sıra yol ve parametre ek açıklamalarına yapılan çağrılardır. Mantığı, url / içerik türü eşlemesinden (kauçuğun yola çıkması için yola çarptığı yerde) temiz bir şekilde ayırır.
Stijn de Witt

aslında, nesneyi Yanıt'a kaydırmayan nesneyi döndürebilirsiniz.
ses

192

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 .

ExceptionMapperJersey 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 ExceptionMappersınıflarınızı tanımlayabilir ve bu haritacıları @Providerek 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 ( POSTistek) oluşturduğunuzda ve bu yeni varlık veya belki de varlığın kendisi hakkında bir 201 Createddurum 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 Responsedönüş kodunu ayarlamak için Oluşturucu kullanmak istiyorsanız Response, benim yöntem bir nesne döndürmek zorunda . UserSerileş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 :)


Yanıt yerine veri nesnesinin kendisini döndürmek için temiz bir yol olup olmadığını merak ediyorum. flushGerçekten kirli.
AlikElzin-kilaka

1
Sadece bir evcil hayvanım: 401 , kullanıcının yetkilendirilmediği anlamına gelmez . Sunucu kim olduğunuzu bilmediği için istemcinin yetkilendirilmediği anlamına gelir . Günlüğe kaydedilen / başka bir şekilde tanınan bir kullanıcının belirli bir eylem gerçekleştirmesine izin verilmezse, doğru yanıt kodu 403 Yasaktır.
Demonblack

69

Tarihçiliğin cevabı işe yarayacaktır, ancak Jackson + JAXB gibi bir sağlayıcının döndürülen nesnenizi otomatik olarak JSON gibi bir çıktı biçimine dönüştürmesine izin vermek için tüm yaklaşımı değiştirir. (CXF'ye özgü bir sınıf kullanan) bir Apache CXF gönderisinden esinlenerek , herhangi bir JAX-RS uygulamasında çalışması gereken yanıt kodunu ayarlamanın bir yolunu buldum: Bir HttpServletResponse bağlamı enjekte edin ve yanıt kodunu manuel olarak ayarlayın. Örneğin, CREATEDuygun olduğunda yanıt kodunun nasıl ayarlanacağı aşağıda açıklanmıştır .

@Path("/foos/{fooId}")
@PUT
@Consumes("application/json")
@Produces("application/json")
public Foo setFoo(@PathParam("fooID") final String fooID, final Foo foo, @Context final HttpServletResponse response)
{
  //TODO store foo in persistent storage
  if(itemDidNotExistBefore) //return 201 only if new object; TODO app-specific logic
  {
    response.setStatus(Response.Status.CREATED.getStatusCode());
  }
  return foo;  //TODO get latest foo from storage if needed
}

İyileştirme: Başka bir ilgili cevap bulduktan sonra , tek HttpServletResponsedeğişkenli servis sınıfı için bile (en azından RESTEasy'de) üye değişken olarak enjekte edilebileceğini öğrendim !! Bu, API'yi uygulama ayrıntılarıyla kirletmekten çok daha iyi bir yaklaşımdır. Şöyle görünecektir:

@Context  //injected response proxy supporting multiple threads
private HttpServletResponse response;

@Path("/foos/{fooId}")
@PUT
@Consumes("application/json")
@Produces("application/json")
public Foo setFoo(@PathParam("fooID") final String fooID, final Foo foo)
{
  //TODO store foo in persistent storage
  if(itemDidNotExistBefore) //return 201 only if new object; TODO app-specific logic
  {
    response.setStatus(Response.Status.CREATED.getStatusCode());
  }
  return foo;  //TODO get latest foo from storage if needed
}

Aslında yaklaşımları birleştirebilirsiniz: yönteme açıklama ekleyin ve @Producesson olarak ortam türünü belirtmeyin ve Response.okdönüş nesnenizi isteğe uygun olarak uygun ortam türüne doğru şekilde JAXB serileştirin. (Ben sadece XML veya JSON dönebilir tek bir yöntemle denedim: yöntemin kendisi @Producesek açıklama hariç, bahsetmek gerekmez .)
Royston Shufflebotham

Haklısın Garret. Örneğim, daha çok bir içerik türü sağlamanın öneminin bir örneğiydi. Bizim yaklaşımlar benzer, ancak bir kullanma fikri MessageBodyWriterve Providersizin örnekte bazı kodu eksik görünse de, örtük içerik müzakere için izin verir. İşte bunu gösteren başka bir cevap: stackoverflow.com/questions/5161466/…
hisdrewness

8
İçindeki durum kodunu geçersiz kılamıyorum response.setStatus() . Örneğin, 404 Bulunamadı yanıtı göndermenin tek yolu yanıt durum kodunu response.setStatus(404)en ayarlamak ve sonra çıkış akışını kapatmaktır, response.getOutputStream().close()böylece JAX-RS durumumu sıfırlayamaz.
Rob Juurlink

2
201 kodunu ayarlamak için bu yaklaşımı kullanabildim, ancak response.flushBuffer()yanıt kodumu geçersiz kılmaktan kaçınmak için bir try-catch bloğu eklemek zorunda kaldım . Çok temiz değil.
Pierre Henry

1
@RJJuurlink, özellikle bir geri dönmek istiyorsanız 404 Not Found, sadece kullanımı daha kolay olabilir throw new NotFoundException().
Garret Wilson

34

Kaynak katmanınızı Responsenesnelerden temiz tutmak istiyorsanız @NameBinding,ContainerResponseFilter .

Ek açıklama eti:

package my.webservice.annotations.status;

import javax.ws.rs.NameBinding;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

@NameBinding
@Retention(RetentionPolicy.RUNTIME)
public @interface Status {
  int CREATED = 201;
  int value();
}

İşte filtrenin eti:

package my.webservice.interceptors.status;

import javax.ws.rs.container.ContainerRequestContext;
import javax.ws.rs.container.ContainerResponseContext;
import javax.ws.rs.container.ContainerResponseFilter;
import javax.ws.rs.ext.Provider;
import java.io.IOException;

@Provider
public class StatusFilter implements ContainerResponseFilter {

  @Override
  public void filter(ContainerRequestContext containerRequestContext, ContainerResponseContext containerResponseContext) throws IOException {
    if (containerResponseContext.getStatus() == 200) {
      for (Annotation annotation : containerResponseContext.getEntityAnnotations()) {
        if(annotation instanceof Status){
          containerResponseContext.setStatus(((Status) annotation).value());
          break;
        }
      }
    }
  }
}

Ve sonra kaynağınızdaki uygulama basitçe şöyle olur:

package my.webservice.resources;

import my.webservice.annotations.status.StatusCreated;
import javax.ws.rs.*;

@Path("/my-resource-path")
public class MyResource{
  @POST
  @Status(Status.CREATED)
  public boolean create(){
    return true;
  }
}

API'yı temiz ve güzel bir yanıt tutar. Ek açıklamanızı @Status (kod = 205) gibi parametrelendirmek ve önleyicinin kodu belirttiğinizle değiştirmesini sağlamak mümkün mü? Sanırım bu, temelde kodları geçersiz kılmak için bir açıklama ekleyecektir.
user2800708

@ user2800708, bunu yerel kodum için zaten yaptım, önerdiğin gibi cevabı güncelledim.
Nthalk

Güzel, teşekkürler. Bu ve birkaç diğer hile ile temelde artık kodumdaki REST API'lerini temizleyebiliyorum, böylece REST'ten bahsetmeden basit bir Java arayüzüne uyuyor; bu sadece başka bir RMI mekanizması.
user2800708

6
StatusFilter'da ek açıklamalar için döngü yapmak yerine, @ Sağlayıcıya ek olarak @ Durum ile filtreye açıklama ekleyebilirsiniz. Ardından filtre yalnızca @ Status ile açıklamalı kaynaklarda çağrılır. @ NameBinding
trevorism'in

1
İyi açıklama @trevorism. Ek açıklama eklemenin çok hoş olmayan bir yan etkisi StatusFiltervardır @Status: ek açıklama valuealanı için bir varsayılan değer sağlamanız veya sınıfa ek açıklama eklerken bir açıklama yapmanız gerekir (ör @Status(200).). Bu kesinlikle ideal değil.
Phil

6

Bir istisna nedeniyle durum kodunu değiştirmek isterseniz, JAX-RS 2.0 ile böyle bir ExceptionMapper uygulayabilirsiniz. Bu, tüm uygulama için bu tür bir istisna işler.

@Provider
public class UnauthorizedExceptionMapper implements ExceptionMapper<EJBAccessException> {

    @Override
    public Response toResponse(EJBAccessException exception) {
        return Response.status(Response.Status.UNAUTHORIZED.getStatusCode()).build();
    }

}

6

WS-RS'nizin bir hataya ihtiyacı varsa neden sadece WebApplicationException kullanılmıyor?

@GET
@Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
@Path("{id}")
public MyEntity getFoo(@PathParam("id") long id,  @QueryParam("lang")long idLanguage) {

if (idLanguage== 0){
    // No URL parameter idLanguage was sent
    ResponseBuilder builder = Response.status(Response.Status.BAD_REQUEST);
    builder.entity("Missing idLanguage parameter on request");
    Response response = builder.build();
    throw new WebApplicationException(response);
    }
... //other stuff to return my entity
return myEntity;
}

4
Bence WebApplicationExceptions büyük yığın izleri attığı için istemci tarafı hataları için uygun değil. İstemci hataları, sunucu tarafı yığın izleri atmamalı ve günlüğe kaydetmeyi kirletmemelidir.
Rob Juurlink

5

JAX-RS'nin standart / özel HTTP kodları desteği vardır. ResponseBuilder ve ResponseStatus'a bakın, örneğin:

http://jackson.codehaus.org/javadoc/jax-rs/1.0/javax/ws/rs/core/Response.ResponseBuilder.html#status%28javax.ws.rs.core.Response.Status%29

JSON bilgilerinin kaynak / uygulama ile ilişkili verilerle ilgili olduğunu unutmayın. HTTP kodları, istenen CRUD işleminin durumu hakkında daha fazladır. (en azından REST-ful sistemlerinde olması gerektiği gibi)


bağlantı koptu
Umpa

5

Ben de böyle tekrarlanan kod ile bir json mesajı oluşturmak için çok yararlı buldum:

@POST
@Consumes("application/json")
@Produces("application/json")
public Response authUser(JsonObject authData) {
    String email = authData.getString("email");
    String password = authData.getString("password");
    JSONObject json = new JSONObject();
    if (email.equalsIgnoreCase(user.getEmail()) && password.equalsIgnoreCase(user.getPassword())) {
        json.put("status", "success");
        json.put("code", Response.Status.OK.getStatusCode());
        json.put("message", "User " + authData.getString("email") + " authenticated.");
        return Response.ok(json.toString()).build();
    } else {
        json.put("status", "error");
        json.put("code", Response.Status.NOT_FOUND.getStatusCode());
        json.put("message", "User " + authData.getString("email") + " not found.");
        return Response.status(Response.Status.NOT_FOUND).entity(json.toString()).build();
    }
}

4

Lütfen buradaki örneğe bakın, sorunu ve Jersey'nin en son (2.3.1) sürümünde nasıl çözüldüğünü en iyi şekilde gösterir.

https://jersey.java.net/documentation/latest/representations.html#d0e3586

Temel olarak özel bir İstisna tanımlamayı ve dönüş türünü varlık olarak tutmayı içerir. Bir hata olduğunda, istisna atılır, aksi takdirde POJO döndürürsünüz.


İlgilenme örneğinin kendi istisna sınıflarını tanımladıkları ve içine bir inşa ettikleri örnek olduğunu eklemek isterim Response. Sadece CustomNotFoundExceptionsınıfı arayın ve belki de gönderinize kopyalayın.
JBert

Bu yaklaşımı hatalar için kullanıyorum ve beğendim. Ancak '201 oluşturuldu' gibi başarı kodları (200'den farklı) için geçerli değildir.
Pierre Henry

3

JAX-RS kullanmıyorum, ancak kullandığım benzer bir senaryo var:

response.setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value());

Bahar MVC kullanarak benim için yapar ama bulmak için kolay bir yol var!
Caps

1

Ayrıca, http kodu 400 veya daha fazla olması durumunda Jersey'nin varsayılan olarak yanıt gövdesini geçersiz kılacağına dikkat edin.

Belirtilen varlığı yanıt gövdesi olarak almak için web.xml yapılandırma dosyasında Jersey'nize aşağıdaki init-param'ı eklemeyi deneyin:

    <init-param>
        <!-- used to overwrite default 4xx state pages -->
        <param-name>jersey.config.server.response.setStatusOverSendError</param-name>
        <param-value>true</param-value>
    </init-param>

0

Aşağıdaki kod benim için çalıştı. MessageContext'i ek açıklamalı ayarlayıcı aracılığıyla enjekte etmek ve "add" yöntemimde durum kodunu ayarlamak.

import java.util.Collection;
import java.util.HashMap;
import java.util.Map;

import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.Response;

import org.apache.cxf.jaxrs.ext.MessageContext;

public class FlightReservationService {

    MessageContext messageContext;

    private final Map<Long, FlightReservation> flightReservations = new HashMap<>();

    @Context
    public void setMessageContext(MessageContext messageContext) {
        this.messageContext = messageContext;
    }

    @Override
    public Collection<FlightReservation> list() {
        return flightReservations.values();
    }

    @Path("/{id}")
    @Produces("application/json")
    @GET
    public FlightReservation get(Long id) {
        return flightReservations.get(id);
    }

    @Path("/")
    @Consumes("application/json")
    @Produces("application/json")
    @POST
    public void add(FlightReservation booking) {
        messageContext.getHttpServletResponse().setStatus(Response.Status.CREATED.getStatusCode());
        flightReservations.put(booking.getId(), booking);
    }

    @Path("/")
    @Consumes("application/json")
    @PUT
    public void update(FlightReservation booking) {
        flightReservations.remove(booking.getId());
        flightReservations.put(booking.getId(), booking);
    }

    @Path("/{id}")
    @DELETE
    public void remove(Long id) {
        flightReservations.remove(id);
    }
}

0

Üzerine Genişleyen cevap ait Nthalk ile Microprofile OpenAPI Eğer kullanarak belgelerle dönüş kodu hizalayabilirsiniz @APIResponse ek açıklama.

Bu, JAX-RS yönteminin

@GET
@APIResponse(responseCode = "204")
public Resource getResource(ResourceRequest request) 

Bu standartlaştırılmış ek açıklamayı bir ContainerResponseFilter ile ayrıştırabilirsiniz

@Provider
public class StatusFilter implements ContainerResponseFilter {

    @Override
    public void filter(ContainerRequestContext requestContext, ContainerResponseContext responseContext) {
        if (responseContext.getStatus() == 200) {
            for (final var annotation : responseContext.getEntityAnnotations()) {
                if (annotation instanceof APIResponse response) {
                    final var rawCode = response.responseCode();
                    final var statusCode = Integer.parseInt(rawCode);

                    responseContext.setStatus(statusCode);
                }
            }
        }
    }

}

Yönteminize birden fazla ek açıklama koyduğunuzda,

@APIResponse(responseCode = "201", description = "first use case")
@APIResponse(responseCode = "204", description = "because you can")
public Resource getResource(ResourceRequest request) 

-1

Jersey 2.0'ı mesaj gövdesi okuyucuları ve yazarlarıyla kullanıyorum. Ben de mesaj gövdesi yazarının uygulanmasında kullanılan belirli bir varlık olarak benim yöntem dönüş tipi vardı ve ben aynı pojo, bir SkuListDTO dönüyordu. @GET @Consumes ({"application / xml", "application / json"}) @Produces ({"application / xml", "application / json"}) @Path ("/ skuResync")

public SkuResultListDTO getSkuData()
    ....
return SkuResultListDTO;

tüm değiştirdiğim buydu, yazar uygulamasını yalnız bıraktım ve hala çalıştı.

public Response getSkuData()
...
return Response.status(Response.Status.FORBIDDEN).entity(dfCoreResultListDTO).build();
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.