Возвращение нескольких ответов в Java [duplicate]

Обновление для Android Studio версии 1.5 или выше Как @LouMorda упомянула в комментарии ниже, что вкладка Emulator , упомянутая в оригинальной записи, была удалена в Android Studio v 1.5.

Теперь они установили эти параметры в настройках симулятора в AVD Manager . Чтобы получить доступ к этим настройкам:

  1. Выберите Инструменты - & gt; Android - & gt; AVD Manager
  2. Нажмите кнопку Edit AVD (значок карандаша)
  3. Доступ к настройкам сети возможен после нажав кнопку Показать дополнительные настройки

Вот скриншот о том, как это может выглядеть:

Оригинал сообщения Для тех, кто использует Android Studio IDE:

  1. Перейдите к Run - & gt; Изменить настройки
  2. Выбрать Android Application - & gt; [Ваше приложение]
  3. Выберите вкладку эмулятора
  4. Здесь вы можете изменить разные значения для Network Speed ​​ и Network Latency для имитации различных скоростей и латентностей и т. д.

В качестве альтернативы вы можете ввести различные аргументы в текстовое поле Additional command line options , как указано в @ ответ индазарука.

Снимок экрана ниже описывает, как выглядит этот экран Run Configuration :

Run Configurations Screen in Android Studio beta 0.8.6 [!d15]

Я знаю его немного поздно, чтобы ответить на этот вопрос, но я надеюсь, что это поможет другим, сталкивающимся с подобными проблемами!

Изменить Для тех, кто использует eclipse, см. ответ @ Abhi ниже.

207
задан Jens Piegsa 23 April 2015 в 11:55
поделиться

12 ответов

Вот пример:

@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 .

Обратите внимание, что вы всегда должны указывать тип контента, особенно если вы передаете несколько типов содержимого, но если каждое сообщение будет представлено как JSON, вы можете просто аннотировать метод с помощью @Produces("application/json")

301
ответ дан Afshin Moazami 16 August 2018 в 04:37
поделиться
  • 1
    Он работает, но то, что мне не нравится в возвращаемом значении Response, заключается в том, что, на мой взгляд, оно загрязняет ваш код, особенно в отношении любого клиента, пытающегося его использовать. Если вы предоставляете интерфейс, возвращающий ответ третьей стороне, он не знает, какой тип вы действительно возвращаете. Spring делает это более понятным с помощью аннотации, очень полезно, если вы всегда возвращаете код состояния (т. Е. HTTP 204) – Guido García 14 November 2012 в 18:48
  • 2
    Создание этого класса generic (Response & lt; T & gt;) было бы интересным улучшением для jax-rs, чтобы иметь преимущества обеих альтернатив. – Guido García 14 November 2012 в 19:07
  • 3
    Нет необходимости каким-либо образом преобразовывать объект в json. Вы можете делать return Response.status(Response.Status.Forbidden).entity(myPOJO).build(); Работает так, как если бы вы return myPOJO;, но с дополнительной настройкой кода HTTP-состояния. – kratenko 25 February 2015 в 16:54
  • 4
    Я думаю, что разделение бизнес-логики на отдельный класс обслуживания хорошо работает. Конечная точка использует Response как тип возврата, и ее методы в основном являются просто вызовами сервисных методов, а также аннотациями path и param. Он чисто отделяет логику от сопоставления типа url / content (где резина так говорит по дороге). – Stijn de Witt 3 April 2017 в 12:08
157
ответ дан Amr ElAdawy 16 August 2018 в 04:37
поделиться

Пожалуйста, посмотрите здесь пример, это лучше всего иллюстрирует проблему и как она решена в последней версии (2.3.1) Джерси.

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

В основном это связано с определением пользовательского исключения и сохранением возвращаемый тип как объект. При возникновении ошибки генерируется исключение, в противном случае вы возвращаете POJO.

4
ответ дан annouk 16 August 2018 в 04:37
поделиться
  • 1
    Я хотел бы добавить, что интерес интересен тем, где они определяют свой собственный класс исключений и создают в нем Response. Просто найдите класс CustomNotFoundException и, возможно, скопируйте его на свой пост. – JBert 3 March 2014 в 18:32
  • 2
    Я использую этот подход для ошибок, и мне это нравится. Но он не применим к кодам успеха (отличным от 200), например «201 создан». – Pierre Henry 3 April 2014 в 16:19

Если ваш WS-RS нуждается в повышении ошибки, почему бы просто не использовать исключение WebApplicationException?

@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;
}
5
ответ дан Ariel 16 August 2018 в 04:37
поделиться
  • 1
    На мой взгляд, WebApplicationExceptions не подходят для ошибок на стороне клиента, потому что они бросают большие трассировки стека. Ошибки клиента не должны вызывать следы стека на стороне сервера и загрязнять журнал с ним. – Rob Juurlink 18 October 2013 в 09:29

Мне было очень полезно создать также json-сообщение с повторным кодом, например:

@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
ответ дан Array 16 August 2018 в 04:37
поделиться

Я использую jersey 2.0 с читателями и авторами сообщений. У меня был тип возвращаемого метода как конкретный объект, который также использовался в реализации автора сообщения сообщения, и я возвращал то же самое pojo, SkuListDTO. @GET @Consumes ({"application / xml", "application / json"}) @Produces ({"application / xml", "application / json"}) @Path ("/ skuResync")

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

все, что я изменил, это то, что я оставил выполнение записи самостоятельно, и он все еще работал.

public Response getSkuData()
...
return Response.status(Response.Status.FORBIDDEN).entity(dfCoreResultListDTO).build();
-1
ответ дан b. phillips 16 August 2018 в 04:37
поделиться

Я не использую JAX-RS, но у меня есть аналогичный сценарий, в котором я использую:

