加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > Java > 正文

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

发布时间:2020-12-15 00:35:26 所属栏目:Java 来源:网络整理
导读:我有以下控制器: @RestController@RequestMapping(value = "/{entity}",produces = MediaType.APPLICATION_JSON_VALUE)public class CrudControllerT extends SomeSuperEntity { @RequestMapping(method = GET) public IterableT findAll(@PathVariable Str
我有以下控制器:
@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) {
    }
}

SomeSuperEntity类看起来像:

public abstract class SomeSuperEntity extends AbstractEntity {
    // some logic
}

和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;
    }
}

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

但是当我试图在保存(实体,正文)中获取请求正文时,我得到以下错误:

Could not read document: Can not construct instance of
SomeSuperEntity,problem: abstract types either need to be mapped to
concrete types,have custom deserializer,or be instantiated with
additional type information

如果我从SomeSuperEntity中删除抽象,一切正常,但我请求正文我只得到那些在AbstractEntity中声明的字段.

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

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

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

提前致谢.

UPD:目前其工作如下:
我在MessageConverter中添加了额外的检查,并将@RequestBody定义为String

@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);
    }

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

final EntityMetaData entityMetadata = getEntityMetadataByName(alias);
final T parsedEntity = getGlobalGson().fromJson(entity,entityMetadata.getEntityType());

其中EntityMetaData是枚举,具有实体别名和类之间的已定义关系.别名来自@PathVariable.

解决方法

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) {
    }
}

对于返回的对象,没关系,因为Jackson无论如何都会生成输出正确的JSON,但看起来Spring无法以相同的方式处理传入的Object.

您可以尝试使用SomeSuperEntity替换泛型,并查看Spring @RequestBody containing a list of different types (but same interface)

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读