所以我想在jax-rs:
中创建自定义ParamConverter<Integer>
public class IntParamConverter implements ParamConverter<Integer>{
@Override
public Integer fromString(String value) {
try{
return Integer.valueOf(value);
}catch (Exception e){
//do some stuff
throw new BadRequestEx("Convert Exception");
}
}
@Override
public String toString(Integer value) {
return String.valueOf(value);
}
}
然后我通过ParamConverterProvider注册它:
@Provider
public class CustomParamConverterHandler implements ParamConverterProvider {
@Override
public <T> ParamConverter<T> getConverter(final Class<T> rawType, Type genericType, Annotation[] annotations) {
if (rawType.equals(Integer.class)){
return (ParamConverter<T>) new IntParamConverter();
}
return null;
}
}
然后在资源POJO中使用它,如下所示:
@GET
@Path("/conv")
@Produces({MediaType.TEXT_PLAIN})
public String conv(@QueryParam("no") int no) {
return ""+no;
}
在运行时(使用system.out测试)我发现Tomee(Apache cfx?)不使用我的IntParamConverter
。如果我声明@QueryParam("no") Integer no
而不是@QueryParam("no") int no
,那么一切正常(tomee使用我的自定义paramConverter。
我尝试使用原始int注册我的IntParamConverter
:
if (rawType.equals(int.class)){
return (ParamConverter<T>) new IntParamConverter();
}
但随后会发生运行时异常:
java.lang.ClassCastException: Cannot cast java.lang.Integer to int
at java.lang.Class.cast(Class.java:3369)
at org.apache.cxf.jaxrs.utils.InjectionUtils.handleParameter(InjectionUtils.java:388)
at org.apache.cxf.jaxrs.utils.InjectionUtils.createParameterObject(InjectionUtils.java:978)
at org.apache.cxf.jaxrs.utils.JAXRSUtils.readQueryString(JAXRSUtils.java:1210)
如何创建这样一个处理原始int的ParamConverter?
答案 0 :(得分:2)
你不能。
Java泛型在编译时都被转换为java.lang.Object
(通过名为 type erasure 的进程)。
int
这样的原始类型没有java.lang.Object
作为基类,因此在这种情况下无法进行此类转换。
答案 1 :(得分:1)
我不肯肯定地说这是一个错误,但他们对InjectionUtils.handleParameter
的实施很奇怪。他们有以下
// [...]
Object result = null;
try {
result = createFromParameterHandler(value, pClass, genericType, paramAnns, message);
} catch (IllegalArgumentException nfe) {
throw createParamConversionException(pType, nfe);
}
从ParamConveter
获取价值。然后他们这样做
if (result != null) {
return pClass.cast(result);
}
// [...]
显然,cast
将被尝试并失败。但是没有理由像原始类型那样投射,反射的Method#invoke
会照顾到这一点。换句话说,您可以(并且必须)将Integer
值传递给Method#invoke
,运行时将负责为您转换它。
如果他们想要进行额外的验证,他们可以先检查目标类型是否是基本类型,然后进行相应的验证(检查您的值是否属于相应的包装类型)。对于其他类型,它们可以回退到cast
(因为方法返回类型是绑定到T
的通用pClass
)或使用类似isInstance
的内容。
我不会与开发者一起打开一张票,但是如此高使用率的库应该能够做到这一点。
如何创建这样一个处理原始int的ParamConverter?
你不能。 ParamConverter
是一个通用类,原语不适用于泛型。但是,图书馆应该支持为您进行最后的Integer
到int
转换,但似乎它没有。