简体   繁体   English

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

[英]CXF JAXRS - How do I pass Date as QueryParam

I have a service defined as follows.我有一个定义如下的服务。

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

I'm trying to pass a java.util.Date to it from my client (which is jaxrs:client of CXF, not a generic HTTP client or browser).我正在尝试从我的客户端(它是 jaxrs: CXF 的客户端,而不是通用 HTTP 客户端或浏览器)传递一个java.util.Date给它。

My service receives the date as Thu Mar 01 22:33:10 IST 2012 in the HTTP URL.我的服务在 HTTP URL 中收到的日期为Thu Mar 01 22:33:10 IST 2012 Since CXF won't be able to create a Date object using this String, my client receives a 404 error.由于 CXF 将无法使用此字符串创建Date对象,因此我的客户端会收到 404 错误。 I tried using a ParameterHandler on the service side, but I still can't parse it successfully because I'm not expecting the date in any specific format.我尝试在服务端使用ParameterHandler ,但我仍然无法成功解析它,因为我不期望任何特定格式的日期。

As per this post , passing a Date is supposed to work out of the box, but I can't seem to get the basic case working.根据这篇文章,传递一个Date应该是开箱即用的,但我似乎无法让基本案例正常工作。 Am I required to do anything in order to successfully pass a Date object from my client to service?我是否需要做任何事情才能成功地将 Date 对象从我的客户端传递给服务? Appreciate any help.感谢任何帮助。

Thanks谢谢

The problem is that JAX-RS dictates that parameter unbundling be done in one of two ways:问题在于 JAX-RS 规定参数分拆以以下两种方式之一完成:

  1. The parameter bean has a public constructor that accepts a String参数 bean 有一个接受 String 的公共构造函数
  2. The parameter bean has a static valueOf(String) method.参数 bean 有一个静态valueOf(String)方法。

In your case, the Date is being unbundled via its Date(String) constructor, which cannot handle the input format your client is sending.在您的情况下, Date 是通过其Date(String)构造函数解绑的,该构造函数无法处理您的客户端发送的输入格式。 You have a couple options available to remedy this:您有几个选项可以解决这个问题:


Option 1选项1

Get your client to change the format of the date before they send it.让您的客户在发送日期之前更改日期格式。 This is the ideal, but probably the hardest to accomplish!这是理想的,但可能是最难实现的!


Option 2选项 2

Handle the crazy date format.处理疯狂的日期格式。 The options for this are:用于此的选项是:

Change your method signature to accept a string.更改您的方法签名以接受字符串。 Attempt to construct a Date object out of that and if that fails, use your own custom SimpleDateFormat class to parse it.尝试从中构造一个 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);
    }
}

Define your own parameter class that does the logic mentioned above.定义您自己的参数类来执行上述逻辑。 Give it a string constructor or static valueOf(String) method that invokes the logic.给它一个调用逻辑的字符串构造函数或静态valueOf(String)方法。 And an additional method to get the Date when all is said and done.还有一个额外的方法来在所有事情都说完后获取日期。

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();
}

Or finally, you can register a parameter handler for dates.或者最后,您可以为日期注册一个参数处理程序。 Where its logic is simply the same as mentioned for the other options above.它的逻辑与上面其他选项中提到的逻辑完全相同。 Note that you need to be using at least CXF 2.5.3 in order to have your parameter handler evaluated before it tries the default unbundling logic.请注意,您至少需要使用 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's answer was very useful, but ParameterHandler has been deprecated in Apache-cxf 3.0, see the Apache-cxf 3.0 Migration Guide : Percepiton 的回答非常有用,但ParameterHandler在 Apache-cxf 3.0 中已被弃用,请参阅Apache-cxf 3.0 迁移指南

CXF JAX-RS ParameterHandler has been dropped, please use JAX-RS 2.0 ParamConverterProvider. CXF JAX-RS ParameterHandler 已被删除,请使用 JAX-RS 2.0 ParamConverterProvider。

So I add an example with the 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);
    }

}

The @SuppressWarnings is required to suppress an "unchecked or unsafe operations" warning during compilation. @SuppressWarnings需要在编译期间抑制“未经检查或不安全的操作”警告。 See How do I address unchecked cast warnings for more details.有关更多详细信息,请参阅如何解决未经检查的强制转换警告

The ParamConverterProvider can be registred as provider. ParamConverterProvider可以注册为提供者。 Here is how I did it:这是我如何做到的:

  <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"/>

See Apache-cxf JAX-RS : Services Configuration for more information.有关更多信息,请参阅Apache-cxf JAX-RS:服务配置

Using a custom DateParam class seems the safest option.使用自定义 DateParam 类似乎是最安全的选择。 You can then base your method signatures on that and implement the ugly conversion logic inside the valueOf() method or the class constructor.然后,您可以基于该方法签名并在 valueOf() 方法或类构造函数中实现丑陋的转换逻辑。 It is also more self-documenting than using plain strings与使用普通字符串相比,它也更具自我记录性

As @Perception suggests in option two, you can handle the date.正如@Perception在选项二中建议的那样,您可以处理日期。 But you should use following:但你应该使用以下内容:

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);
    }
}

You call it from within the resource as你从资源中调用它作为

Date date = getDateFromString(dateString);//dateString is query param.

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM