Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/369.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/visual-studio/8.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java Jackson和JAX-RS:基于@PathParam的类型解析抽象类型_Java_Jackson_Jax Rs - Fatal编程技术网

Java Jackson和JAX-RS:基于@PathParam的类型解析抽象类型

Java Jackson和JAX-RS:基于@PathParam的类型解析抽象类型,java,jackson,jax-rs,Java,Jackson,Jax Rs,假设Animal在我的项目中是一个抽象类,我有一个REST资源(在JAX-RS服务器上,使用Jackson进行(反)序列化),用于PUT操作存储在数据库中的动物。它们有具体的类型,REST资源在请求路径中指定类型: @PUT @Consumes(MediaType.APPLICATION_JSON) @Path("/{entityType}/{id: \\d+}") public <T extends Animal> void putAnimal(@PathParam("entity

假设
Animal
在我的项目中是一个抽象类,我有一个REST资源(在JAX-RS服务器上,使用Jackson进行(反)序列化),用于
PUT
操作存储在数据库中的动物。它们有具体的类型,REST资源在请求路径中指定类型:

@PUT
@Consumes(MediaType.APPLICATION_JSON)
@Path("/{entityType}/{id: \\d+}")
public <T extends Animal> void putAnimal(@PathParam("entityType") String entityType, @PathParam("id") String id, Animal input) throws IOException {
    //...
}
@PUT
@使用(MediaType.APPLICATION_JSON)
@路径(“/{entityType}/{id:\\d+}”)
public void putAnimal(@PathParam(“entityType”)字符串entityType,@PathParam(“id”)字符串id,动物输入)引发IOException{
//...
}
我想使用
entityType
来选择具体的类来进行反序列化(
Dog
Cat
或任何东西,因为
entityType
Dog
Cat
或任何东西)。由于此处难以解释的原因,我无法将类型信息放入JSON输入本身

因此,用自定义的
TypeIdResolver
或类似的东西来注释
Animal
对我没有帮助,因为类型信息不在JSON本身中(这就是类型解析程序将获得的所有信息)。我本来打算使用一个自定义的
MessageBodyReader
,但据我所知,它无法从其
readValue
方法中传递的body中获取其他参数值,因此我不知道反序列化成什么


我错过了什么?如果这种方法失败了,我如何在不指定特定于动物的端点的情况下实现我想要的目标(这会导致大量重复的代码以及通用性的丧失-现在我可以添加
animal
的一个子类,而此代码将正常工作,这非常好。)

以下引用自JAX-RS规范(5.2.2 URI和URI模板)建议您应该能够将
UriInfo
实例注入自定义
MessageBodyReader
,并使用其方法之一检查请求的URL路径

可以使用@Context An-notation将UriInfo的实例注入类字段或方法参数中。UriInfo提供了关于请求URI组件的静态和动态信息

这里提供的示例显示了一个接收
UriInfo
参数的资源方法,但通常也可以将实例注入提供者(
MessageBodyReader


在通过
UriInfo
获得
entityType
路径参数后,您的
MessageBodyReader
应该能够提供
Animal
的相应子类。鉴于您正试图做的事情,您最好构建一个
AnimalResource
类,其中包含您的基本方法和构建独立的
DogResource
CatResource
以及扩展
AnimalResource
所需的任何其他类。这将允许您获得
Animal
的正确子类,从而正确反序列化输入JSON

更新 这是如何实现的示例。您的基本资源如下所示:

public class AnimalResource<T extends Animal>
{
    private final transient AnimalService<T> service;

    public AnimalResource(final AnimalService<T> service)
    {
        this.service = service;
    }

    @Get
    @Path("{id}")
    @Produces(MediaType.APPLICATION_JSON)
    public T getbyId(@PathParam("id") final String id)
    {
        return this.service.findById(id);
    }

    // Other CRUD methods go here
}
公共类动物资源
{
私人临时动物服务;
公共动物资源(最终动物服务)
{
服务=服务;
}
@得到
@路径(“{id}”)
@产生(MediaType.APPLICATION_JSON)
公共T getbyId(@PathParam(“id”)最终字符串id)
{
返回此.service.findById(id);
}
//其他积垢方法也在这里
}
然后你的个体动物,假设它们都有相同的设置,简单地说:

@Path("/cats")
public class CatResource extends AnimalResource<Cat>
{
    public CatResource(final CatService catService)
    {
        super(catService);
    }
}
@Path(“/cats”)
公共类CatResource扩展了AnimalResource
{
公共CatResource(最终CatService CatService)
{
超级(有线电视服务);
}
}
为了一只猫和一只猫

@Path("/dogs")
public class DogResource extends AnimalResource<Dog>
{
    public DogResource(final DogService dogService)
    {
        super(dogService);
    }
}
@Path(“/dogs”)
公共类DogResource扩展了AnimalResource
{
公共狗资源(最终狗服务狗服务)
{
超级(狗服务);
}
}

对于狗来说。它们将从父母那里继承标准的CRUD方法,任何特定于动物的方法仍然可以放在单个
*资源
类中。

正如我在问题中已经说过的,这将导致重复代码和失去通用性。您也没有说明为什么我这样做比我目前的方法更好。这是这在项目中也不实用,因为我们基本上会在运行时添加动物。在运行时添加JAX-RS资源并不有趣。首先,如果您有具体的子类,那么就不会有重复的代码,但这不是您的主要问题。这取决于您如何创建子类(javassist?)您可以将它们与
ObjectMapper
一起使用,也可以不使用它们,但无论如何,您都应该考虑构建一个筛选器。筛选器可以访问完整的请求,决定类型,解析输入,并存储对象,以便您可以在资源中检索它。不过,这将是非常手动的……如果有具体的子类,AIUI你的方法将导致1-1个对应的资源类,除了对我来说构成重复代码的
s/cat/dog/
等,它们都是相同的。是的,手动性是我试图避免的。:-)这就是
AnimalResource
的来源,你有所有的基本方法,只需将其子类化为cat,狗,任何包含
@路径的东西。我会举一个简单的例子。好的,所以这里的
CatResource
DogResource
是完全重复的,除了
s/cat/dog/
,这是我试图避免的。经过测试,第一次工作完美无瑕。太棒了,非常感谢!