Unable to find a constructor that takes a String param or a valueOf() or fromString() method

最近在做服务的dubbo-rest改造,在启动服务的时候遇到这个错。

2020-02-21 14:15:51,433 [main] ERROR org.springframework.boot.SpringApplication - Application startup failed
java.lang.RuntimeException: RESTEASY003875: Unable to find a constructor that takes a String param or a valueOf() or fromString() method for javax.ws.rs.QueryParam("roleList") on java.util.List com.xxx.uic.entity.req.UserRoleReq.roleList for basetype: com.xxx.uic.entity.req.RoleReq
at org.jboss.resteasy.core.StringParameterInjector.initialize(StringParameterInjector.java:220)
at org.jboss.resteasy.core.StringParameterInjector.<init>(StringParameterInjector.java:64)
at org.jboss.resteasy.core.QueryParamInjector.<init>(QueryParamInjector.java:30)
at org.jboss.resteasy.core.InjectorFactoryImpl.createParameterExtractor(InjectorFactoryImpl.java:165)
at org.jboss.resteasy.core.PropertyInjectorImpl.getParameterExtractor(PropertyInjectorImpl.java:118)
at org.jboss.resteasy.core.PropertyInjectorImpl.populateMap(PropertyInjectorImpl.java:66)
at org.jboss.resteasy.core.PropertyInjectorImpl.<init>(PropertyInjectorImpl.java:54)
at org.jboss.resteasy.core.InjectorFactoryImpl.createPropertyInjector(InjectorFactoryImpl.java:65)
at org.jboss.resteasy.core.FormInjector.<init>(FormInjector.java:37)
at org.jboss.resteasy.core.InjectorFactoryImpl.createParameterExtractor(InjectorFactoryImpl.java:119)
at org.jboss.resteasy.core.MethodInjectorImpl.<init>(MethodInjectorImpl.java:44)
at org.jboss.resteasy.core.InjectorFactoryImpl.createMethodInjector(InjectorFactoryImpl.java:77)
at org.jboss.resteasy.core.ResourceMethodInvoker.<init>(ResourceMethodInvoker.java:99)
at org.jboss.resteasy.core.ResourceMethodRegistry.processMethod(ResourceMethodRegistry.java:281)
at org.jboss.resteasy.core.ResourceMethodRegistry.register(ResourceMethodRegistry.java:252)
at org.jboss.resteasy.core.ResourceMethodRegistry.addResourceFactory(ResourceMethodRegistry.java:222)
at org.jboss.resteasy.core.ResourceMethodRegistry.addResourceFactory(ResourceMethodRegistry.java:194)
at org.jboss.resteasy.core.ResourceMethodRegistry.addResourceFactory(ResourceMethodRegistry.java:180)
at com.alibaba.dubbo.rpc.protocol.rest.BaseRestServer.deploy(BaseRestServer.java:46)
....

大意就是我的@QueryParam注解下的参数没有使用String参数的构造方法,也没有对应的valueOf()和fromString(),所以这里是没法反序列化的。

    @QueryParam("roleList")
List<RoleReq> roleList;

如果深究这里的原因,需要查看resteasy里面的部分源码。

