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 с помощью этой строки, Мой клиент получит ошибку 404.
Я попытался использовать ParameterHandler на стороне службы, но я все еще не могу разобрать его успешно, потому что я не ожидаю дату в любом конкретном случае. формат.



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



Спасибо

734   4  

4 ответов:

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

  1. параметр bean имеет открытый конструктор, который принимает строку
  2. параметр 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);
        }
    }
}

Percepiton ответ был очень полезным, но 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-РТС : услуги конфигурации для получения дополнительной информации.

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

Как предполагает @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.

Comments

    Ничего не найдено.