如何使用 ModelAndView 在 RestController 上实现 REST API
Posted
技术标签:
【中文标题】如何使用 ModelAndView 在 RestController 上实现 REST API【英文标题】:How to implement REST API on a RestController using ModelAndView 【发布时间】: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);
【问题讨论】:
问题更多的是设计选择。 【参考方案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。
【讨论】:
以上是关于如何使用 ModelAndView 在 RestController 上实现 REST API的主要内容,如果未能解决你的问题,请参考以下文章
什么时候在 Spring 中使用 ModelAndView 和 Model?
JAVA 如何获取modelandview的返回值,如果把一个对象放在map集合里(假如集合名字是