//String参数注入器 初始化方法
protected void initialize(Class type, Type genericType, String paramName, Class paramType, String defaultValue, AccessibleObject target, Annotation[] annotations, ResteasyProviderFactory factory)
{
this.type = type;
this.paramName = paramName;
this.paramType = paramType;
this.defaultValue = defaultValue;
this.target = target;
baseType = type;
baseGenericType = genericType;
//对集合类型进行判断
if (type.isArray()) baseType = type.getComponentType();
if (List.class.isAssignableFrom(type))
{
isCollection = true;
collectionType = ArrayList.class;
}
else if (SortedSet.class.isAssignableFrom(type))
{
isCollection = true;
collectionType = TreeSet.class;
}
else if (Set.class.isAssignableFrom(type))
{
isCollection = true;
collectionType = HashSet.class;
}
if (isCollection)
{
//如果是集合类型,取集合内成员的类型
if (genericType != null && genericType instanceof ParameterizedType)
{
ParameterizedType zType = (ParameterizedType) genericType;
baseType = Types.getRawType(zType.getActualTypeArguments()[0]);
baseGenericType = zType.getActualTypeArguments()[0];
}
else
{
baseType = String.class;
baseGenericType = null;
}
}
if (!baseType.isPrimitive())
{
//如果注入对象类型为非基础类型,尝试拿到参数的转换器
paramConverter = factory.getParamConverter(baseType, baseGenericType, annotations);
if (paramConverter != null) return;
//尝试获取解析器
unmarshaller = factory.createStringParameterUnmarshaller(baseType);
if (unmarshaller != null)
{
unmarshaller.setAnnotations(annotations);
return;
} for (Annotation annotation : annotations)
{
StringParameterUnmarshallerBinder binder = annotation.annotationType().getAnnotation(StringParameterUnmarshallerBinder.class);
if (binder != null)
{
try
{
unmarshaller = binder.value().newInstance();
}
catch (InstantiationException e)
{
throw new RuntimeException(e.getCause());
}
catch (IllegalAccessException e)
{
throw new RuntimeException(e);
}
factory.injectProperties(unmarshaller);
unmarshaller.setAnnotations(annotations);
return;
}
}
//尝试获取String的转换器
converter = factory.getStringConverter(baseType);
if (converter != null) return; if (paramType.equals(HeaderParam.class))
{
delegate = factory.getHeaderDelegate(baseType);
if (delegate != null) return;
} try
{
constructor = baseType.getConstructor(String.class);
if (!Modifier.isPublic(constructor.getModifiers())) constructor = null;
}
catch (NoSuchMethodException ignored)
{ }
if (constructor == null)
{
try
{
// this is for JAXB generated enums.
Method fromValue = baseType.getDeclaredMethod("fromValue", String.class);
if (Modifier.isPublic(fromValue.getModifiers()))
{
for (Annotation ann : baseType.getAnnotations())
{
if (ann.annotationType().getName().equals("javax.xml.bind.annotation.XmlEnum"))
{
valueOf = fromValue;
}
}
}
}
catch (NoSuchMethodException e)
{
}
//以上转换方式都没有,尝试使用方法名匹配,使用fromString和valueOf去匹配方法
if (valueOf == null)
{
Method fromString = null; try
{
fromString = baseType.getDeclaredMethod("fromString", String.class);
if (Modifier.isStatic(fromString.getModifiers()) == false) fromString = null;
}
catch (NoSuchMethodException ignored)
{
}
try
{
valueOf = baseType.getDeclaredMethod("valueOf", String.class);
if (Modifier.isStatic(valueOf.getModifiers()) == false) valueOf = null;
}
catch (NoSuchMethodException ignored)
{
}
// If enum use fromString if it exists: as defined in JAX-RS spec
if (baseType.isEnum())
{
if (fromString != null)
{
valueOf = fromString;
}
}
else if (valueOf == null)
{
valueOf = fromString;
}
if (valueOf == null)
{
//如果还是没有则抛出上面的异常
throw new
RuntimeException(Messages.MESSAGES.unableToFindConstructor(getParamSignature(), target, baseType.getName()));
}
} }
}
}

为了解决这个问题,我对RoleReq类增加了valueof(String)的方法来实现String反序列化成我需要的bean。

    public static RoleReq valueOf(String string){
return JSONObject.parseObject(string,RoleReq.class);
}

由于时间仓促这一块没有去仔细思考这种改法有没有问题或者有没有更好的改法,后续有时间会对本文进行更新。

