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. linux网络编程-socket(36)

    进程是程序的一次动态执行的过程,进程是短暂的. 一个程序可以对应多个进程,可以打开多个记事本程序,存在多个进程. 线程是进程内部中的控制序列,一个进程至少有一个执行线路. 一个进程可以存在多个线程

  2. Python分支结构与流程控制

    Python分支结构与流程控制 分支结构 if 语句 分支结构在任何编程语言中都是至关重要的一环,它最主要的目的是让计算机拥有像人一样的思想,能在不同的情况下做出不同的应对方案,所以if语句不管是在什 ...

  3. Jmeter系列(31)- 获取并使用 JDBC Request 返回的数据

    如果你想从头学习Jmeter,可以看看这个系列的文章哦 https://www.cnblogs.com/poloyy/category/1746599.html 前言 Jmeter 使用 JDBC R ...

  4. springboot项目打war包发布到外置tomcat

    第一步:修改pom.xml 1. <version>0.0.1-SNAPSHOT</version> <packaging>war</packaging> ...

  5. CSS定位(Positioning)

    CSS 定位和浮动 CSS 为定位和浮动提供了一些属性,利用这些属性,可以建立列式布局,将布局的一部分与另一部分重叠,还可以完成多年来通常需要使用多个表格才能完成的任务. 一切皆为框 div.h1 或 ...

  6. iptables failed: iptables --wait -t nat -A DOCKER -p tcp -d 0/0 --dport 3306 -j DNAT --to-destination 172.17.0.2:3306 ! -i docker0: iptables: No chain/target/match by that name

    今天使用docker运行mysql时报错, 执行命令: docker run --restart=always --name mysql5.7 -p 3306:3306 -v /data/mysql/ ...

  7. vim 常用指令-持续更新

    1. 查询文件夹file1内文件数量:ls file1 | wc -l 2. 生成文件夹file1内的文件列表:find file1 -type f > list.txt 3. git管理文件, ...

  8. ORACLE数据库数据被修改或者删除恢复数据(闪回)

    1. SELECT * FROM CT_FIN_RiskItem  --先查询表,确定数据的确不对  (cfstatus 第一行缺少) 2. select * from CT_FIN_RiskItem ...

  9. win10 麦克风无法使用,可能是设置了权限

    驱动什么的都正常,平白无故麦克风不好用了,原来是之前自己设置了麦克风权限: 把这个开关打开就可以了. (完)

  10. python基础知识练习3

    1.如何实现 "1,2,3" 变成 ['1','2','3'] ? 如何实现['1','2','3']变成[1,2,3] ?(代码题) # 第一个问题 str1 = "1 ...