CXF JAXRS - 如何将 Date 作为 QueryParam 传递

2022-08-31 17:36:00

我有一个定义如下的服务。

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

我试图从我的客户端(这是CXF的jaxrs:client,而不是通用的HTTP客户端或浏览器)传递给它。java.util.Date

我的服务接收的日期与 HTTP URL 中的日期相同。由于 CXF 将无法使用此字符串创建对象,因此我的客户端会收到 404 错误。我尝试在服务端使用 a,但我仍然无法成功解析它,因为我不期望任何特定格式的日期。Thu Mar 01 22:33:10 IST 2012DateParameterHandler

根据这篇文章,通过a应该是开箱即用的,但我似乎无法让基本案例工作。我是否需要执行任何操作才能成功地将 Date 对象从我的客户端传递到服务?感谢任何帮助。Date

谢谢


答案 1

问题在于 JAX-RS 规定参数解绑应通过以下两种方式之一完成:

  1. 参数 Bean 具有接受字符串的公共构造函数
  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);
    }
}

定义您自己的参数类,以执行上述逻辑。为它指定一个调用逻辑的字符串构造函数或静态值Of(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的答案非常有用,但在Apache-cxf 3.0中已被弃用,请参阅Apache-cxf 3.0迁移指南ParameterHandler

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 :服务配置


推荐