Java CXF JAXRS-如何将日期作为QueryParam传递

Java CXF JAXRS-如何将日期作为QueryParam传递,java,rest,service,cxf,jax-rs,Java,Rest,Service,Cxf,Jax Rs,我有一个服务定义如下 公共字符串getData(@QueryParam(“日期”)date-date) 我试图从我的客户机(它是jaxrs:CXF的客户机,而不是通用的HTTP客户机或浏览器)向它传递一个java.util.Date 我的服务在HTTP URL中接收日期为2012年3月1日星期四22:33:10。由于CXF无法使用此字符串创建Date对象,因此我的客户端收到404错误。 我尝试在服务端使用ParameterHandler,但仍然无法成功解析它,因为我不希望使用任何特定格式的日期

我有一个服务定义如下

公共字符串getData(@QueryParam(“日期”)date-date)

我试图从我的客户机(它是jaxrs:CXF的客户机,而不是通用的HTTP客户机或浏览器)向它传递一个
java.util.Date

我的服务在HTTP URL中接收日期为2012年3月1日星期四22:33:10。由于CXF无法使用此字符串创建
Date
对象,因此我的客户端收到404错误。 我尝试在服务端使用
ParameterHandler
,但仍然无法成功解析它,因为我不希望使用任何特定格式的日期

根据,传递
日期
应该是开箱即用的,但我似乎无法让基本案例起作用。为了成功地将日期对象从我的客户机传递到服务,我是否需要执行任何操作?谢谢你的帮助


谢谢

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

  • 参数bean有一个接受字符串的公共构造函数
  • 参数bean有一个静态的
    valueOf(String)
    方法
  • 在您的情况下,日期通过其
    Date(String)
    构造函数进行拆分,该构造函数无法处理客户端发送的输入格式。您有几个选项可以解决此问题:


    选项1

    让您的客户在发送日期之前更改日期格式。这是理想的,但可能是最难实现的


    选项2

    处理疯狂的日期格式。这方面的选择包括:

    更改方法签名以接受字符串。尝试从中构造日期对象,如果失败,请使用您自己的自定义SimpleDataFormat类对其进行解析。

    定义执行上述逻辑的您自己的参数类。给它一个字符串构造函数或调用逻辑的静态
    valueOf(string)
    方法。还有一个额外的方法来获取所有事情都说了和做了的日期。

    或者,最后,您可以注册日期的参数处理程序。其逻辑与上面提到的其他选项完全相同。请注意,您至少需要使用CXF 2.5.3,以便在参数处理程序尝试默认拆分逻辑之前对其进行评估。

    公共类DateHandler实现ParameterHandler{
    公共映射fromString(字符串s){
    最后日期;
    试一试{
    date=newdate(dateString);//是的,我知道这是一个不推荐使用的方法
    }捕获(例外e){
    date=CRAZY\u FORMAT.parse(日期字符串);
    }
    }
    }
    
    正如
    @Perception
    在选项2中建议的那样,您可以处理日期。但您应该使用以下选项:

    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.
    

    使用自定义DateParam类似乎是最安全的选择。然后,您可以在此基础上创建方法签名,并在valueOf()方法或类构造函数中实现丑陋的转换逻辑。与使用普通字符串相比,它还具有更多的自文档功能

    非常有用,但在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);
        }
    
    }
    

    有关更多信息,请参阅。

    不确定您所说的
    是什么意思导致日期被发送为2012年3月1日星期四22:33:10
    ,因为您收到的是日期,而不是发送日期。在调用URL之前,请确保您正在调用的URL已正确编码。编辑此帖子以进行澄清。URL已正确编码。我的客户将日期参数作为2012年3月1日星期四22:33:10发送,我的服务也将按原样接收。但是,日期的格式无法解析(如果我使用ParameterHandler),或者CXF无法使用该格式直接创建日期对象。这让事情变得更清楚。这就引出了下一个问题——这种方法是否也能处理其他(更标准)格式的日期?实际上,我根本不关心日期格式。只要我能够传递
    日期
    对象,就足够了,内部使用的格式可以是任何格式。如果有帮助的话,我不介意在内部使用特定的格式(例如yyyyMMddHHmmSS)。实际上,我是为了更好地确定处理传入日期的解决方案而询问的。请看下面我的答案。Reg。选项#1:在这种情况下,我自己将客户机分发给用户,因此如果有帮助,我可以自由选择固定日期格式。但问题是,我到底该怎么做?什么决定了CXF客户端将使用哪种格式?我仍然将
    java.util.Date
    保留为
    QueryParam
    ,而不是更改为
    String
    或另一个
    DateParam
    类对象,以封装
    Date
    对象。只需传入任何可以由
    date(String)
    构造函数处理的日期格式。例如“12/20/2005 09:30:00+0100”(mm/dd/yyy HH:mm:ss Z)。我确实可以控制客户,但我在客户和服务端的签名都应该是
    日期
    。由于在客户端,CXF在构造查询参数时在我的
    Date
    对象上内部调用
    toString()?您是否建议延长
    Date
    并覆盖
    toString()
    (这意味着客户端签名将更改)?或者是否有其他机制可以在客户端和服务端使用来覆盖该行为?我猜
    MessageBodyReader/Wrtier
    仅用于请求正文。我最终使用了
    ParameterHand
    
    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.
    
    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);
        }
    
    }
    
      <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"/>