Spring通用REST控制器:解析请求体

Ole*_*nyj 7 java generics rest spring json

我有以下控制器:

@RestController
@RequestMapping(value = "/{entity}", produces = MediaType.APPLICATION_JSON_VALUE)
public class CrudController<T extends SomeSuperEntity> {

    @RequestMapping(method = GET)
    public Iterable<T> findAll(@PathVariable String entity) {
    }

    @RequestMapping(value = "{id}", method = GET)
    public T findOne(@PathVariable String entity, @PathVariable String id) {
    }

    @RequestMapping(method = POST)
    public void save(@PathVariable String entity, @RequestBody T body) {
    }
}
Run Code Online (Sandbox Code Playgroud)

SomeSuperEntity 课程看起来像:

public abstract class SomeSuperEntity extends AbstractEntity {
    // some logic
}
Run Code Online (Sandbox Code Playgroud)

AbstractEntity它的抽象类的一些领域:

public abstract class AbstractEntity implements Comparable<AbstractEntity>, Serializable {

    private Timestamp firstField;
    private String secondField;

    public Timestamp getFirstField() {
        return firstField;
    }

    public void setFirstField(Timestamp firstField) {
        this.firstField = firstField;
    }

    public String getSecondField() {
        return secondField;
    }

    public void setSecondField(String secondField) {
        this.secondField = secondField;
    }
}
Run Code Online (Sandbox Code Playgroud)

所有子类SomeSuperEntity- 简单的JavaBeans.如果用findAll()findOne(id)方法 - 一切正常.我在服务层创建实体,它以JSON的形式返回客户端,所有字段都在子类和in中声明AbstractEntity.

但当我试图获取请求正文时save(entity, body),我得到以下错误:

无法读取文档:无法构造SomeSuperEntity的实例,问题:抽象类型需要映射到具体类型,具有自定义反序列化器,或者使用其他类型信息进行实例化

如果我删除摘要SomeSuperEntity,一切正常,但我请求身体我只得到那些声明的字段AbstractEntity.

这是我的问题,在我的案例中是否有针对此类问题的解决方法?如果没有,那么在没有任何结构变化的情况下,最佳解决方案会是什么(为每个实体制作子控制器不是一个选项)?将检索体作为纯文本是个好主意吗?或者它最好Map用于此?

我使用Spring v4.2.1和Jackson 2.6.3作为转换器.

有一些关于通用控制器的信息,但我找不到任何涵盖我的情况.所以,请在重复问题的情况下导航.

提前致谢.

UPD:目前其工作方式如下:我添加了额外的检查,MessageConverter并定义@RequestBodyString

@Override
    public Object read(Type type, Class<?> contextClass, HttpInputMessage inputMessage) throws IOException, HttpMessageNotReadableException {
        if (IGenericController.class.isAssignableFrom(contextClass)) {
            return CharStreams.toString(new InputStreamReader(inputMessage.getBody(), getCharset(inputMessage.getHeaders())));
        }
        return super.read(type, contextClass, inputMessage);
    }
Run Code Online (Sandbox Code Playgroud)

然后,在服务层,我定义接收的实体(在普通的json中)并转换它:

final EntityMetaData entityMetadata = getEntityMetadataByName(alias);
final T parsedEntity = getGlobalGson().fromJson(entity, entityMetadata.getEntityType());
Run Code Online (Sandbox Code Playgroud)

哪里EntityMetaDataenum与实体别名和类之间的关系定义.别名来了@PathVariable.

use*_*037 1

Spring真正看到的是:

public class CrudController {

    @RequestMapping(method = GET)
    public Iterable<Object> findAll(@PathVariable String entity) {
    }

    @RequestMapping(value = "{id}", method = GET)
    public Object findOne(@PathVariable String entity, @PathVariable String id)     {
    }

    @RequestMapping(method = POST)
    public void save(@PathVariable String entity, @RequestBody Object body) {
    }
}
Run Code Online (Sandbox Code Playgroud)

对于返回的对象并不重要,因为 Jackson 无论如何都会生成正确的 JSON 输出,但看起来 Spring 无法以相同的方式处理传入的对象。

您可以尝试仅用 SomeSuperEntity 替换泛型,并查看包含不同类型列表(但接口相同)的 Spring @RequestBody