在Spring中将路径变量绑定到自定义的模型对象

33

我有一个代表我的请求的类,像这样:

class Venue {
    private String city;
    private String place;

    // Respective getters and setters.
}

我希望支持一个RESTful的URL来获取关于场馆的信息。所以我有一个像这样的控制器方法。

@RequestMapping(value = "/venue/{city}/{place}", method = "GET")
public String getVenueDetails(@PathVariable("city") String city, @PathVariable("place") String place, Model model) {
    // code
}

我能否在Spring中以某种方式将我的路径变量绑定到模型对象(在本例中为Venue),而不是获取每个单独的参数?

3个回答

47

Spring MVC提供了将请求参数和路径变量绑定到JavaBean的能力,这在您的情况下是Venue。例如:

@RequestMapping(value = "/venue/{city}/{place}", method = "GET")
public String getVenueDetails(Venue venue, Model model) {
    // venue object will be automatically populated with city and place
}

请注意,您的JavaBean必须具有cityplace属性才能正常工作。

有关更多信息,您可以查看spring-projects/spring-mvc-showcase中withParamGroup()示例


1
我从未想过甚至路径变量也可以自动放入bean中。有关此有趣行为的任何文档吗?它的正式名称是什么? - torez233
1
这个解决方案的奇怪之处在于,Spring会接受像/venue/{city}/{place}?city=foo&place=bar这样的URL,并绑定对象属性到查询参数而不是路径参数。如果有一种方法可以告诉Spring Boot这些只应该来自路径而不是查询参数,那就太好了。 - Shannon

3

您可以提供HandlerMethodArgumentResolver接口的实现。该接口主要用于以Spring无法解决的方式解决控制器方法中的参数(这基本上就是您试图做的事情)。您需要实现以下两个方法:

public boolean supportsParameter(MethodParameter mp) {
    ...
}

public Object resolveArgument(mp, mavc, nwr, wdbf) throws Exception {
    ...
}

您可以通过以下方式将您的实现注入到Spring上下文中:
<mvc:annotation-driven>
    <mvc:argument-resolvers>
        <bean class="com.path.ImplementationOfHandlerMethodArgumentResolver"/>
    </mvc:argument-resolvers>
</mvc:annotation-driven>

当Spring遇到无法解析的参数时,它将调用您的方法supportsParameter()来查看您的解析器是否可以解析该参数。如果您的方法返回true,则Spring将调用您的resolveArgument()方法来实际解析该参数。在此方法中,您可以访问NativeWebRequest对象,您可以使用它来获取超出contextPath的路径(在您的情况下,它将是:/venue/{city}/{place})。您可以解析请求路径并尝试获取城市/地点字符串以填充您的Venue对象。

3
根据Spring文档(http://static.springsource.org/spring/docs/3.2.3.RELEASE/spring-framework-reference/html/mvc.html#mvc-ann-requestmapping-uri-templates)所述,自动支持仅限于简单类型:

@PathVariable参数可以是任何简单类型,例如int、long、Date等。Spring会自动转换为适当的类型,如果无法转换则会抛出TypeMismatchException异常。

我没有尝试过@RequestParamModel的这种特定组合,但看起来您可以通过创建自定义的WebBindingInitializer来实现所需的实现,详见http://static.springsource.org/spring/docs/3.2.3.RELEASE/spring-framework-reference/html/mvc.html#mvc-ann-typeconversion
自定义类将可以访问 WebRequest,并返回一个填充了从该请求提取的数据的域对象。

我想,对于我的使用情况来说,这可能有点过头了。但还是谢谢你的建议。 - Senthil Babu

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接