CXF JAXRS - как передать дату как QueryParam - PullRequest
44 голосов
/ 01 марта 2012

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

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

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

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

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

Спасибо

Ответы [ 4 ]

56 голосов
/ 01 марта 2012

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

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

В вашем случае Date отделяется через конструктор 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);
        }
    }
}
13 голосов
/ 17 июля 2015

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

CXF JAX-RS ParameterHandler был удален, используйте 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: Конфигурация служб для получения дополнительной информации.

1 голос
/ 20 февраля 2014

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

0 голосов
/ 21 октября 2012

Как указывает @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.
...