【发布时间】:2010-02-19 02:01:17
【问题描述】:
我正在尝试使用Spring 3.0 创建一个RESTful 控制器。控制器用于门户应用程序的管理 API。我要执行的操作是:
- GET /api/portals 列出所有门户
- 发布 /api/portals 以创建新门户
- GET /api/portals/{id} 以检索现有门户
- PUT /api/portals/{id} 以更新现有门户
- DELETE /api/portal/{id} 删除现有门户
如下图所示注释控制器后,我发现列出所有门户或创建新门户的操作没有得到映射。
所以我的问题是:
- 我是否正确注释了类?
- 我是否遵循了实现 RESTful Web 服务的正确约定?
- 春天会不会有什么东西坏了?
下面的代码摘录显示了我是如何注释我的类的:
@Controller
@RequestMapping("/api/portals")
public final class PortalAPIController
{
private final static Logger LOGGER = LoggerFactory.getLogger(PortalAPIController.class);
@RequestMapping(value = "/", method = RequestMethod.GET)
public String listPortals(final Model model)
{
PortalAPIController.LOGGER.debug("Portal API: listPortals()");
.
.
return "portals";
}
@RequestMapping(value = "/", method = RequestMethod.POST)
public String createPortal(@RequestBody final MultiValueMap<String, String> portalData, final Model model)
{
PortalAPIController.LOGGER.debug("Portal API: createPortal()");
.
.
return "portal";
}
@RequestMapping(value = "/{id}", method = RequestMethod.GET)
public String getPortal(@PathVariable("id") final String portalId, final Model model, final HttpServletResponse response)
throws IOException
{
PortalAPIController.LOGGER.debug("Portal API: getPortal()");
.
.
return "portal";
}
@RequestMapping(value = "/{id}", method = RequestMethod.PUT)
public String updatePortal(@PathVariable("id") final String portalId,
@RequestBody final MultiValueMap<String, String> portalData, final Model model, final HttpServletResponse response)
throws IOException
{
PortalAPIController.LOGGER.debug("Portal API: updatePortal()");
.
.
return "portal";
}
@RequestMapping(value = "/{id}", method = RequestMethod.DELETE)
public String deletePortal(@PathVariable("id") final String portalId, final Model model, final HttpServletResponse response)
throws IOException
{
PortalAPIController.LOGGER.debug("Portal API: deletePortal()");
.
.
return "portal";
}
.
.
}
在启动期间,我看到 Spring 的东西已经注册了端点:
2010-02-19 01:18:41,733 INFO [org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping] - Mapped URL path [/api/portals/] onto handler [com.btmatthews.mars.portal.web.controller.PortalAPIController@141717f]
2010-02-19 01:18:41,734 INFO [org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping] - Mapped URL path [/api/portals/{id}] onto handler [com.btmatthews.mars.portal.web.controller.PortalAPIController@141717f]
2010-02-19 01:18:41,734 INFO [org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping] - Mapped URL path [/api/portals/{id}.*] onto handler [com.btmatthews.mars.portal.web.controller.PortalAPIController@141717f]
2010-02-19 01:18:41,735 INFO [org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping] - Mapped URL path [/api/portals/{id}/] onto handler [com.btmatthews.mars.portal.web.controller.PortalAPIController@141717f]
2010-02-19 01:18:41,735 INFO [org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping] - Mapped URL path [/api/portals] onto handler [com.btmatthews.mars.portal.web.controller.PortalAPIController@141717f]
2010-02-19 01:18:41,735 INFO [org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping] - Mapped URL path [/api/portals.*] onto handler [com.btmatthews.mars.portal.web.controller.PortalAPIController@141717f]
但是当我尝试使用 cURL 调用我的 API 时
curl http://localhost:8080/com.btmatthews.minerva.portal/api/portals/
或
curl http://localhost:8080/com.btmatthews.minerva.portal/api/portals
我收到以下错误:
2010-02-19 01:19:20,199 WARN [org.springframework.web.servlet.PageNotFound] - No mapping found for HTTP request with URI [/com.btmatthews.minerva.portal/api/portals] in DispatcherServlet with name 'portal'
2010-02-19 01:19:32,360 WARN [org.springframework.web.servlet.PageNotFound] - No mapping found for HTTP request with URI [/com.btmatthews.minerva.portal/api/portals/] in DispatcherServlet with name 'portal'
我在尝试创建时遇到了同样的问题:
curl -F ...... --request POST http://localhost:8080/com.btmatthtews.minerva/api/portals
但如果尝试对现有资源进行操作(检索、更新或删除),它可以正常工作。
更新:@axtavt 在评论中提供了解决方案。我在我的 web.xml servlet 映射中使用了
【问题讨论】:
-
您可能想删除列表中的 value="/",创建方法。它可能会混淆 url 解析器。我注意到的另一件事是名称空间的问题。这些方法映射到“com.btmatthews.mars”,并且您收到“com.btmatthews.minerva”的错误
-
取出 value="/" 没有任何区别,但是当我测试时,我看到注册了相同的 URL 映射,所以无论如何我都会删除它。门户组件的包名称是 com.btmatthews.mars...,但在它之上构建的应用程序打包在 com.btmatthews.minerva...中。它令人困惑但不是问题。
-
我能看到的唯一可能是 DispatcherServlet 的
<url-pattern>错误。对于这个配置,它应该是<url-pattern>/</url-pattern>。 -
如果 axtavt 可以重新发布评论作为答案,然后您可以选择它作为正确答案,那就太好了。
-
帮自己一个忙,使用出色的 spring-test-mvc 库 (github.com/SpringSource/spring-test-mvc) 对 Spring MVC 控制器进行单元测试,该库自 Spring 3.2 起就在 spring-test 中。
标签: java spring rest spring-mvc