Подтвердить что ты не робот

CXF JAXRS - Как передать дату как QueryParam

У меня есть служба, определяемая следующим образом.

public String getData(@QueryParam("date") Date date)

Я пытаюсь передать java.util.Date его с моего клиента (который является jaxrs: клиентом CXF, а не общим HTTP-клиентом или браузером).

Мой сервис получает дату как Thu Mar 01 22:33:10 IST 2012 в URL-адресе HTTP. Поскольку CXF не сможет создать объект Date, используя эту String, мой клиент получит ошибку 404. Я попытался использовать ParameterHandler на стороне службы, но я все еще не могу проанализировать его успешно, потому что я не ожидаю даты в каком-либо конкретном формате.

По этот пост, передача Date должна работать из коробки, но я не могу получить основной случай работы. Должен ли я что-то делать, чтобы успешно передать объект Date от моего клиента к сервису? Цените любую помощь.

Спасибо

4b9b3361

Ответ 1

Проблема в том, что JAX-RS диктует, что разделение параметров выполняется одним из двух способов:

  • Параметр bean имеет открытый конструктор, который принимает строку
  • Параметр bean имеет статический метод valueOf(String).

В вашем случае дата разделяется с помощью конструктора Date(String), который не может обрабатывать формат ввода, который отправляет ваш клиент. У вас есть пара возможностей для исправления этого:


Вариант 1

Попросите вашего клиента изменить формат даты перед отправкой. Это идеальный, но, вероятно, самый трудный результат!


Вариант 2

Обрабатывать сумасшедший формат даты. Возможны следующие варианты:

Измените свою подпись метода, чтобы принять строку. Попытайтесь создать объект Date из этого, и если это не удается, используйте свой собственный класс SimpleDateFormat для его анализа.

static final DateFormat CRAZY_FORMAT = new SimpleDateFormat("");

public String getData(@QueryParam("date") String dateString) {
    final Date date;
    try {
        date = new Date(dateString); // yes, I know this is a deprecated method
    } catch(Exception e) {
        date = CRAZY_FORMAT.parse(dateString);
    }
}

Определите свой собственный класс параметров, который выполняет указанную выше логику. Дайте ему конструктор строк или статический метод valueOf(String), который вызывает логику. И дополнительный метод для получения даты, когда все сказано и сделано.

public class DateParameter implements Serializable {
    public static DateParameter valueOf(String dateString) {
        try {
            date = new Date(dateString); // yes, I know this is a deprecated method
        } catch(Exception e) {
            date = CRAZY_FORMAT.parse(dateString);
        }
    }

    private Date date;
    // Constructor, Getters, Setters
}

public String getData(@QueryParam("date") DateParameter dateParam) {
    final Date date = dateParam.getDate();
}

Или, наконец, вы можете зарегистрировать обработчик параметров для дат. Где его логика просто такая же, как указано для других опций выше. Обратите внимание, что вам нужно использовать, по крайней мере, CXF 2.5.3, чтобы обработать ваш обработчик параметров до того, как он попробует логику развязки по умолчанию.

public class DateHandler implements ParameterHandler<Date> {
    public Map fromString(String s) {
        final Date date;
        try {
            date = new Date(dateString); // yes, I know this is a deprecated method
        } catch(Exception e) {
            date = CRAZY_FORMAT.parse(dateString);
        }
    }
}

Ответ 2

Ответ Percepiton был очень полезен, но ParameterHandler устарел в Apache-cxf 3.0, см. Руководство по перенастройке Apache-cxf 3.0:

CXF JAX-RS ПараметрHandler был удален, используйте JAX-RS 2.0 ParamConverterProvider.

Итак, я добавляю пример с ParamConverterProvider:

public class DateParameterConverterProvider implements ParamConverterProvider {

    @Override
    public <T> ParamConverter<T> getConverter(Class<T> type, Type type1, Annotation[] antns) {
        if (Date.class.equals(type)) {
            @SuppressWarnings("unchecked")
            ParamConverter<T> paramConverter = (ParamConverter<T>) new DateParameterConverter();
            return paramConverter;
        }
        return null;
    }

}

public class DateParameterConverter implements ParamConverter<Date> {

    public static final String format = "yyyy-MM-dd"; // set the format to whatever you need

    @Override
    public Date fromString(String string) {
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat(format);
        try {
            return simpleDateFormat.parse(string);
        } catch (ParseException ex) {
            throw new WebApplicationException(ex);
        }
    }

    @Override
    public String toString(Date t) {
        return new SimpleDateFormat(format).format(t);
    }

}

В процессе компиляции требуется @SuppressWarnings, чтобы подавить предупреждение "непроверенные или небезопасные операции". См. Как отправить непроверенные предупреждения о броске для более подробной информации.

ParamConverterProvider может быть зарегистрирован как поставщик. Вот как я это сделал:

  <jaxrs:server id="myService" address="/rest">
      <jaxrs:serviceBeans>
           ...
      </jaxrs:serviceBeans>

      <jaxrs:providers>
          <ref bean="dateParameterConverterProvider" />
      </jaxrs:providers>
  </jaxrs:server>

  <bean id="dateParameterConverterProvider" class="myPackage.DateParameterConverterProvider"/>

Для получения дополнительной информации см. Apache-cxf JAX-RS: Конфигурация служб.

Ответ 3

Использование настраиваемого класса DateParam представляется наиболее безопасным. Затем вы можете основывать свои сигнатуры методов на этом и реализовывать уродливую логику преобразования внутри метода valueOf() или конструктора классов. Это также более самодокументируемо, чем использование простых строк

Ответ 4

Как @Perception предлагает во второй вариант, вы можете обрабатывать дату. Но вы должны использовать следующее:

private Date getDateFromString(String dateString) {
    try {
        DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
        Date date = df.parse(dateString);
        return date;
    } catch (ParseException e) {
        //WebApplicationException ...("Date format should be yyyy-MM-dd'T'HH:mm:ss", Status.BAD_REQUEST);
    }
}

Вы вызываете его из ресурса как

Date date = getDateFromString(dateString);//dateString is query param.