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

时间:2012-03-01 17:10:38

标签: java rest service cxf jax-rs

我的服务定义如下。

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

我正在尝试从我的客户端(它是jaxrs:CXF的客户端,而不是通用HTTP客户端或浏览器)传递java.util.Date

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

根据this post,传递Date应该是开箱即用的,但我似乎无法让基本案例正常工作。我是否需要做任何事情才能成功地将Date对象从我的客户端传递给服务?感谢任何帮助。

由于

4 个答案:

答案 0 :(得分:56)

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

  1. 参数bean有一个接受String
  2. 的公共构造函数
  3. 参数bean具有静态valueOf(String)方法。
  4. 在您的情况下,日期通过其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);
            }
        }
    }
    

答案 1 :(得分:13)

Percepiton's answer非常有用,但在Apache-cxf 3.0中已弃用ParameterHandler,请参阅Apache-cxf 3.0 Migration Guide

  

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需要禁止&#34;未经检查或不安全的操作&#34;编译期间的警告。有关详细信息,请参阅How do I address unchecked cast warnings

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 : Services Configuration

答案 2 :(得分:1)

使用自定义DateParam类似乎是最安全的选择。然后,您可以在其上建立方法签名,并在valueOf()方法或类构造函数中实现丑陋的转换逻辑。它比使用普通字符串更自我记录

答案 3 :(得分:0)

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