【问题标题】:Request method 'GET' not supported after implementing PUT实现 PUT 后不支持请求方法“GET”
【发布时间】:2018-10-10 18:27:42
【问题描述】:

嗯,这是我在 * 上的第一个问题,所以我希望我能很好地解释我的问题 :-)

我正在使用 Spring Data Rest MongoDB。我正在使用一些仅通过实现 MongoRepository 就可用的“魔术”方法,但我也在使用自定义实现和 RestController。所以让我给你看一些代码:

我的存储库如下所示:

public interface BookRepository extends MongoRepository<Book, String>{
   //here are some methods that don't play a role here
}

现在我的前端由优秀的旧 AngularJS 制作,并在资源的自链接上调用一些神奇的 Spring Data Rest 方法,如 GET 和 PUT。但是现在我在调用 PUT 后需要一些服务器端日志记录。所以我决定为 PUT 做一些自己的实现——但不是为 GET。 PUT 工作正常,但不幸的是 GET 不再工作。我的日志中总是出现“不支持请求方法 'GET'”。

我的 RestController 现在看起来像这样:

@RepositoryRestController
@RequestMapping("/book/{mongoId}")
public class BookRestController {

    @Autowired
    private ResourceProcessor<Resource<Book>> bookResourceProcessor;

    @Autowired
    private BookRepository bookRepository;

    private static Logger LOG = 
        Logger.getLogger(BookRestController.class);


    @RequestMapping(method = RequestMethod.PUT,
        consumes = MediaType.APPLICATION_JSON_VALUE)
    public
    @ResponseBody
    ResponseEntity<Resource<Book>> updateBookAndLog(
        @RequestBody Book book,
        @PathVariable(value = "mongoId") String mongoId,
        @RequestHeader("MyApp-User") String userId,
        @RequestHeader("MyApp-Action") String action) {

        Book bookBeforeUpdate = bookRepository.findOne(mongoId);
        LOG.info("Log something");

        book.setMongoId(mongoId);
        Book responseBook = bookRepository.save(book);

        return ResponseEntity.ok(bookResourceProcessor.process(new 
           Resource<book>(responseBook)));
    }
}

这里是我前端的 GET 和 PUT 示例:

myApp.factory('Book', function($http, $q, ConfigurationHelper) {

    return {
       getById: function (bookId) {
          return $http.get('book/' + bookId);
       },

       save: function(book, userId, action) {
            return $http.put(book._links.self.href, book,
                {headers: {"MyApp-User": userId,
                        "MyApp-Action" : action}
                });
        }
    }

所以现在我的问题是:是因为 PUT 和 POST 使用相同的 URL(书籍资源的自链接) - 我必须为一个 URL 实现所有 HTTP 方法还是不实现?有什么我错过的吗?

【问题讨论】:

    标签: spring angular mongodb rest http


    【解决方案1】:

    每个端点都需要一个动词,因此需要一个 @RequestMapping(method = RequestMethod.GET) 方法来处理 GET 请求。

    另外,Spring 团队推荐constructor injection over @Autowired

    public BookRestController(ResourceProcessor<Resource<Book>> bookResourceProcessor, BookRepository bookRepository) {
      this.bookResourceProcessor = bookResourceProcessor;
      this.bookRepository = bookRepository;
    }
    

    【讨论】:

    • 感谢您的回答,只是想确保我们彼此理解正确:在我实施示例中的 PUT 方法之前,由于 RepositoryRestResource-Annotation,PUT 和 GET 工作(我忘了这个在我的示例中 - 我将添加它。)我只是想知道为什么 GET 现在不起作用,当我实现 PUT 时。所以你说的意思是我必须在实现其中一个动词后立即实现这两个动词?
    • 没有问题,您的 BookRestController 没有 GET 处理程序
    • 其实,如果不指定RequestMapping,同样的方法可以处理所有动词。当您专门添加 PUT 时,它不再是默认设置,因此您还需要指定 GET 以允许 GET 请求*.com/questions/38811606/…
    • 我知道没有 GET 处理程序。我想覆盖 PUT 但仍然有其他 HTTP 方法,如 spring data rest 自动公开它们。也许写过以下问题的人解释得更好:*.com/questions/36773171/…