response.setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value());
4
ответ дан Caps 16 August 2018 в 04:37
поделиться
  • 1
    Спасибо, я не уверен, что если статус настройки заставит браузер бросить страницу ошибки tho .. – masato-san 14 January 2011 в 08:29
  • 2
    Это делает для меня использование Spring MVC, но есть простой способ узнать об этом! – Caps 17 January 2011 в 02:42

Если вы хотите изменить код состояния из-за исключения, с JAX-RS 2.0 вы можете реализовать ExceptionMapper, как это. Это обрабатывает такое исключение для всего приложения.

@Provider
public class UnauthorizedExceptionMapper implements ExceptionMapper<EJBAccessException> {

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

}
6
ответ дан ercalamar 16 August 2018 в 04:37
поделиться

Ответ от hedrewness будет работать, но он изменяет весь подход к тому, чтобы провайдер, такой как Jackson + JAXB, автоматически конвертировал возвращаемый объект в какой-то выходной формат, такой как JSON. Вдохновленный Apache CXF post (который использует класс, специфичный для CXF), я нашел один способ установить код ответа, который должен работать в любой реализации JAX-RS: ввести контекст HttpServletResponse и вручную установить код ответа. Например, вот как установить код ответа на CREATED, когда это необходимо.

@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
}

Улучшение: После поиска другого связанного ответа Я узнал, что в качестве переменной-члена можно ввести HttpServletResponse, даже для класса обслуживания Singleton (по крайней мере, в RESTEasy)! Это гораздо лучший подход, чем загрязнение API с помощью деталей реализации. Это будет выглядеть так:

@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
}
66
ответ дан Jasper 16 August 2018 в 04:37
поделиться
  • 1
    Фактически вы можете комбинировать подходы: аннотировать метод с помощью @Produces и не указывать тип носителя в конечной Response.ok, и вы правильно получите возвращаемый объект JAXB-сериализован в соответствующий тип носителя, чтобы он соответствовал запрос. (Я просто попробовал это с помощью одного метода, который мог бы вернуть либо XML, либо JSON: сам метод не нужно упоминать, кроме как в аннотации @Produces.) – Royston Shufflebotham 26 September 2012 в 22:31
  • 2
    Ты прав Гаррет. Мой пример был скорее иллюстрацией важности предоставления типа контента. Наши подходы схожи, но идея использования MessageBodyWriter и Provider допускает неявное согласование содержимого, хотя, похоже, ваш пример не содержит кода. Ниже приведен еще один ответ, который иллюстрирует это: stackoverflow.com/questions/5161466/… – hisdrewness 4 December 2012 в 22:38
  • 3
    Я не могу переопределить код состояния в response.setStatus(). Единственный способ отправить, например, ответ 404 Not Found , - это установить код состояния ответа response.setStatus(404) en, а затем закрыть выходной поток response.getOutputStream().close(), чтобы JAX-RS не смог сбросить мой статус. – Rob Juurlink 18 October 2013 в 09:45
  • 4
    Я смог использовать этот подход для установки кода 201, но ему пришлось добавить блок try-catch с response.flushBuffer(), чтобы избежать переопределения кода ответа. Не очень чистый. – Pierre Henry 3 April 2014 в 16:40
  • 5
    @RobJuurlink, если вы хотите специально вернуть 404 Not Found, может быть проще просто использовать throw new NotFoundException(). – Garret Wilson 22 August 2014 в 01:25

JAX-RS поддерживает стандартные / пользовательские HTTP-коды. См. ResponseBuilder и ResponseStatus, например:

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 больше связана с данными, связанными с ресурсом / приложением. Коды HTTP больше относятся к статусу запрашиваемой операции CRUD. (по крайней мере, так оно и должно быть в системах REST-ful)

5
ответ дан kvista 16 August 2018 в 04:37
поделиться

Также обратите внимание, что по умолчанию Джерси переопределит тело ответа в случае http-кода 400 или более.

Чтобы получить указанный объект в качестве тела ответа, попробуйте добавить следующий init -param к вашему Джерси в вашем файле конфигурации web.xml:

    <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>
1
ответ дан Maxime T 16 August 2018 в 04:37
поделиться

Если вы хотите, чтобы ваш уровень ресурсов был очищен от объектов Response, я рекомендую вам использовать @NameBinding и привязку к реализациям ContainerResponseFilter.

Вот мясо аннотации:

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();
}

Вот мясо фильтра:

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;
        }
      }
    }
  }
}

И тогда реализация на вашем ресурсе просто станет:

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;
  }
}
28
ответ дан Nthalk 16 August 2018 в 04:37
поделиться
  • 1
    Сохраняет API чистый, приятный ответ. Можно ли параметризовать свою аннотацию, например @Status (код = 205), и перехватчик заменить код на все, что вы укажете? Я думаю, что это в основном даст вам аннотацию для переопределения кодов всякий раз, когда вам нужно. – user2800708 1 April 2015 в 08:00
  • 2
    @ user2800708, я уже сделал это для своего локального кода, обновил ответ, как вы предложили. – Nthalk 1 April 2015 в 15:57
  • 3
    Приятно, спасибо. Благодаря этому и нескольким трюкам я в основном теперь могу очистить API REST в своем коде, чтобы он соответствовал простому интерфейсу Java без упоминания REST; его просто еще один механизм RMI. – user2800708 1 April 2015 в 21:39
  • 4
    Вместо цикла для аннотаций в StatusFilter вы можете аннотировать фильтр с @ Status в дополнение к @ Provider. Затем фильтр будет вызываться только для ресурсов, которые аннотируются с помощью @ Status. Это цель @ NameBinding – trevorism 24 March 2016 в 12:54
Другие вопросы по тегам:

Похожие вопросы: