CXF JAXRS – 如何将Query作为QueryParam传递给Date
我有一个服务定义如下。
public String getData(@QueryParam("date") Date date)
我试图从我的客户端(这是CXF的jaxrs:客户端,而不是通用的HTTP客户端或浏览器)传递一个java.util.Date
到它。
我的服务在HTTP URL中收到date为Thu Mar 01 22:33:10 IST 2012
。 由于CXF将无法使用此string创buildDate
对象,因此我的客户端收到404错误。 我尝试在服务端使用ParameterHandler
,但我仍然无法成功parsing它,因为我不期望在任何特定格式的date。
根据这篇文章 ,传递Date
应该是开箱即用,但我似乎无法得到基本的情况下工作。 我是否需要做任何事情才能成功地将我的客户的Date对象传递给服务? 感谢任何帮助。
谢谢
问题是JAX-RS规定参数分拆可以通过以下两种方式之一来完成:
- 参数bean有一个接受String的公共构造函数
- 参数bean有一个静态的
valueOf(String)
方法。
在你的情况下,date是通过它的Date(String)
构造函数,它不能处理您的客户端发送input格式分拆。 你有几个选项可以解决这个问题:
选项1
让您的客户在发送之前更改date的格式。 这是理想的,但可能是最难完成的!
选项2
处理疯狂的date格式。 这个选项是:
改变你的方法签名接受一个string。 试图构造一个Date对象,如果失败了,使用你自己定制的SimpleDateFormat类来parsing它。
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); } }
定义你自己的参数类,做上面提到的逻辑。 给它一个调用逻辑的string构造函数或静态的valueOf(String)
方法。 还有一个额外的方法来获取date时,所有的说法和完成。
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(); }
最后,你可以注册一个date参数处理程序。 其逻辑与前面提到的其他选项一样。 请注意,您需要至less使用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的答案非常有用,但是在Apache-cxf 3.0中不推荐使用ParameterHandler
,请参阅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-RS:服务configuration 。
使用自定义的DateParam类似乎是最安全的select。 然后,您可以基于您的方法签名,并在valueOf()方法或类构造函数内部实现丑陋的转换逻辑。 这也比使用普通string更自我logging
正如@Perception
在选项二中所build议的,你可以处理date。 但是你应该使用以下内容:
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.