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. elasticserach数据库深度分页查询的原理

    深度分页存在的问题 https://segmentfault.com/a/1190000019004316?utm_source=tag-newest 在实际应用中,分页是必不可少的,例如,前端页面展 ...

  2. pxc搭建mysql集群

    docker -y update yum install -y docker service docker satrt docker images 服务器:curl -sSL https://get. ...

  3. 编译ts时候src目录的ts分别生成了单独的js文件

    { "compilerOptions": { "target": "es5", "outDir": "bin- ...

  4. git和github入门指南(6)

    6.交作业的流程 以下内容是螺钉课堂在线就业班提交作业的要求,非螺钉课堂在线就业班学员不用学习 螺钉课堂作业全程采用git管理,希望在日常使用中,加深对git和github的理解 具体流程: 1.注册 ...

  5. node+ajax实战案例(3)

    3.用户注册实现 3.1.注册用户功能的实现逻辑 1 用户在表单上输入注册信息 2 点击注册后,收集用户在表单上输入的注册信息并且发送给后台 3 后台接收用户发送过来的注册信息 4 后台需要处理数据并 ...

  6. Spring-AliasRegistry

    使用Spring 的时候我们可以很容易的为某个bean 配置一个或多个别名 <bean id="app:dataSource" class="..."&g ...

  7. STL初步学习(map)

    3.map map作为一个映射,有两个参数,第一个参数作为关键值,第二个参数为对应的值,关键值是唯一的 在平时使用的数组中,也有点类似于映射的方法,例如a[10]=1,但其实我们的关键值和对应的值只能 ...

  8. SecureCRT连接阿里云ECS服务器,经常掉线的解决方案

    1 使用SecureCRT远程连接后,Options > Session Options > Terminal(终端) > 勾选 “Send protocol NO-OP”

  9. 使用CodeMirror插件遇到的问题

    CodeMirror的正常使用: //首先通过<script>标签引入相应的js,这个就不必说了 var myCodeMirror = CodeMirror.fromTextArea(my ...

  10. java NIO 实例之多人聊天

    关键抽象 1.定义一个HashMap<String,SocketChannel>用户存储每个用户的管道. 2.服务端监听read事件,获取消息后轮询hashmap发送消息给用户模型内的所有 ...