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. 00【笔记】 Shiro登陆过滤提示信息

    Shiro登陆过滤 提示信息 package top.yangbuyi.system.shiro; import com.alibaba.fastjson.JSONObject; import org ...

  2. 这一次搞懂SpringBoot核心原理(自动配置、事件驱动、Condition)

    @ 目录 前言 正文 启动原理 事件驱动 自动配置原理 Condition注解原理 总结 前言 SpringBoot是Spring的包装,通过自动配置使得SpringBoot可以做到开箱即用,上手成本 ...

  3. hive sql 解析json

    在hive中会有很多数据是用json格式来存储的,而我们用数据的时候又必须要将json格式的数据解析成为正常的数据,今天我们就来聊聊hive中是如何解析json数据的. 下面这张表就是json格式的表 ...

  4. vim中设置tab的长度

  5. mssql 手工注入流程小结

    对于MSSQL的注入点,无外乎这三种权限:SA,DB_OENER,PUBLIC.SA(System Admin)权限我们可以直接执行命令,DB_OENER权限的话,我们可以找到WEB的路径,然后用备份 ...

  6. 每日一题 - 剑指 Offer 30. 包含min函数的栈

    题目信息 时间: 2019-06-24 题目链接:Leetcode tag:栈 难易程度:简单 题目描述: 定义栈的数据结构,请在该类型中实现一个能够得到栈的最小元素的 min 函数在该栈中,调用 m ...

  7. LESS 原理,一款css的预处理程序Less的使用

    ​Less一种动态样式语言,LESS将CSS赋予了动态语言的特性,如变量,继承,运算,函数...LESS 既可以在客户端上运行 (支持IE 6+, Webkit, Firefox),也可以借助Node ...

  8. 01.RabbitMQ简单使用

    官网地址:https://www.rabbitmq.com/getstarted.html RabbitMQ 优点: 数据处理异步执行: 应用之间解耦: 流量削峰 1.docker 安装 Rabbit ...

  9. CD题解(药水的选择)

    这道题显然是一个01背包加上记录路径的题目,要说这道题的原型就是N多年前的CD 本题主要考的就是对01背包的基础板子加上稍微一点点的码力,就可以A掉这个题了 废话不多说,上代码: #include&l ...

  10. NIVIDIA Tegra K1 QWT安装使用问题和解决办法

    在Linux系统下,Tegra K1(ARM体系),只有QtCreator的环境下,去安装Qwt6.1.0: 下载: 系统安装好之后,直接联网在系统自带的软件安装程序中搜索Qt,安装Qt5.2.1,之 ...