如何使用ModelAndView在RestController上实现REST API

时间:2019-06-06 22:21:25

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

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

我的控制器如下:

@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);
    }

2 个答案:

答案 0 :(得分:1)

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

答案 1 :(得分:1)

Internal Server Error: /parts/10/ Traceback (most recent call last): File "/home/anani/PycharmProjects/part_management_backend/venv/lib/python3.6/site-packages/django/db/backends/utils.py", line 84, in _execute return self.cursor.execute(sql, params) File "/home/anani/PycharmProjects/part_management_backend/venv/lib/python3.6/site-packages/django/db/backends/sqlite3/base.py", line 383, in execute return Database.Cursor.execute(self, query, params) sqlite3.IntegrityError: UNIQUE constraint failed: part_management_part.class_code_id, part_management_part.number The above exception was the direct cause of the following exception: Traceback (most recent call last): File "/home/anani/PycharmProjects/part_management_backend/venv/lib/python3.6/site-packages/django/core/handlers/exception.py", line 34, in inner response = get_response(request) File "/home/anani/PycharmProjects/part_management_backend/venv/lib/python3.6/site-packages/django/core/handlers/base.py", line 115, in _get_response response = self.process_exception_by_middleware(e, request) File "/home/anani/PycharmProjects/part_management_backend/venv/lib/python3.6/site-packages/django/core/handlers/base.py", line 113, in _get_response response = wrapped_callback(request, *callback_args, **callback_kwargs) File "/home/anani/PycharmProjects/part_management_backend/venv/lib/python3.6/site-packages/django/views/decorators/csrf.py", line 54, in wrapped_view return view_func(*args, **kwargs) File "/home/anani/PycharmProjects/part_management_backend/venv/lib/python3.6/site-packages/rest_framework/viewsets.py", line 116, in view return self.dispatch(request, *args, **kwargs) File "/home/anani/PycharmProjects/part_management_backend/venv/lib/python3.6/site-packages/rest_framework/views.py", line 495, in dispatch response = self.handle_exception(exc) File "/home/anani/PycharmProjects/part_management_backend/venv/lib/python3.6/site-packages/rest_framework/views.py", line 455, in handle_exception self.raise_uncaught_exception(exc) File "/home/anani/PycharmProjects/part_management_backend/venv/lib/python3.6/site-packages/rest_framework/views.py", line 492, in dispatch response = handler(request, *args, **kwargs) File "/home/anani/PycharmProjects/part_management_backend/venv/lib/python3.6/site-packages/rest_framework/mixins.py", line 84, in partial_update return self.update(request, *args, **kwargs) File "/home/anani/PycharmProjects/part_management_backend/venv/lib/python3.6/site-packages/rest_framework/mixins.py", line 70, in update self.perform_update(serializer) File "/home/anani/PycharmProjects/part_management_backend/venv/lib/python3.6/site-packages/rest_framework/mixins.py", line 80, in perform_update serializer.save() File "/home/anani/PycharmProjects/part_management_backend/venv/lib/python3.6/site-packages/rest_framework/serializers.py", line 209, in save self.instance = self.update(self.instance, validated_data) File "/home/anani/PycharmProjects/part_management_backend/part_management/serializers.py", line 55, in update instance.save() File "/home/anani/PycharmProjects/part_management_backend/venv/lib/python3.6/site-packages/django/db/models/base.py", line 741, in save force_update=force_update, update_fields=update_fields) File "/home/anani/PycharmProjects/part_management_backend/venv/lib/python3.6/site-packages/django/db/models/base.py", line 779, in save_base force_update, using, update_fields, File "/home/anani/PycharmProjects/part_management_backend/venv/lib/python3.6/site-packages/django/db/models/base.py", line 851, in _save_table forced_update) File "/home/anani/PycharmProjects/part_management_backend/venv/lib/python3.6/site-packages/django/db/models/base.py", line 900, in _do_update return filtered._update(values) > 0 File "/home/anani/PycharmProjects/part_management_backend/venv/lib/python3.6/site-packages/django/db/models/query.py", line 760, in _update return query.get_compiler(self.db).execute_sql(CURSOR) File "/home/anani/PycharmProjects/part_management_backend/venv/lib/python3.6/site-packages/django/db/models/sql/compiler.py", line 1429, in execute_sql cursor = super().execute_sql(result_type) File "/home/anani/PycharmProjects/part_management_backend/venv/lib/python3.6/site-packages/django/db/models/sql/compiler.py", line 1100, in execute_sql cursor.execute(sql, params) File "/home/anani/PycharmProjects/part_management_backend/venv/lib/python3.6/site-packages/django/db/backends/utils.py", line 99, in execute return super().execute(sql, params) File "/home/anani/PycharmProjects/part_management_backend/venv/lib/python3.6/site-packages/django/db/backends/utils.py", line 67, in execute return self._execute_with_wrappers(sql, params, many=False, executor=self._execute) File "/home/anani/PycharmProjects/part_management_backend/venv/lib/python3.6/site-packages/django/db/backends/utils.py", line 76, in _execute_with_wrappers return executor(sql, params, many, context) File "/home/anani/PycharmProjects/part_management_backend/venv/lib/python3.6/site-packages/django/db/backends/utils.py", line 84, in _execute return self.cursor.execute(sql, params) File "/home/anani/PycharmProjects/part_management_backend/venv/lib/python3.6/site-packages/django/db/utils.py", line 89, in __exit__ raise dj_exc_value.with_traceback(traceback) from exc_value File "/home/anani/PycharmProjects/part_management_backend/venv/lib/python3.6/site-packages/django/db/backends/utils.py", line 84, in _execute return self.cursor.execute(sql, params) File "/home/anani/PycharmProjects/part_management_backend/venv/lib/python3.6/site-packages/django/db/backends/sqlite3/base.py", line 383, in execute return Database.Cursor.execute(self, query, params) django.db.utils.IntegrityError: UNIQUE constraint failed: part_management_part.class_code_id, part_management_part.number [06/Jun/2019 23:37:04] "PATCH /parts/10/ HTTP/1.1" 500 22340 是编写@RestController@Controller的简写,只有在所有方法都返回一个应被视为响应主体的对象(例如JSON)时,才应使用它

如果要在同一控制器中同时合并REST端点和MVC端点,则可以使用@ResponseBody对其进行注释,并使用@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() { /* ... */ }
}