【问题标题】:Spring Data Rest controllers: behaviour and usage of @BasePathAwareController, @RepositoryRestController, @Controller and @RestControllerSpring Data Rest 控制器:@BasePathAwareController、@RepositoryRestController、@Controller 和 @RestController 的行为和使用
【发布时间】:2016-07-27 08:14:09
【问题描述】:

我正在尝试了解 Spring Data Rest Controller 的确切行为。

我做了一个简单的实现来测试 4 种带注释的控制器:@BasePathAwareController@RepositoryRestController@RestController@Controller

控制器在存储库中有一个实体“作者”的映射。

这是控制器:

@BasePathAwareController
//@RepositoryRestController
//@RestController
//@Controller
public class MyController {

    @RequestMapping(value="authors/mycontroller/test")
    public void handleRequest(){
        System.out.println("handleRequest of class MyController");
    }

    @RequestMapping(value="/authors/mycontroller/testslash")
    public void handleSlashRequest(){
        System.out.println("handleSlashRequest of class MyController");
    }

    @RequestMapping(value="api/authors/mycontroller/test")
    public void handleApiRequest(){
        System.out.println("handleApiRequest of class MyController");
    }

    @RequestMapping(value="/api/authors/mycontroller/testslash")
    public void handleSlashApiRequest(){
        System.out.println("handleSlashApiRequest of class MyController");
    }

}

我正在测试 4 种方法,因为我对要使用的正确映射有一些疑问。

对于每个实验,我都使用具有相同映射的不同控制器,只需取消该实验所需的注释即可。

我正在使用 HTTP GET 调用这两个 URL:

http://localhost:8080/myApp/api/mycontroller/test
http://localhost:8080/myApp/api/mycontroller/testslash

这是我使用@BasePathAwareController得到的结果:

http://localhost:8080/myApp/api/mycontroller/test
    White page, No errors, No print on console

http://localhost:8080/myApp/api/mycontroller/testslash
    White page, No errors, No print on console

这是使用@RepositoryRestController的结果:

http://localhost:8080/myApp/api/mycontroller/test
    White page, No errors, No print on console

http://localhost:8080/myApp/api/mycontroller/testslash
    White page, and this message on the console (only for the first HTTP GET on this url):
    jul 27, 2016 9:23:57 AM org.springframework.web.servlet.DispatcherServlet noHandlerFound
    WARNING: No mapping found for HTTP request with URI [/myApp/api/authors/mycontroller/testslash] in DispatcherServlet with name 'rest'

如果我使用@RestController,这就是结果:

http://localhost:8080/myApp/api/mycontroller/test
    White page, in console: "handleRequest of class MyController"

http://localhost:8080/myApp/api/mycontroller/testslash
    White page, in console: "handleSlashRequest of class MyController"

最后,这是使用@Controller的结果:

http://localhost:8080/myApp/api/mycontroller/test
    HTTP STATUS 404, in console: "handleRequest of class MyController"

http://localhost:8080/myApp/api/mycontroller/testslash
    HTTP STATUS 404, in console: "handleSlashRequest of class MyController"

For both urls I have this warning:

jul 27, 2016 9:28:11 AM org.springframework.web.servlet.DispatcherServlet noHandlerFound
WARNING: No mapping found for HTTP request with URI [/myApp/api/authors/mycontroller/authors/mycontroller/test] in DispatcherServlet with name 'rest'

我不明白发生了什么。

似乎提供预期结果的唯一注释是@RestController

@Controller 似乎可以正常工作,但我的 HTTP 状态为 404,并且有一条消息的 URL 不一致 /myApp/api/authors/mycontroller/authors/mycontroller/test,尽管有 控制台上的正确处理消息。

另外两个注解(@BasePathAwareController@RepositoryRestController)什么都不做。

总结:

  • @BasePathAwareController: 什么都不做
  • @RepositoryRestController: 什么都不做
  • @Controller: 奇怪的行为
  • @RestController:完美运行

非常感谢您对每种@Controller 的行为和用法进行任何类型的说明。

谢谢。

【问题讨论】:

    标签: spring spring-mvc spring-data-rest


    【解决方案1】:

    我已经找到了让所有带注释的控制器工作的方法,我在这里分享一下。

    @BasePathAwareController@RepositoryRestController 在班级级别必须有 @RequestMapping

    @RepositoryRestController
    //@BasePathAwareController
    @RequestMapping(value="/authors/mycontroller")
    public class MyController {
    
        @RequestMapping(value="/test")
        public void handleRequest(){
            //...
        }
    }
    

    如果没有类级别的映射,则不会处理两个控制器

    这就是原因,因为在我之前的测试中,这些方法从未被调用过。

    类级别的映射可以以“/”开头,也可以不以“/”开头,在这两种情况下都有效。

    此外,我注意到在配置上下文中添加<mvc:default-servlet-handler/>,警告“No mapping found for HTTP request with URI”消失了。

    【讨论】:

    • 请解释为什么文档说“此控制器 (@RepositoryRestController) 将从 RepositoryRestConfiguration.setBasePath 中定义的所有其他 RESTful 端点(例如 /api)使用的相同 API 基本路径提供服务”。并且代码 sn-p 在类级别上没有 @RequestMapping。 docs.spring.io/spring-data/rest/docs/3.0.1.RELEASE/reference/…(第 15.4 章)
    • 错了,它们将从复数域对象类或您在RepositoryRestResource(path=指定的路径中处理
    • 这可能取决于您使用的版本。用我当时用的版本,我就是这样解决的。
    • 我为此jira.spring.io/browse/DATAREST-1327开了一个spring-data-rest bug
    • 我认为 Spring Boot 2.5.6 "java.lang.IllegalStateException: Spring Data REST controller ... must not use @RequestMapping on class level 因为这会导致双重使用 Spring MVC 注册!”
    【解决方案2】:

    当您使用 REST API 时,您需要使用 @RestController

    如需进一步阅读,请查看spring docs

    【讨论】:

    • 感谢您的回答。但是在什么条件下应该使用其他的呢?
    • 我已经阅读了文档...如果我在这里,那是因为尽管文档中写了内容,但我得到了不同的结果。
    • 使用控制器部分覆盖 Spring 数据休息存储库时要小心。您不应该使用类级别映射。 jira.spring.io/browse/DATAREST-535
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-04-03
    • 2015-12-05
    • 1970-01-01
    • 2014-10-04
    • 1970-01-01
    • 2020-07-08
    相关资源
    最近更新 更多