Unable to find a constructor that takes a String param or a valueOf() or fromString() method的更多相关文章

  1. C# "error CS1729: 'XXClass' does not contain a constructor that takes 0 arguments"的解决方案

    出现这种错误的原因时,没有在子类的构造函数中指出仅有带参构造函数的父类的构造参数. 具体来讲就是: 当子类要重用父类的构造函数时, C# 语法通常会在子类构造函数后面调用 : base( para_t ...

  2. Unable to locate appropriate constructor on class异常

    一般出现Unable to locate appropriate constructor on class这个异常,都是实体类的带参数的构造方法和使用查询语句出现偏差,两个地方的代码如下: 一般都是第 ...

  3. 【Hibernate】Unable to locate appropriate constructor on class原因分析

    通常我们喜欢将hql查询结果封装到POJO对象syntax:select new POJO(id,name) from POJO ; 这种封装需要POJO类提供对应构造器,POJO(id,name)构 ...

  4. Unable to find a constructor to use for type System.Security.Claims.Claim. A class should either have a default constructor

    Newtonsoft.Json DeserializeObject 反序列化  IdentityServer4.Models Cliecnt 错误: Newtonsoft.Json.JsonSeria ...

  5. Unable to locate appropriate constructor on class报错

    在项目开发中,使用Hibernate里的JPA criteria查询,但是在写完之后使用时,会报错:Unable to locate appropriate constructor on class, ...

  6. Base class does not contain a constructor that takes '0' argument

    刚刚在写一段直播室网站中的一段程序遇,突然遇到一个错误,如下 'TVLLKBLL.BaseClass' does not contain a constructor that takes 0 argu ...

  7. Hibernate异常:Unable to locate appropriate constructor on class

    异常信息:org.hibernate.hql.ast.QuerySyntaxException: Unable to locate appropriate constructor on class o ...

  8. 出现Unable to locate appropriate constructor on class 错误可能的原因

    1)参数构造器的参数类型是否正确2)参数构造器的顺序和hql中的顺序是否一致3)参数构造器的参数个数是否和hql中的个数一致4)参数构造器的参数类型是否TimeStamp

  9. C# does not contain a constructor that takes no parameter

    C# 中子类要重用父类的构造函数时, 一般会在子类构造函数后面调用 : base(paratype, para). 如果父类有一个參数个数为1的构造函数, 没有 0 參构造函数. 子类想要重用这个构造 ...

随机推荐

  1. 01-最大子列和问题(java)

    问题描述:给定N个整数的序列{A1,A2,A3,…,An},求解子列和中最大的值. 这里我们给出{-2,11,-4,13,-5,-2}这样一个序列,正确的最大子列和为20 该题是在数据结构与算法中经常 ...

  2. Nginx基本知识,nginx安装使用方法

    Nginx 是一款高性能的Web服务器软件. - 具有极高的并发性能 - 利用Nginx与Tomcat组合使用, 搭建反向代理集群 - Nginx 反向代理集群可以解决网站的高并发问题! 1.安装 Y ...

  3. MongoDB入门二

    MongoDB配置 本地启动 c:\MongoDB\bin>mongod.exe --dbpath "C:\\MongoDB\data\db" --logpath " ...

  4. 使用docker创建redis容器

    1.拉取redis镜像

  5. HDU 5969 最大的位或【贪心】

    题目 B君和G君聊天的时候想到了如下的问题. 给定自然数l和r ,选取2个整数x,y满足l <= x <= y <= r ,使得x|y最大. 其中|表示按位或,即C. C++. Ja ...

  6. Spring Boot + Vue + Shiro 实现前后端分离、权限控制

    本文总结自实习中对项目的重构.原先项目采用Springboot+freemarker模版,开发过程中觉得前端逻辑写的实在恶心,后端Controller层还必须返回Freemarker模版的ModelA ...

  7. 09 . Kubernetes之pv、pvc及使用nfs网络存储应用

    PV,PVC概述 PV的全称是: PersistentVolume (持久化卷),是对底层的共享存储的一种抽象,PV由管理员进行创建和配置,它和具体的底层的共享存储技术的实现方式有关,比如Ceph.G ...

  8. less的使用几个技巧

    1.层级关系 让这个box范围内的全部包进来,这样的话就完美的进行调节,再也不用到处找第几行第几个,我刚才在哪个位置给覆盖了.一看便知! .box{ width: 100%; height: 300p ...

  9. VSCode 配 uni-app

    CLI工程 全局安装vue-cli npm install -g @vue/cli 通过cli创建uni-app项目 vue create -p dcloudio/uni-preset-vue uni ...

  10. CSRF原理及防御

    CSRF原理及防御 CSRF攻击原理 CSRF攻击利用网站对用户的信任,以用户的身份发送请求来执行攻击者所要的操作,比如:转账.发邮件.修改密码.添加用户等. CSRF和XSS一样危害都特别大,只不过 ...