我在spring引导中有两个java端点:
@PostMapping(path="/my-import-1")
@ResponseStatus(HttpStatus.OK)
public String myImport1(@Valid @RequestBody ParameterDto1 params) {
return this.serviceImpl.import(params);
}
和
@PostMapping(path="/my-import-2")
@ResponseStatus(HttpStatus.OK)
public String myImport2(@Valid @RequestBody ParameterDto2 params) {
return this.serviceImpl.import(params);
}
两者都使用相同的服务进行导入,但在参数上有一些不同。
我像这样创建了服务的导入方法
@Override
public String import(ParameterInterface params) throws Exception {
...
}
和这样的ParameterInterface
public interface ImportMetaData {
public default ArrayList<FileInterface> getFiles() {
return null;
}
public void setFiles(ArrayList<FileInterface> files);
}
为了实现这个接口,我创建了两个ParameterDto类(ParameterDto1和ParameterDto2)。IDE显示一切正常,我的服务也开始工作,但是一旦我向其中一个端点发送请求,我就会得到以下错误:
servlet .service()为servlet [dispatcherServlet]在上下文与路径[]抛出异常[请求处理失败;嵌套异常是org.springframework.http.converter.HttpMessageConversionException:类型定义错误:[简单类型,类。com.beo.services.myImportService.rest.domain.dto.metadata.interfaces.ParameterInerface];嵌套异常是com.fasterxml.jackson.databind.exc.InvalidDefinitionException:不能的构造实例
com.beo.services.myImportService.rest.domain.dto.metadata.interfaces.ParameterInerface
(不存在像默认构造函数一样的创建者):抽象类型需要映射到具体类型,具有自定义反序列化器,或者在[来源:(PushbackInputStream);行:3,列:5](通过引用链:com.beo.services.myImportService.rest.domain.dto.metadata.ParameterDto("files"→java.util.ArrayList [0])有根本原因
我能知道如何从接口创建这样一个数组列表并使这两个端点运行吗?还是有别的解决办法?
问题在于ParameterDto1和ParameterDto2。Jackson库需要一个默认的、无参数的构造函数,或者一个带@JsonProperty("field_name")
注释参数的构造函数,否则它不能转换你的消息。
解决方案:
为ParameterDto1和ParameterDto2添加一个无参数的构造函数或用@JsonProperty("field_name")
注释构造函数参数
我猜这里是因为您没有共享ParameterDto1
或ParameterDto2
的实现-并且由于某种原因,您的接口称为ImportMetaData
,其中根据例外,您的解释和其他文件应该是ParameterInterface
。
问题是getFiles/setFiles被jackson认为是一个属性,它的类型是一个接口,而你没有发送任何类型信息。
一般来说,假设ParameterDto1
和ParameterDto2
使用FileInterface
的具体实现,你可以改变你的接口方法getFiles
/setFiles
,这样他们就使用泛型参数,并在每个实现中设置你正在使用的FileInterface
的具体类型,这将允许jackson理解FileInterface
的具体类型。
如果ParameterDto1
和ParameterDto2
没有使用FileInterface
的具体实现,你应该添加@JsonTypeInfo
或@JsonSubTypes
(参见https://www.baeldung.com/jackson-annotations第5节了解更多信息)-注意,调用api的客户端也应该在json类型字段
建议实施
public interface ParameterInterface {
@JsonIgnore
public List<FileInterface> getParameters() default { return null;}
.....
}
public class ParameterDto1 implements ParameterInterface {
private List<FileImpl1> files;
public List<FileImpl1> getFiles(){return files;}
public void setFiles(List<FileImpl1> files){this.files=files;}
....
}
public class ParameterDto2 implements ParameterInterface {
private List<FileImpl2> files;
public List<FileImpl2> getFiles(){return files;}
public void setFiles(List<FileImpl2> files){this.files=files;}
...
}
public class FileImpl1 implements FileInterface{
...
}
public class FileImpl2 implements FileInterface{
...
}