【问题标题】:How configure a RESTful controller in Spring 3 with annotations?如何在 Spring 3 中使用注释配置 RESTful 控制器?
【发布时间】: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 映射中使用了 /api/*。需要改为/

【问题讨论】:

  • 您可能想删除列表中的 value="/",创建方法。它可能会混淆 url 解析器。我注意到的另一件事是名称空间的问题。这些方法映射到“com.btmatthews.mars”,并且您收到“com.btmatthews.minerva”的错误
  • 取出 value="/" 没有任何区别,但是当我测试时,我看到注册了相同的 URL 映射,所以无论如何我都会删除它。门户组件的包名称是 com.btmatthews.mars...,但在它之上构建的应用程序打包在 com.btmatthews.minerva...中。它令人困惑但不是问题。
  • 我能看到的唯一可能是 DispatcherServlet 的 &lt;url-pattern&gt; 错误。对于这个配置,它应该是&lt;url-pattern&gt;/&lt;/url-pattern&gt;
  • 如果 axtavt 可以重新发布评论作为答案,然后您可以选择它作为正确答案,那就太好了。
  • 帮自己一个忙,使用出色的 spring-test-mvc 库 (github.com/SpringSource/spring-test-mvc) 对 Spring MVC 控制器进行单元测试,该库自 Spring 3.2 起就在 spring-test 中。

标签: java spring rest spring-mvc


【解决方案1】:

仔细检查 web.xml 中的 url-pattern 并将其与 curl 参数进行比较。

Here is an example我写的它会引导你完成整个 Spring MVC 过程。

【讨论】:

    【解决方案2】:

    您在 curl 摘录中发布的 URL

    http://localhost:8080/portal/api/portals
    

    与 Spring 警告中的 URL 不匹配

    /com.btmatthews.minerva.portal/api/portals
    

    如果不知道您的 web 应用程序是如何设置的、它位于什么上下文路径、Spring 上下文是什么样的等等,很难诊断,但这对我来说似乎是一个很大的线索。

    【讨论】:

    • 正确的上下文根是 /com.btmatthews.minerva.portal 而不是门户。我更新了原来的问题。
    【解决方案3】:

    你犯了一些错误。

    @RequestMapping(value = "/", method = RequestMethod.GET)
    
    public String listPortals(final Model model)
    {
    }
    

    这里的方法必须接受一些参数模型,但没有传递。 您必须在内部方法中编写该方法。或者如果你想传递它,你必须将它作为路径变量或请求参数发送。

    @RequestMapping(value = "/{id}", method = RequestMethod.GET)
    
    public String getPortal(@PathVariable("id") 
    

    这里正确的语法是@PathVariable(value="id")

    如果这不起作用 然后试试这个:

    @RequestMapping(value = "/SOMETHING", method = RequestMethod.GET)
    

    【讨论】:

    • 回答这么老的问题通常没有帮助,尤其是当问题已经用解决方案更新时。
    【解决方案4】:

    在 Spring 3 中,Rest Controller 只不过是一个常规控制器(@Component),唯一的区别是 Rest 控制器返回 JSON/XML 而不是“视图”。所以我认为你在注释方面做得很好。但是,我看不到两件事: 1-每种方法都需要有一个“生产”值(用于内容协商): @RequestMapping(value = "/{id}", method = RequestMethod.GET,produces = "application/json")

    2- 您需要某种类型的 ObjectMapper(例如:Marshaller 和 Unmarshaller)才能将对象映射到 JSON/XML,反之亦然。这两个应该在您的 servlet 配置中,而不是配置视图解析器。 应该就是这样。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-09-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-05-10
      • 1970-01-01
      • 2020-08-05
      • 2013-01-21
      相关资源
      最近更新 更多