Spring MVC绑定在一个类型字段上

时间:2017-01-12 16:30:32

标签: java spring spring-mvc

我有一个像这样的Spring MVC控制器:

    @RequestMapping(value = "/search", method = RequestMethod.GET)
    @ResponseBody
    public Object grid(Search<MyFilter> search){
      ...
    }

我的搜索对象如下:

public class Search<F extends Filter> {
    private int offset;
    private int size;
    private F filter;

    //... getters/ setters
}

过滤器只是一个接口。 MyFilterFilter的实施,其中包含name, title等字段。

我正在使用:/search?offset=0&size=10&filter.name=john

对此控制器进行HTTP GET

但是春天无法实例化MyFilter。我试图让Filter成为普通的空类,并MyFilter来扩展它,但它也不可能。

是否可以弹出实例化正确的过滤器然后绑定值?

2 个答案:

答案 0 :(得分:2)

[TL; DR] 不,Spring不会从参数化类型中实例化MyFilter

当请求到达时,Search对象被实例化。 问题是,在运行时,有关类型参数化的信息将被删除并转换为最常规的类型。我的意思是在运行时,您的Search对象有效地看起来像:

class Search {

    /*
     * F is replaced by Filter since it is the most general type 
     * for <F extends Filter> parametrization. 
     * This will be the only Search class representation that compiler generates.
     */
    private Filter filter;

    //Rest of class body omitted
}

这是泛型的工作原理。 Sicne Filter是一个接口,对象映射器不知道如何解决它。您可以引导对象映射器如何基于另外的类型参数将Filter解析为特定类(我相信这种情况已被回答here)。但我不认为将其与仿制药混合是个好主意。这会导致复杂而混乱的代码。

您显然依赖MyFilter实施,因此您可以使用@DeezCashews建议的方法。或者你可以想到更灵活的解决方案。如果所有类型的Filter只是字段名称和所需值的容器,您可以执行以下操作:

public class Search {
    private int offset;
    private int size;
    private List<FieldPredicateTuple> filters;

    //getters and setters omitted
}

public class FieldPredicateTuple {
    String field;
    String value;

    //getters and setters omitted
}

然后调用端点:/search?offset=0&size=10&filters[0].field=name&filters[0].value=john

我不知道你想如何使用这些过滤器,所以我不知道该建议什么。但我建议以某种方式重新设计它。

答案 1 :(得分:1)

我知道这可能不是你正在寻找的东西但是如果你被困住或许考虑将共享变量提取到它自己的类中,然后将两个参数传递给你的网格方法而不是一个。 Spring Data有一个类似的Pageable类,所以你可以看一下它的灵感。然后你可以传递一个带有条件的bean和另一个带有offset和size的bean。例如:

ncol=5, byrow =F