【问题标题】:How to implement REST API on a RestController using ModelAndView如何使用 ModelAndView 在 RestController 上实现 REST API
【发布时间】:2019-10-22 10:57:56
【问题描述】:

当我的控制器中的方法返回 ModelAndView 时,我正在努力解决如何实现 API。我能找到的大多数教程都返回 ResponseEntities。我应该制作单独的 API 控制器来严格处理 /api 映射下的 API 调用吗? (我认为这不是 RESTFUL 做法)。或者是否可以在同一个控制器中处理我的 API 调用,即使使用 ModelAndView 也是如此?

我的控制器如下所示:

@RestController
@RequestMapping("/dish")
public class DishController {

    private final DishRepository dishRepository;

    public DishController(DishRepository dishRepository) {
        this.dishRepository = dishRepository;
    }

    @GetMapping
    public ModelAndView list() {
        Iterable<Dish> dishes = this.dishRepository.findAll();
        return new ModelAndView("dishes/list", "dishes", dishes);
    }

    @GetMapping("{id}")
    public ModelAndView view(@PathVariable("id") Dish dish) {
        return new ModelAndView("dishes/view", "dish", dish);
    }

    @GetMapping(params = "form")
    @PreAuthorize("hasRole('ROLE_ADMIN')")
    public String createForm(@ModelAttribute Dish dish) {
        return "dishes/form";
    }

    @ResponseStatus(HttpStatus.CREATED)
    @PostMapping
    @PreAuthorize("hasRole('ROLE_ADMIN')")
    public ModelAndView create(@Valid Dish dish, BindingResult result,
                               RedirectAttributes redirect) {
        if (result.hasErrors()) {
            return new ModelAndView("dishes/form", "formErrors", result.getAllErrors());
        }
        dish = this.dishRepository.save(dish);
        redirect.addFlashAttribute("globalMessage", "view.success");
        return new ModelAndView("redirect:/d/{dish.id}", "dish.id", dish.getId());
    }

    @RequestMapping("foo")
    public String foo() {
        throw new RuntimeException("Expected exception in controller");
    }

    @ResponseStatus(HttpStatus.OK)
    @GetMapping("delete/{id}")
    @PreAuthorize("hasRole('ROLE_ADMIN')")
    public ModelAndView delete(@PathVariable("id") Long id) {
        this.dishRepository.deleteById(id);
        Iterable<Dish> dishes = this.dishRepository.findAll();
        return new ModelAndView("dishes/list", "dishes", dishes);
    }

    @ResponseStatus(HttpStatus.OK)
    @GetMapping("/modify/{id}")
    @PreAuthorize("hasRole('ROLE_ADMIN')")
    public ModelAndView modifyForm(@PathVariable("id") Dish dish) {
        return new ModelAndView("dishes/form", "dish", dish);
    }

【问题讨论】:

  • 问题更多的是设计选择。

标签: spring rest api spring-boot spring-mvc


【解决方案1】:

@RestController 是写 @Controller@ResponseBody 的简写,只有在所有方法都返回一个应该被视为响应正文的对象(例如 JSON)时才应该使用它。

如果您想在同一个控制器中组合 REST 端点和 MVC 端点,您可以使用 @Controller 对其进行注释,并使用 @ResponseBody 单独注释每个方法。

例如:

@Controller // Use @Controller in stead of @RestController
@RequestMapping("/dish")
public class DishController {

    @GetMapping("/list")
    public ModelAndView list() { /* ... */ }

    @GetMapping
    @ResponseBody // Use @ResponseBody for REST API methods
    public List<Dish> findAll() { /* ... */ }
}

或者,正如您所提到的,您可以使用多个控制器:

@Controller
@RequestMapping("/dish")
public class DishViewController { /* ... */ }

@RestController
@RequestMapping("/api/dish")
public class DishAPIController { /* ... */ }

【讨论】:

  • 非常感谢您解决了很多问题!我想我会选择多个控制器
  • @Bram 听起来是个好主意。我通常还会将我的 API 控制器映射与我的 API 控制器映射分开。
【解决方案2】:

你不应该在 RestController 中使用 Model 和 View。 RestController 的主要目标是返回数据,而不是视图。在这里查看更多详细信息:Returning view from Spring MVC @RestController

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-08-12
    • 2014-06-10
    • 1970-01-01
    • 2013-03-07
    相关资源
    最近更新 更多